torusguard 1.3.4 → 1.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (319) hide show
  1. package/.torusguard/.manifest.json +66 -63
  2. package/.torusguard/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +30 -14
  3. package/.torusguard/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +33 -16
  4. package/.torusguard/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +31 -15
  5. package/.torusguard/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +26 -16
  6. package/.torusguard/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +24 -16
  7. package/.torusguard/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +32 -18
  8. package/.torusguard/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +24 -17
  9. package/.torusguard/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +31 -18
  10. package/.torusguard/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +28 -17
  11. package/.torusguard/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +33 -17
  12. package/.torusguard/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +31 -16
  13. package/.torusguard/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +25 -16
  14. package/.torusguard/rules/secrets/TG-SEC-005-secret-in-git-history.md +24 -19
  15. package/.torusguard/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +36 -19
  16. package/.torusguard/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +21 -16
  17. package/.torusguard/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +45 -18
  18. package/.torusguard/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +20 -16
  19. package/.torusguard/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +28 -19
  20. package/.torusguard/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +25 -18
  21. package/.torusguard/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +29 -19
  22. package/.torusguard/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +23 -18
  23. package/.torusguard/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +23 -18
  24. package/.torusguard/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +36 -16
  25. package/.torusguard/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +26 -17
  26. package/.torusguard/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +30 -16
  27. package/.torusguard/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +25 -16
  28. package/.torusguard/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +28 -17
  29. package/.torusguard/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +31 -17
  30. package/.torusguard/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +31 -17
  31. package/.torusguard/rules_catalog.json +520 -0
  32. package/.torusguard/runs/report-latest.html +2700 -232
  33. package/.torusguard/runs/results-latest.sarif +20 -0
  34. package/.torusguard/runs/run-20260912-214110-audit/findings.json +1256 -0
  35. package/.torusguard/runs/run-20260912-214110-audit/findings.md +534 -0
  36. package/.torusguard/runs/run-20260912-214110-audit/manifest.json +12 -0
  37. package/.torusguard/runs/run-20260912-214110-audit/summary.md +5 -0
  38. package/.torusguard/runs/run-20260912-214813-audit/findings.json +992 -0
  39. package/.torusguard/runs/run-20260912-214813-audit/findings.md +422 -0
  40. package/.torusguard/runs/run-20260912-214813-audit/manifest.json +12 -0
  41. package/.torusguard/runs/run-20260912-214813-audit/summary.md +5 -0
  42. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-auth-003-49-7c96f3/metadata.json +17 -0
  43. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-auth-003-49-7c96f3/minimal_patch_plan.md +21 -0
  44. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-auth-003-49-7c96f3/patch.diff +9 -0
  45. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +17 -0
  46. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
  47. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
  48. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-platform-001-12-cf8156/metadata.json +17 -0
  49. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-platform-001-12-cf8156/minimal_patch_plan.md +21 -0
  50. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-platform-001-12-cf8156/patch.diff +9 -0
  51. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-rate-001-26-affcfa/metadata.json +17 -0
  52. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-rate-001-26-affcfa/minimal_patch_plan.md +21 -0
  53. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-rate-001-26-affcfa/patch.diff +9 -0
  54. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-sec-001-9-e22e50/metadata.json +17 -0
  55. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-sec-001-9-e22e50/minimal_patch_plan.md +21 -0
  56. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-sec-001-9-e22e50/patch.diff +9 -0
  57. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-ssrf-004-9-9803ad/metadata.json +17 -0
  58. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-ssrf-004-9-9803ad/minimal_patch_plan.md +21 -0
  59. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-ssrf-004-9-9803ad/patch.diff +9 -0
  60. package/.torusguard/runs/run-20260912-215555-audit/findings.json +530 -0
  61. package/.torusguard/runs/run-20260912-215555-audit/findings.md +232 -0
  62. package/.torusguard/runs/run-20260912-215555-audit/manifest.json +13 -0
  63. package/.torusguard/runs/run-20260912-215555-audit/remediation.md +102 -0
  64. package/.torusguard/runs/run-20260912-215555-audit/summary.md +5 -0
  65. package/.torusguard/runs/run-20260912-215731-audit/apply_plan.md +6 -0
  66. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/metadata.json +17 -0
  67. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/minimal_patch_plan.md +21 -0
  68. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/patch.diff +9 -0
  69. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-db-002-9-5f7850/metadata.json +17 -0
  70. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-db-002-9-5f7850/minimal_patch_plan.md +21 -0
  71. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-db-002-9-5f7850/patch.diff +9 -0
  72. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/metadata.json +17 -0
  73. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/minimal_patch_plan.md +22 -0
  74. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/patch.diff +10 -0
  75. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +17 -0
  76. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
  77. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
  78. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-001-12-cf8156/metadata.json +17 -0
  79. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-001-12-cf8156/minimal_patch_plan.md +21 -0
  80. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-001-12-cf8156/patch.diff +9 -0
  81. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-17-876973/metadata.json +17 -0
  82. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-17-876973/minimal_patch_plan.md +23 -0
  83. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-17-876973/patch.diff +11 -0
  84. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-5-40c794/metadata.json +17 -0
  85. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-5-40c794/minimal_patch_plan.md +23 -0
  86. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-5-40c794/patch.diff +11 -0
  87. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-001-26-affcfa/metadata.json +17 -0
  88. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-001-26-affcfa/minimal_patch_plan.md +21 -0
  89. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-001-26-affcfa/patch.diff +9 -0
  90. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-002-54-0b38d2/metadata.json +17 -0
  91. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-002-54-0b38d2/minimal_patch_plan.md +21 -0
  92. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-002-54-0b38d2/patch.diff +9 -0
  93. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-18-a3c1e8/metadata.json +17 -0
  94. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-18-a3c1e8/minimal_patch_plan.md +21 -0
  95. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-18-a3c1e8/patch.diff +9 -0
  96. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-9-e22e50/metadata.json +17 -0
  97. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-9-e22e50/minimal_patch_plan.md +21 -0
  98. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-9-e22e50/patch.diff +9 -0
  99. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-28-a1a0a1/metadata.json +17 -0
  100. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-28-a1a0a1/minimal_patch_plan.md +21 -0
  101. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-28-a1a0a1/patch.diff +9 -0
  102. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-30-00569e/metadata.json +17 -0
  103. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-30-00569e/minimal_patch_plan.md +21 -0
  104. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-30-00569e/patch.diff +9 -0
  105. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-ssrf-004-9-9803ad/metadata.json +17 -0
  106. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-ssrf-004-9-9803ad/minimal_patch_plan.md +21 -0
  107. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-ssrf-004-9-9803ad/patch.diff +9 -0
  108. package/.torusguard/runs/run-20260912-215731-audit/diff_summary.md +186 -0
  109. package/.torusguard/runs/run-20260912-215731-audit/findings.json +497 -0
  110. package/.torusguard/runs/run-20260912-215731-audit/findings.md +218 -0
  111. package/.torusguard/runs/run-20260912-215731-audit/manifest.json +14 -0
  112. package/.torusguard/runs/run-20260912-215731-audit/recheck.md +76 -0
  113. package/.torusguard/runs/run-20260912-215731-audit/remediation.md +234 -0
  114. package/.torusguard/runs/run-20260912-215731-audit/summary.md +5 -0
  115. package/.torusguard/runs/run-20260912-220134-audit/findings.json +68 -0
  116. package/.torusguard/runs/run-20260912-220134-audit/findings.md +36 -0
  117. package/.torusguard/runs/run-20260912-220134-audit/manifest.json +12 -0
  118. package/.torusguard/runs/run-20260912-220134-audit/summary.md +5 -0
  119. package/.torusguard/runs/run-20260912-220200-audit/findings.json +1 -0
  120. package/.torusguard/runs/run-20260912-220200-audit/findings.md +8 -0
  121. package/.torusguard/runs/run-20260912-220200-audit/manifest.json +12 -0
  122. package/.torusguard/runs/run-20260912-220200-audit/recheck.md +6 -0
  123. package/.torusguard/runs/run-20260912-220200-audit/summary.md +5 -0
  124. package/.torusguard/runs/run-20260912-220227-audit/findings.json +1 -0
  125. package/.torusguard/runs/run-20260912-220227-audit/findings.md +8 -0
  126. package/.torusguard/runs/run-20260912-220227-audit/manifest.json +12 -0
  127. package/.torusguard/runs/run-20260912-220227-audit/recheck.md +6 -0
  128. package/.torusguard/runs/run-20260912-220227-audit/summary.md +5 -0
  129. package/.torusguard/runs/run-20260918-104221-audit/findings.json +1 -0
  130. package/.torusguard/runs/run-20260918-104221-audit/findings.md +8 -0
  131. package/.torusguard/runs/run-20260918-104221-audit/manifest.json +12 -0
  132. package/.torusguard/runs/run-20260918-104221-audit/summary.md +5 -0
  133. package/.torusguard/runs/run-20260918-104236-audit/findings.json +2314 -0
  134. package/.torusguard/runs/run-20260918-104236-audit/findings.md +960 -0
  135. package/.torusguard/runs/run-20260918-104236-audit/manifest.json +12 -0
  136. package/.torusguard/runs/run-20260918-104236-audit/summary.md +5 -0
  137. package/.torusguard/runs/run-20260918-105723-audit/findings.json +2382 -0
  138. package/.torusguard/runs/run-20260918-105723-audit/findings.md +960 -0
  139. package/.torusguard/runs/run-20260918-105723-audit/manifest.json +12 -0
  140. package/.torusguard/runs/run-20260918-105723-audit/summary.md +5 -0
  141. package/.torusguard/runs/run-20260918-105731-audit/findings.json +1 -0
  142. package/.torusguard/runs/run-20260918-105731-audit/findings.md +8 -0
  143. package/.torusguard/runs/run-20260918-105731-audit/manifest.json +12 -0
  144. package/.torusguard/runs/run-20260918-105731-audit/summary.md +5 -0
  145. package/.torusguard/runs/run-20260918-105940-audit/findings.json +1 -0
  146. package/.torusguard/runs/run-20260918-105940-audit/findings.md +8 -0
  147. package/.torusguard/runs/run-20260918-105940-audit/manifest.json +12 -0
  148. package/.torusguard/runs/run-20260918-105940-audit/summary.md +5 -0
  149. package/.torusguard/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
  150. package/.torusguard/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
  151. package/.torusguard/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
  152. package/.torusguard/scripts/__pycache__/diff_guard.cpython-314.pyc +0 -0
  153. package/.torusguard/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
  154. package/.torusguard/scripts/__pycache__/finding_scorer.cpython-314.pyc +0 -0
  155. package/.torusguard/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
  156. package/.torusguard/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
  157. package/.torusguard/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
  158. package/.torusguard/scripts/__pycache__/memory_engine.cpython-314.pyc +0 -0
  159. package/.torusguard/scripts/__pycache__/monorepo_detector.cpython-314.pyc +0 -0
  160. package/.torusguard/scripts/__pycache__/recheck_runner.cpython-314.pyc +0 -0
  161. package/.torusguard/scripts/__pycache__/report_sync.cpython-311.pyc +0 -0
  162. package/.torusguard/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
  163. package/.torusguard/scripts/__pycache__/run_manager.cpython-314.pyc +0 -0
  164. package/.torusguard/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
  165. package/.torusguard/scripts/__pycache__/stack_detect.cpython-314.pyc +0 -0
  166. package/.torusguard/scripts/__pycache__/term_ui.cpython-311.pyc +0 -0
  167. package/.torusguard/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
  168. package/.torusguard/scripts/apply_runner.py +389 -377
  169. package/.torusguard/scripts/audit_runner.py +1513 -653
  170. package/.torusguard/scripts/finding_scorer.py +14 -2
  171. package/.torusguard/scripts/harden_runner.py +628 -455
  172. package/.torusguard/scripts/html_reporter.py +2668 -648
  173. package/.torusguard/scripts/recheck_runner.py +248 -238
  174. package/.torusguard/scripts/recipes_runner.py +137 -137
  175. package/.torusguard/scripts/report_sync.py +719 -0
  176. package/.torusguard/scripts/sarif_exporter.py +156 -116
  177. package/.torusguard/scripts/stack_detect.py +44 -2
  178. package/.torusguard/scripts/term_ui.py +162 -162
  179. package/.torusguard/skills/torusguard/SKILL.md +75 -72
  180. package/.torusguard/skills/torusguard-apply/SKILL.md +84 -80
  181. package/.torusguard/skills/torusguard-audit/SKILL.md +87 -83
  182. package/.torusguard/skills/torusguard-authorize/SKILL.md +7 -2
  183. package/.torusguard/skills/torusguard-exploit-check/SKILL.md +7 -2
  184. package/.torusguard/skills/torusguard-full/SKILL.md +7 -2
  185. package/.torusguard/skills/torusguard-harden/SKILL.md +98 -94
  186. package/.torusguard/skills/torusguard-init/SKILL.md +68 -64
  187. package/.torusguard/skills/torusguard-recheck/SKILL.md +81 -77
  188. package/.torusguard/skills/torusguard-report/SKILL.md +93 -72
  189. package/.torusguard/skills/torusguard-status/SKILL.md +62 -58
  190. package/.torusguard/skills/torusguard-verify/SKILL.md +7 -2
  191. package/.torusguard/skills/torusguard-web-validate/SKILL.md +7 -2
  192. package/.torusguard/snapshots/run-20260912-215731-audit/demo/playground/vulnerable_nextjs/actions.ts.bak +24 -0
  193. package/.torusguard/snapshots/run-20260912-215731-audit/examples/hardened-react-express/server/index.js.bak +121 -0
  194. package/.torusguard/snapshots/run-20260912-215731-audit/examples/python/fastapi-vuln/main.py.bak +20 -0
  195. package/.torusguard/snapshots/run-20260912-215731-audit/examples/vulnerable-react-express/client/src/App.jsx.bak +63 -0
  196. package/.torusguard/snapshots/run-20260912-215731-audit/examples/vulnerable-react-express/client/vite.config.js.bak +12 -0
  197. package/.torusguard/snapshots/run-20260912-215731-audit/examples/vulnerable-react-express/server/index.js.bak +82 -0
  198. package/.torusguard/workflows/apply.md +11 -4
  199. package/.torusguard/workflows/audit.md +7 -1
  200. package/.torusguard/workflows/authorize.md +2 -1
  201. package/.torusguard/workflows/exploit-check.md +2 -1
  202. package/.torusguard/workflows/harden.md +7 -1
  203. package/.torusguard/workflows/init.md +6 -1
  204. package/.torusguard/workflows/memory.md +2 -1
  205. package/.torusguard/workflows/recheck.md +7 -1
  206. package/.torusguard/workflows/report.md +7 -1
  207. package/.torusguard/workflows/status.md +6 -1
  208. package/.torusguard/workflows/verify.md +6 -1
  209. package/.torusguard/workflows/web-validate.md +2 -1
  210. package/README.md +476 -345
  211. package/bin/torusguard.js +586 -545
  212. package/package.json +1 -1
  213. package/skills/torusguard/SKILL.md +73 -72
  214. package/skills/torusguard/bootstrap.py +7 -2
  215. package/skills/torusguard/payload/.manifest.json +66 -63
  216. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +30 -14
  217. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +33 -16
  218. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +31 -15
  219. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +26 -16
  220. package/skills/torusguard/payload/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +24 -16
  221. package/skills/torusguard/payload/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +32 -18
  222. package/skills/torusguard/payload/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +24 -17
  223. package/skills/torusguard/payload/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +31 -18
  224. package/skills/torusguard/payload/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +28 -17
  225. package/skills/torusguard/payload/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +33 -17
  226. package/skills/torusguard/payload/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +31 -16
  227. package/skills/torusguard/payload/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +25 -16
  228. package/skills/torusguard/payload/rules/secrets/TG-SEC-005-secret-in-git-history.md +24 -19
  229. package/skills/torusguard/payload/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +36 -19
  230. package/skills/torusguard/payload/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +21 -16
  231. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +45 -18
  232. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +20 -16
  233. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +28 -19
  234. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +25 -18
  235. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +29 -19
  236. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +23 -18
  237. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +23 -18
  238. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +36 -16
  239. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +26 -17
  240. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +30 -16
  241. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +25 -16
  242. package/skills/torusguard/payload/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +28 -17
  243. package/skills/torusguard/payload/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +31 -17
  244. package/skills/torusguard/payload/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +31 -17
  245. package/skills/torusguard/payload/rules_catalog.json +520 -0
  246. package/skills/torusguard/payload/scripts/__pycache__/apply_runner.cpython-314.pyc +0 -0
  247. package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
  248. package/skills/torusguard/payload/scripts/__pycache__/audit_runner.cpython-314.pyc +0 -0
  249. package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-311.pyc +0 -0
  250. package/skills/torusguard/payload/scripts/__pycache__/diff_guard.cpython-314.pyc +0 -0
  251. package/skills/torusguard/payload/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
  252. package/skills/torusguard/payload/scripts/__pycache__/finding_scorer.cpython-314.pyc +0 -0
  253. package/skills/torusguard/payload/scripts/__pycache__/harden_runner.cpython-314.pyc +0 -0
  254. package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-311.pyc +0 -0
  255. package/skills/torusguard/payload/scripts/__pycache__/html_reporter.cpython-314.pyc +0 -0
  256. package/skills/torusguard/payload/scripts/__pycache__/manifest_builder.cpython-314.pyc +0 -0
  257. package/skills/torusguard/payload/scripts/__pycache__/memory_engine.cpython-311.pyc +0 -0
  258. package/skills/torusguard/payload/scripts/__pycache__/memory_engine.cpython-314.pyc +0 -0
  259. package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
  260. package/skills/torusguard/payload/scripts/__pycache__/monorepo_detector.cpython-314.pyc +0 -0
  261. package/skills/torusguard/payload/scripts/__pycache__/recheck_runner.cpython-314.pyc +0 -0
  262. package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-311.pyc +0 -0
  263. package/skills/torusguard/payload/scripts/__pycache__/report_sync.cpython-314.pyc +0 -0
  264. package/skills/torusguard/payload/scripts/__pycache__/rules_sync.cpython-311.pyc +0 -0
  265. package/skills/torusguard/payload/scripts/__pycache__/run_manager.cpython-311.pyc +0 -0
  266. package/skills/torusguard/payload/scripts/__pycache__/run_manager.cpython-314.pyc +0 -0
  267. package/skills/torusguard/payload/scripts/__pycache__/sarif_exporter.cpython-314.pyc +0 -0
  268. package/skills/torusguard/payload/scripts/__pycache__/stack_detect.cpython-311.pyc +0 -0
  269. package/skills/torusguard/payload/scripts/__pycache__/stack_detect.cpython-314.pyc +0 -0
  270. package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-311.pyc +0 -0
  271. package/skills/torusguard/payload/scripts/__pycache__/term_ui.cpython-314.pyc +0 -0
  272. package/skills/torusguard/payload/scripts/apply_runner.py +389 -377
  273. package/skills/torusguard/payload/scripts/audit_runner.py +1513 -653
  274. package/skills/torusguard/payload/scripts/finding_scorer.py +14 -2
  275. package/skills/torusguard/payload/scripts/harden_runner.py +628 -455
  276. package/skills/torusguard/payload/scripts/html_reporter.py +2668 -648
  277. package/skills/torusguard/payload/scripts/recheck_runner.py +248 -238
  278. package/skills/torusguard/payload/scripts/recipes_runner.py +137 -137
  279. package/skills/torusguard/payload/scripts/report_sync.py +719 -0
  280. package/skills/torusguard/payload/scripts/sarif_exporter.py +156 -116
  281. package/skills/torusguard/payload/scripts/stack_detect.py +44 -2
  282. package/skills/torusguard/payload/scripts/term_ui.py +162 -162
  283. package/skills/torusguard/payload/skills/torusguard/SKILL.md +75 -72
  284. package/skills/torusguard/payload/skills/torusguard-apply/SKILL.md +84 -80
  285. package/skills/torusguard/payload/skills/torusguard-audit/SKILL.md +87 -83
  286. package/skills/torusguard/payload/skills/torusguard-authorize/SKILL.md +7 -2
  287. package/skills/torusguard/payload/skills/torusguard-exploit-check/SKILL.md +7 -2
  288. package/skills/torusguard/payload/skills/torusguard-full/SKILL.md +7 -2
  289. package/skills/torusguard/payload/skills/torusguard-harden/SKILL.md +98 -94
  290. package/skills/torusguard/payload/skills/torusguard-init/SKILL.md +68 -64
  291. package/skills/torusguard/payload/skills/torusguard-recheck/SKILL.md +81 -77
  292. package/skills/torusguard/payload/skills/torusguard-report/SKILL.md +93 -72
  293. package/skills/torusguard/payload/skills/torusguard-status/SKILL.md +62 -58
  294. package/skills/torusguard/payload/skills/torusguard-verify/SKILL.md +7 -2
  295. package/skills/torusguard/payload/skills/torusguard-web-validate/SKILL.md +7 -2
  296. package/skills/torusguard/payload/workflows/apply.md +11 -4
  297. package/skills/torusguard/payload/workflows/audit.md +7 -1
  298. package/skills/torusguard/payload/workflows/authorize.md +2 -1
  299. package/skills/torusguard/payload/workflows/exploit-check.md +2 -1
  300. package/skills/torusguard/payload/workflows/harden.md +7 -1
  301. package/skills/torusguard/payload/workflows/init.md +6 -1
  302. package/skills/torusguard/payload/workflows/memory.md +2 -1
  303. package/skills/torusguard/payload/workflows/recheck.md +7 -1
  304. package/skills/torusguard/payload/workflows/report.md +7 -1
  305. package/skills/torusguard/payload/workflows/status.md +6 -1
  306. package/skills/torusguard/payload/workflows/verify.md +6 -1
  307. package/skills/torusguard/payload/workflows/web-validate.md +2 -1
  308. package/skills/torusguard-apply/SKILL.md +84 -80
  309. package/skills/torusguard-audit/SKILL.md +87 -83
  310. package/skills/torusguard-authorize/SKILL.md +7 -2
  311. package/skills/torusguard-exploit-check/SKILL.md +7 -2
  312. package/skills/torusguard-full/SKILL.md +7 -2
  313. package/skills/torusguard-harden/SKILL.md +98 -94
  314. package/skills/torusguard-init/SKILL.md +68 -64
  315. package/skills/torusguard-recheck/SKILL.md +81 -77
  316. package/skills/torusguard-report/SKILL.md +93 -72
  317. package/skills/torusguard-status/SKILL.md +62 -58
  318. package/skills/torusguard-verify/SKILL.md +7 -2
  319. package/skills/torusguard-web-validate/SKILL.md +7 -2
@@ -1,116 +1,156 @@
1
- #!/usr/bin/env python3
2
- """
3
- TorusGuard OASIS SARIF v2.1.0 Exporter
4
- Converts normalized TorusGuard findings into standard SARIF v2.1.0 format with
5
- GitHub Code Scanning multi-analysis category separation and partialFingerprints deduplication.
6
- """
7
-
8
- import sys
9
- import json
10
- import hashlib
11
- import argparse
12
- from typing import List, Dict, Any
13
-
14
- def generate_sarif(findings: List[Dict[str, Any]], run_id: str = "default", category: str = "torusguard/static") -> Dict[str, Any]:
15
- rules_map: Dict[str, Dict[str, Any]] = {}
16
- results: List[Dict[str, Any]] = []
17
-
18
- for f in findings:
19
- rule_id = f.get("rule_id", "TG-GEN-001")
20
- if rule_id not in rules_map:
21
- rules_map[rule_id] = {
22
- "id": rule_id,
23
- "name": f.get("title", rule_id),
24
- "shortDescription": {"text": f.get("title", rule_id)},
25
- "fullDescription": {"text": f.get("description", f.get("title", rule_id))},
26
- "defaultConfiguration": {
27
- "level": "error" if f.get("severity") in ("Critical", "High") else "warning"
28
- },
29
- "properties": {
30
- "tags": ["security", "torusguard", f.get("category", "general")]
31
- }
32
- }
33
-
34
- target = f.get("target", {})
35
- file_path = target.get("file_path", "unknown")
36
- line = target.get("start_line", 1)
37
-
38
- # Generate deduplication fingerprint
39
- seed = f"{rule_id}:{file_path}:{line}"
40
- line_hash = hashlib.sha256(seed.encode("utf-8")).hexdigest()[:16]
41
-
42
- result: Dict[str, Any] = {
43
- "ruleId": rule_id,
44
- "message": {"text": f.get("title", "TorusGuard Security Finding")},
45
- "level": "error" if f.get("severity") in ("Critical", "High") else "warning",
46
- "locations": [
47
- {
48
- "physicalLocation": {
49
- "artifactLocation": {
50
- "uri": file_path,
51
- "uriBaseId": "%SRCROOT%"
52
- },
53
- "region": {
54
- "startLine": line,
55
- "startColumn": 1
56
- }
57
- }
58
- }
59
- ],
60
- "partialFingerprints": {
61
- "primaryLocationLineHash": line_hash
62
- },
63
- "properties": {
64
- "confidence": f.get("confidence", 70),
65
- "status": f.get("status", "Confirmed"),
66
- "finding_id": f.get("finding_id", "TG-FIND-UNKNOWN")
67
- }
68
- }
69
- results.append(result)
70
-
71
- sarif = {
72
- "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
73
- "version": "2.1.0",
74
- "runs": [
75
- {
76
- "tool": {
77
- "driver": {
78
- "name": "TorusGuard",
79
- "semanticVersion": "0.8.0",
80
- "informationUri": "https://github.com/githubmofo/TorusGuard",
81
- "rules": list(rules_map.values())
82
- }
83
- },
84
- "automationDetails": {
85
- "id": f"{category}/{run_id}"
86
- },
87
- "results": results
88
- }
89
- ]
90
- }
91
- return sarif
92
-
93
-
94
- def main():
95
- parser = argparse.ArgumentParser(description="TorusGuard SARIF v2.1.0 Exporter")
96
- parser.add_argument("--input", "-i", help="Path to findings JSON file")
97
- parser.add_argument("--output", "-o", help="Output path for sarif.json")
98
- parser.add_argument("--run-id", default="run-default", help="Unique execution Run ID")
99
- args = parser.parse_args()
100
-
101
- findings = []
102
- if args.input:
103
- with open(args.input, "r", encoding="utf-8") as f:
104
- findings = json.load(f)
105
-
106
- sarif = generate_sarif(findings, run_id=args.run_id)
107
-
108
- if args.output:
109
- with open(args.output, "w", encoding="utf-8") as f:
110
- json.dump(sarif, f, indent=2)
111
- print(f"SARIF log written to: {args.output}")
112
- else:
113
- print(json.dumps(sarif, indent=2))
114
-
115
- if __name__ == "__main__":
116
- main()
1
+ #!/usr/bin/env python3
2
+ """
3
+ TorusGuard OASIS SARIF v2.1.0 Exporter
4
+ Converts normalized TorusGuard findings into standard SARIF v2.1.0 format with
5
+ GitHub Code Scanning multi-analysis category separation and partialFingerprints deduplication.
6
+ """
7
+
8
+ import sys
9
+ import json
10
+ import hashlib
11
+ import argparse
12
+ from pathlib import Path
13
+ from typing import List, Dict, Any
14
+
15
+ def generate_sarif(findings: List[Dict[str, Any]], run_id: str = "default", category: str = "torusguard/static") -> Dict[str, Any]:
16
+ rules_map: Dict[str, Dict[str, Any]] = {}
17
+ results: List[Dict[str, Any]] = []
18
+
19
+ for f in findings:
20
+ rule_id = f.get("rule_id", "TG-GEN-001")
21
+ if rule_id not in rules_map:
22
+ rules_map[rule_id] = {
23
+ "id": rule_id,
24
+ "name": f.get("title", rule_id),
25
+ "shortDescription": {"text": f.get("title", rule_id)},
26
+ "fullDescription": {"text": f.get("description", f.get("title", rule_id))},
27
+ "defaultConfiguration": {
28
+ "level": "error" if f.get("severity") in ("Critical", "High") else "warning"
29
+ },
30
+ "properties": {
31
+ "tags": ["security", "torusguard", f.get("category", "general")]
32
+ }
33
+ }
34
+
35
+ target = f.get("target", {})
36
+ file_path = target.get("file_path", "unknown")
37
+ line = target.get("start_line", 1)
38
+
39
+ # Generate deduplication fingerprint
40
+ seed = f"{rule_id}:{file_path}:{line}"
41
+ line_hash = hashlib.sha256(seed.encode("utf-8")).hexdigest()[:16]
42
+
43
+ result: Dict[str, Any] = {
44
+ "ruleId": rule_id,
45
+ "message": {"text": f.get("title", "TorusGuard Security Finding")},
46
+ "level": "error" if f.get("severity") in ("Critical", "High") else "warning",
47
+ "locations": [
48
+ {
49
+ "physicalLocation": {
50
+ "artifactLocation": {
51
+ "uri": file_path,
52
+ "uriBaseId": "%SRCROOT%"
53
+ },
54
+ "region": {
55
+ "startLine": line,
56
+ "startColumn": 1
57
+ }
58
+ }
59
+ }
60
+ ],
61
+ "partialFingerprints": {
62
+ "primaryLocationLineHash": line_hash
63
+ },
64
+ "properties": {
65
+ "confidence": f.get("confidence", 70),
66
+ "status": f.get("status", "Confirmed"),
67
+ "finding_id": f.get("finding_id", "TG-FIND-UNKNOWN")
68
+ }
69
+ }
70
+ results.append(result)
71
+
72
+ sarif = {
73
+ "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
74
+ "version": "2.1.0",
75
+ "runs": [
76
+ {
77
+ "tool": {
78
+ "driver": {
79
+ "name": "TorusGuard",
80
+ "semanticVersion": "1.3.6",
81
+ "informationUri": "https://github.com/githubmofo/TorusGuard",
82
+ "rules": list(rules_map.values())
83
+ }
84
+ },
85
+ "automationDetails": {
86
+ "id": f"{category}/{run_id}"
87
+ },
88
+ "results": results
89
+ }
90
+ ]
91
+ }
92
+ return sarif
93
+
94
+
95
+ def main():
96
+ parser = argparse.ArgumentParser(description="TorusGuard SARIF v2.1.0 Exporter")
97
+ parser.add_argument("--input", "-i", help="Path to findings JSON file")
98
+ parser.add_argument("--output", "-o", help="Output path for sarif.json")
99
+ parser.add_argument("--root", "-r", help="Project root override")
100
+ parser.add_argument("--run-id", default=None, help="Unique execution Run ID")
101
+ parser.add_argument("--stdout", action="store_true", help="Print SARIF JSON to stdout")
102
+ args = parser.parse_args()
103
+
104
+ root = Path(args.root).resolve() if args.root else Path.cwd().resolve()
105
+ findings = []
106
+ run_id = args.run_id or "run-default"
107
+
108
+ if args.input:
109
+ in_path = Path(args.input)
110
+ if not in_path.is_absolute():
111
+ in_path = (root / in_path).resolve()
112
+ if in_path.is_file():
113
+ with open(in_path, "r", encoding="utf-8") as f:
114
+ findings = json.load(f)
115
+ else:
116
+ # Auto-discover latest audit run findings
117
+ runs_dir = root / ".torusguard" / "runs"
118
+ if runs_dir.is_dir():
119
+ run_folders = sorted(
120
+ [d for d in runs_dir.iterdir() if d.is_dir() and (d / "findings.json").is_file()],
121
+ key=lambda p: p.stat().st_mtime,
122
+ reverse=True
123
+ )
124
+ if run_folders:
125
+ latest_run = run_folders[0]
126
+ run_id = args.run_id or latest_run.name
127
+ findings_file = latest_run / "findings.json"
128
+ try:
129
+ with open(findings_file, "r", encoding="utf-8") as f:
130
+ findings = json.load(f)
131
+ except Exception:
132
+ findings = []
133
+
134
+ sarif = generate_sarif(findings, run_id=run_id)
135
+
136
+ if args.output:
137
+ out_path = Path(args.output)
138
+ if not out_path.is_absolute():
139
+ out_path = (root / out_path).resolve()
140
+ out_path.parent.mkdir(parents=True, exist_ok=True)
141
+ with open(out_path, "w", encoding="utf-8") as f:
142
+ json.dump(sarif, f, indent=2)
143
+ print(f"[SUCCESS] SARIF log written to: {out_path}")
144
+ elif args.stdout:
145
+ print(json.dumps(sarif, indent=2))
146
+ else:
147
+ # Default to writing in .torusguard/runs/results-latest.sarif
148
+ default_sarif = root / ".torusguard" / "runs" / "results-latest.sarif"
149
+ default_sarif.parent.mkdir(parents=True, exist_ok=True)
150
+ with open(default_sarif, "w", encoding="utf-8") as f:
151
+ json.dump(sarif, f, indent=2)
152
+ print(f"[SUCCESS] SARIF log written to: {default_sarif}")
153
+
154
+
155
+ if __name__ == "__main__":
156
+ main()
@@ -221,6 +221,24 @@ def detect_stack(project_root: Path) -> dict[str, Any]:
221
221
  "indicator": "Flask application instantiation"
222
222
  })
223
223
  profile["recommended_references"].append("flask-security.md")
224
+ elif "tornado" in content or "tornado.web" in content:
225
+ add_to_list(profile, "languages_found", "Python")
226
+ profile["ecosystem_family"] = "python"
227
+ add_to_list(profile, "frameworks_found", "Tornado")
228
+ profile["confidence"] = "Confirmed"
229
+ profile["detection_evidence"].append({
230
+ "file": str(py_file.relative_to(project_root)),
231
+ "indicator": "Tornado application"
232
+ })
233
+ elif "starlette" in content:
234
+ add_to_list(profile, "languages_found", "Python")
235
+ profile["ecosystem_family"] = "python"
236
+ add_to_list(profile, "frameworks_found", "Starlette")
237
+ profile["confidence"] = "Confirmed"
238
+ profile["detection_evidence"].append({
239
+ "file": str(py_file.relative_to(project_root)),
240
+ "indicator": "Starlette application"
241
+ })
224
242
 
225
243
  if "sqlalchemy" in content:
226
244
  add_to_list(profile, "data_layers_found", "SQLAlchemy")
@@ -286,11 +304,27 @@ def detect_stack(project_root: Path) -> dict[str, Any]:
286
304
  profile["confidence"] = "Confirmed"
287
305
  profile["detection_evidence"].append({"file": "package.json", "indicator": "express dependency"})
288
306
  profile["recommended_references"].append("express-security.md")
307
+ elif "fastify" in deps:
308
+ add_to_list(profile, "frameworks_found", "Fastify")
309
+ profile["confidence"] = "Confirmed"
310
+ profile["detection_evidence"].append({"file": "package.json", "indicator": "fastify dependency"})
311
+ elif "koa" in deps:
312
+ add_to_list(profile, "frameworks_found", "Koa")
313
+ profile["confidence"] = "Confirmed"
314
+ profile["detection_evidence"].append({"file": "package.json", "indicator": "koa dependency"})
315
+ elif "@remix-run/react" in deps or "@remix-run/node" in deps:
316
+ add_to_list(profile, "frameworks_found", "Remix")
317
+ profile["confidence"] = "Confirmed"
318
+ profile["detection_evidence"].append({"file": "package.json", "indicator": "Remix dependency"})
289
319
  elif "react" in deps:
290
320
  add_to_list(profile, "frameworks_found", "React / Vite")
291
321
  profile["confidence"] = "Confirmed"
292
322
  profile["detection_evidence"].append({"file": "package.json", "indicator": "react dependency"})
293
323
  profile["recommended_references"].append("react-vite-security.md")
324
+ elif "vite" in deps:
325
+ add_to_list(profile, "frameworks_found", "Vite")
326
+ profile["confidence"] = "Confirmed"
327
+ profile["detection_evidence"].append({"file": "package.json", "indicator": "vite dependency"})
294
328
 
295
329
  # ORM / Data layer detection
296
330
  if "@prisma/client" in deps or "prisma" in deps:
@@ -433,6 +467,8 @@ def detect_stack(project_root: Path) -> dict[str, Any]:
433
467
 
434
468
  if "Microsoft.NET.Sdk.Web" in csproj_content or "Microsoft.AspNetCore" in csproj_content or "Swashbuckle" in csproj_content:
435
469
  add_to_list(profile, "frameworks_found", "ASP.NET Core")
470
+ if list(project_root.glob("**/*.razor")) or "Microsoft.AspNetCore.Components" in csproj_content or "blazor" in csproj_content.lower():
471
+ add_to_list(profile, "frameworks_found", "Blazor")
436
472
  if "Microsoft.EntityFrameworkCore" in csproj_content:
437
473
  add_to_list(profile, "data_layers_found", "Entity Framework Core")
438
474
  elif "Dapper" in csproj_content:
@@ -442,11 +478,17 @@ def detect_stack(project_root: Path) -> dict[str, Any]:
442
478
  # G. PHP Ecosystem
443
479
  # -------------------------------------------------------------------------
444
480
  composer_json = project_root / "composer.json"
445
- if composer_json.is_file():
481
+ is_wordpress = (project_root / "wp-config.php").is_file() or (project_root / "wp-load.php").is_file() or (project_root / "wp-content").is_dir()
482
+ if composer_json.is_file() or is_wordpress:
446
483
  add_to_list(profile, "languages_found", "PHP")
447
484
  profile["ecosystem_family"] = "php"
448
485
  profile["confidence"] = "Confirmed"
449
- profile["detection_evidence"].append({"file": "composer.json", "indicator": "PHP Composer manifest"})
486
+ if is_wordpress:
487
+ add_to_list(profile, "frameworks_found", "WordPress")
488
+ add_to_list(profile, "data_layers_found", "MySQL / wpdb")
489
+ profile["detection_evidence"].append({"file": "wp-config.php" if (project_root / "wp-config.php").is_file() else "wp-content", "indicator": "WordPress installation"})
490
+ if composer_json.is_file():
491
+ profile["detection_evidence"].append({"file": "composer.json", "indicator": "PHP Composer manifest"})
450
492
  profile["recommended_rules"].extend(["TG-SEC-*", "TG-INPUT-001", "TG-INPUT-002", "TG-PLATFORM-*"])
451
493
  profile["recommended_references"].append("polyglot-security-matrix.md")
452
494