torusguard 1.3.4 → 1.3.5

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 (239) 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 +93 -7
  33. package/.torusguard/runs/run-20260912-214110-audit/findings.json +1256 -0
  34. package/.torusguard/runs/run-20260912-214110-audit/findings.md +534 -0
  35. package/.torusguard/runs/run-20260912-214110-audit/manifest.json +12 -0
  36. package/.torusguard/runs/run-20260912-214110-audit/summary.md +5 -0
  37. package/.torusguard/runs/run-20260912-214813-audit/findings.json +992 -0
  38. package/.torusguard/runs/run-20260912-214813-audit/findings.md +422 -0
  39. package/.torusguard/runs/run-20260912-214813-audit/manifest.json +12 -0
  40. package/.torusguard/runs/run-20260912-214813-audit/summary.md +5 -0
  41. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-auth-003-49-7c96f3/metadata.json +17 -0
  42. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-auth-003-49-7c96f3/minimal_patch_plan.md +21 -0
  43. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-auth-003-49-7c96f3/patch.diff +9 -0
  44. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +17 -0
  45. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
  46. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
  47. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-platform-001-12-cf8156/metadata.json +17 -0
  48. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-platform-001-12-cf8156/minimal_patch_plan.md +21 -0
  49. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-platform-001-12-cf8156/patch.diff +9 -0
  50. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-rate-001-26-affcfa/metadata.json +17 -0
  51. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-rate-001-26-affcfa/minimal_patch_plan.md +21 -0
  52. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-rate-001-26-affcfa/patch.diff +9 -0
  53. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-sec-001-9-e22e50/metadata.json +17 -0
  54. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-sec-001-9-e22e50/minimal_patch_plan.md +21 -0
  55. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-sec-001-9-e22e50/patch.diff +9 -0
  56. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-ssrf-004-9-9803ad/metadata.json +17 -0
  57. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-ssrf-004-9-9803ad/minimal_patch_plan.md +21 -0
  58. package/.torusguard/runs/run-20260912-215555-audit/bundles/bnd-tg-ssrf-004-9-9803ad/patch.diff +9 -0
  59. package/.torusguard/runs/run-20260912-215555-audit/findings.json +530 -0
  60. package/.torusguard/runs/run-20260912-215555-audit/findings.md +232 -0
  61. package/.torusguard/runs/run-20260912-215555-audit/manifest.json +13 -0
  62. package/.torusguard/runs/run-20260912-215555-audit/remediation.md +102 -0
  63. package/.torusguard/runs/run-20260912-215555-audit/summary.md +5 -0
  64. package/.torusguard/runs/run-20260912-215731-audit/apply_plan.md +6 -0
  65. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/metadata.json +17 -0
  66. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/minimal_patch_plan.md +21 -0
  67. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-client-001-7-587129/patch.diff +9 -0
  68. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-db-002-9-5f7850/metadata.json +17 -0
  69. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-db-002-9-5f7850/minimal_patch_plan.md +21 -0
  70. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-db-002-9-5f7850/patch.diff +9 -0
  71. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/metadata.json +17 -0
  72. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/minimal_patch_plan.md +22 -0
  73. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-001-27-2486f1/patch.diff +10 -0
  74. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +17 -0
  75. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
  76. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
  77. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-001-12-cf8156/metadata.json +17 -0
  78. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-001-12-cf8156/minimal_patch_plan.md +21 -0
  79. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-001-12-cf8156/patch.diff +9 -0
  80. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-17-876973/metadata.json +17 -0
  81. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-17-876973/minimal_patch_plan.md +23 -0
  82. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-17-876973/patch.diff +11 -0
  83. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-5-40c794/metadata.json +17 -0
  84. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-5-40c794/minimal_patch_plan.md +23 -0
  85. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-platform-002-5-40c794/patch.diff +11 -0
  86. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-001-26-affcfa/metadata.json +17 -0
  87. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-001-26-affcfa/minimal_patch_plan.md +21 -0
  88. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-001-26-affcfa/patch.diff +9 -0
  89. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-002-54-0b38d2/metadata.json +17 -0
  90. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-002-54-0b38d2/minimal_patch_plan.md +21 -0
  91. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-rate-002-54-0b38d2/patch.diff +9 -0
  92. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-18-a3c1e8/metadata.json +17 -0
  93. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-18-a3c1e8/minimal_patch_plan.md +21 -0
  94. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-18-a3c1e8/patch.diff +9 -0
  95. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-9-e22e50/metadata.json +17 -0
  96. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-9-e22e50/minimal_patch_plan.md +21 -0
  97. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-001-9-e22e50/patch.diff +9 -0
  98. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-28-a1a0a1/metadata.json +17 -0
  99. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-28-a1a0a1/minimal_patch_plan.md +21 -0
  100. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-28-a1a0a1/patch.diff +9 -0
  101. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-30-00569e/metadata.json +17 -0
  102. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-30-00569e/minimal_patch_plan.md +21 -0
  103. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-sec-004-30-00569e/patch.diff +9 -0
  104. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-ssrf-004-9-9803ad/metadata.json +17 -0
  105. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-ssrf-004-9-9803ad/minimal_patch_plan.md +21 -0
  106. package/.torusguard/runs/run-20260912-215731-audit/bundles/bnd-tg-ssrf-004-9-9803ad/patch.diff +9 -0
  107. package/.torusguard/runs/run-20260912-215731-audit/diff_summary.md +186 -0
  108. package/.torusguard/runs/run-20260912-215731-audit/findings.json +497 -0
  109. package/.torusguard/runs/run-20260912-215731-audit/findings.md +218 -0
  110. package/.torusguard/runs/run-20260912-215731-audit/manifest.json +14 -0
  111. package/.torusguard/runs/run-20260912-215731-audit/recheck.md +76 -0
  112. package/.torusguard/runs/run-20260912-215731-audit/remediation.md +234 -0
  113. package/.torusguard/runs/run-20260912-215731-audit/summary.md +5 -0
  114. package/.torusguard/runs/run-20260912-220134-audit/findings.json +68 -0
  115. package/.torusguard/runs/run-20260912-220134-audit/findings.md +36 -0
  116. package/.torusguard/runs/run-20260912-220134-audit/manifest.json +12 -0
  117. package/.torusguard/runs/run-20260912-220134-audit/summary.md +5 -0
  118. package/.torusguard/runs/run-20260912-220200-audit/findings.json +1 -0
  119. package/.torusguard/runs/run-20260912-220200-audit/findings.md +8 -0
  120. package/.torusguard/runs/run-20260912-220200-audit/manifest.json +12 -0
  121. package/.torusguard/runs/run-20260912-220200-audit/recheck.md +6 -0
  122. package/.torusguard/runs/run-20260912-220200-audit/summary.md +5 -0
  123. package/.torusguard/runs/run-20260912-220227-audit/findings.json +1 -0
  124. package/.torusguard/runs/run-20260912-220227-audit/findings.md +8 -0
  125. package/.torusguard/runs/run-20260912-220227-audit/manifest.json +12 -0
  126. package/.torusguard/runs/run-20260912-220227-audit/recheck.md +6 -0
  127. package/.torusguard/runs/run-20260912-220227-audit/summary.md +5 -0
  128. package/.torusguard/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
  129. package/.torusguard/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
  130. package/.torusguard/scripts/__pycache__/report_sync.cpython-311.pyc +0 -0
  131. package/.torusguard/scripts/__pycache__/term_ui.cpython-311.pyc +0 -0
  132. package/.torusguard/scripts/apply_runner.py +383 -377
  133. package/.torusguard/scripts/audit_runner.py +1306 -653
  134. package/.torusguard/scripts/finding_scorer.py +14 -2
  135. package/.torusguard/scripts/harden_runner.py +628 -455
  136. package/.torusguard/scripts/recheck_runner.py +248 -238
  137. package/.torusguard/scripts/recipes_runner.py +137 -137
  138. package/.torusguard/scripts/report_sync.py +423 -0
  139. package/.torusguard/scripts/sarif_exporter.py +116 -116
  140. package/.torusguard/scripts/term_ui.py +162 -162
  141. package/.torusguard/snapshots/run-20260912-215731-audit/demo/playground/vulnerable_nextjs/actions.ts.bak +24 -0
  142. package/.torusguard/snapshots/run-20260912-215731-audit/examples/hardened-react-express/server/index.js.bak +121 -0
  143. package/.torusguard/snapshots/run-20260912-215731-audit/examples/python/fastapi-vuln/main.py.bak +20 -0
  144. package/.torusguard/snapshots/run-20260912-215731-audit/examples/vulnerable-react-express/client/src/App.jsx.bak +63 -0
  145. package/.torusguard/snapshots/run-20260912-215731-audit/examples/vulnerable-react-express/client/vite.config.js.bak +12 -0
  146. package/.torusguard/snapshots/run-20260912-215731-audit/examples/vulnerable-react-express/server/index.js.bak +82 -0
  147. package/.torusguard/workflows/apply.md +11 -4
  148. package/.torusguard/workflows/audit.md +7 -1
  149. package/.torusguard/workflows/authorize.md +2 -1
  150. package/.torusguard/workflows/exploit-check.md +2 -1
  151. package/.torusguard/workflows/harden.md +7 -1
  152. package/.torusguard/workflows/init.md +6 -1
  153. package/.torusguard/workflows/memory.md +2 -1
  154. package/.torusguard/workflows/recheck.md +7 -1
  155. package/.torusguard/workflows/report.md +7 -1
  156. package/.torusguard/workflows/status.md +6 -1
  157. package/.torusguard/workflows/verify.md +6 -1
  158. package/.torusguard/workflows/web-validate.md +2 -1
  159. package/README.md +470 -345
  160. package/bin/torusguard.js +550 -545
  161. package/package.json +1 -1
  162. package/skills/torusguard/SKILL.md +73 -72
  163. package/skills/torusguard/payload/.manifest.json +66 -63
  164. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +30 -14
  165. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +33 -16
  166. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +31 -15
  167. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +26 -16
  168. package/skills/torusguard/payload/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +24 -16
  169. package/skills/torusguard/payload/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +32 -18
  170. package/skills/torusguard/payload/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +24 -17
  171. package/skills/torusguard/payload/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +31 -18
  172. package/skills/torusguard/payload/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +28 -17
  173. package/skills/torusguard/payload/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +33 -17
  174. package/skills/torusguard/payload/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +31 -16
  175. package/skills/torusguard/payload/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +25 -16
  176. package/skills/torusguard/payload/rules/secrets/TG-SEC-005-secret-in-git-history.md +24 -19
  177. package/skills/torusguard/payload/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +36 -19
  178. package/skills/torusguard/payload/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +21 -16
  179. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +45 -18
  180. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +20 -16
  181. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +28 -19
  182. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +25 -18
  183. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +29 -19
  184. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +23 -18
  185. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +23 -18
  186. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +36 -16
  187. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +26 -17
  188. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +30 -16
  189. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +25 -16
  190. package/skills/torusguard/payload/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +28 -17
  191. package/skills/torusguard/payload/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +31 -17
  192. package/skills/torusguard/payload/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +31 -17
  193. package/skills/torusguard/payload/rules_catalog.json +520 -0
  194. package/skills/torusguard/payload/scripts/apply_runner.py +383 -377
  195. package/skills/torusguard/payload/scripts/audit_runner.py +1306 -653
  196. package/skills/torusguard/payload/scripts/finding_scorer.py +14 -2
  197. package/skills/torusguard/payload/scripts/harden_runner.py +628 -455
  198. package/skills/torusguard/payload/scripts/recheck_runner.py +248 -238
  199. package/skills/torusguard/payload/scripts/recipes_runner.py +137 -137
  200. package/skills/torusguard/payload/scripts/report_sync.py +423 -0
  201. package/skills/torusguard/payload/scripts/sarif_exporter.py +116 -116
  202. package/skills/torusguard/payload/scripts/term_ui.py +162 -162
  203. package/skills/torusguard/payload/skills/torusguard/SKILL.md +75 -72
  204. package/skills/torusguard/payload/skills/torusguard-apply/SKILL.md +84 -80
  205. package/skills/torusguard/payload/skills/torusguard-audit/SKILL.md +87 -83
  206. package/skills/torusguard/payload/skills/torusguard-authorize/SKILL.md +7 -2
  207. package/skills/torusguard/payload/skills/torusguard-exploit-check/SKILL.md +7 -2
  208. package/skills/torusguard/payload/skills/torusguard-full/SKILL.md +7 -2
  209. package/skills/torusguard/payload/skills/torusguard-harden/SKILL.md +98 -94
  210. package/skills/torusguard/payload/skills/torusguard-init/SKILL.md +68 -64
  211. package/skills/torusguard/payload/skills/torusguard-recheck/SKILL.md +81 -77
  212. package/skills/torusguard/payload/skills/torusguard-report/SKILL.md +76 -72
  213. package/skills/torusguard/payload/skills/torusguard-status/SKILL.md +62 -58
  214. package/skills/torusguard/payload/skills/torusguard-verify/SKILL.md +7 -2
  215. package/skills/torusguard/payload/skills/torusguard-web-validate/SKILL.md +7 -2
  216. package/skills/torusguard/payload/workflows/apply.md +11 -4
  217. package/skills/torusguard/payload/workflows/audit.md +7 -1
  218. package/skills/torusguard/payload/workflows/authorize.md +2 -1
  219. package/skills/torusguard/payload/workflows/exploit-check.md +2 -1
  220. package/skills/torusguard/payload/workflows/harden.md +7 -1
  221. package/skills/torusguard/payload/workflows/init.md +6 -1
  222. package/skills/torusguard/payload/workflows/memory.md +2 -1
  223. package/skills/torusguard/payload/workflows/recheck.md +7 -1
  224. package/skills/torusguard/payload/workflows/report.md +7 -1
  225. package/skills/torusguard/payload/workflows/status.md +6 -1
  226. package/skills/torusguard/payload/workflows/verify.md +6 -1
  227. package/skills/torusguard/payload/workflows/web-validate.md +2 -1
  228. package/skills/torusguard-apply/SKILL.md +84 -80
  229. package/skills/torusguard-audit/SKILL.md +87 -83
  230. package/skills/torusguard-authorize/SKILL.md +7 -2
  231. package/skills/torusguard-exploit-check/SKILL.md +7 -2
  232. package/skills/torusguard-full/SKILL.md +7 -2
  233. package/skills/torusguard-harden/SKILL.md +98 -94
  234. package/skills/torusguard-init/SKILL.md +68 -64
  235. package/skills/torusguard-recheck/SKILL.md +81 -77
  236. package/skills/torusguard-report/SKILL.md +76 -72
  237. package/skills/torusguard-status/SKILL.md +62 -58
  238. package/skills/torusguard-verify/SKILL.md +7 -2
  239. package/skills/torusguard-web-validate/SKILL.md +7 -2
@@ -0,0 +1,422 @@
1
+ # TorusGuard Security Audit Findings: run-20260912-214813-audit
2
+ - Target Root: `C:\Users\Admin\Desktop\TorusGuard`
3
+ - Total Scored Findings: `30`
4
+ - Identified Clusters: `8`
5
+ - Generated At: `2026-09-12 21:48:13 IST`
6
+
7
+ ---
8
+ ## Summary of Findings
9
+
10
+ ### [Critical] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
11
+ - **Finding ID:** `TG-SEC-001-bb5e4b77`
12
+ - **Location:** `examples/vulnerable-react-express/server/index.js:9`
13
+ - **Confidence Score:** `80/100` (High Confidence)
14
+ - **Cluster:** `cluster-credentials-exposure`
15
+ - **Description:** Hardcoded JWT signing secret
16
+ ```
17
+
18
+ // TG-SEC-001: Hardcoded JWT secret
19
+ const JWT_SECRET = 'FAKE_DEMO_JWT_SECRET_NOT_FOR_PRODUCTION';
20
+
21
+ // TG-PLATFORM-001: Wildcard CORS with credentials
22
+ ```
23
+
24
+ ### [Critical] TG-SEC-001 - Hardcoded Secret or API Key in Tracked Source
25
+ - **Finding ID:** `TG-SEC-001-c393d596`
26
+ - **Location:** `examples/vulnerable-react-express/server/index.js:18`
27
+ - **Confidence Score:** `80/100` (High Confidence)
28
+ - **Cluster:** `cluster-credentials-exposure`
29
+ - **Description:** Hardcoded credential or API secret string
30
+ ```
31
+
32
+ const users = [
33
+ { id: '1', email: 'alice@demo.local', password: 'password123', name: 'Alice' },
34
+ { id: '2', email: 'bob@demo.local', password: 'secret456', name: 'Bob' },
35
+ ];
36
+ ```
37
+
38
+ ### [Critical] TG-SSRF-002 - Missing Internal Network Protection
39
+ - **Finding ID:** `TG-SSRF-002-8378a839`
40
+ - **Location:** `core/clustering.py:53`
41
+ - **Confidence Score:** `70/100` (High Confidence)
42
+ - **Cluster:** `cluster-ssrf`
43
+ - **Description:** Hardcoded internal loopback or cloud metadata endpoint target
44
+ ```
45
+ "cluster_id": "cluster-ssrf-network",
46
+ "title": "Unvalidated Outbound HTTP Requests & Network Boundary Leakage",
47
+ "shared_remediation_path": "Validate destination URLs against strict allowlists and block internal IP ranges (127.0.0.1, 169.254.169.254).",
48
+ "shared_verification_plan": "Attempt outbound requests to loopback and link-local metadata endpoints."
49
+ },
50
+ ```
51
+
52
+ ### [Critical] TG-DB-002 - Privileged Database Credential in Browser Context
53
+ - **Finding ID:** `TG-DB-002-d9bd69df`
54
+ - **Location:** `demo/playground/vulnerable_nextjs/actions.ts:9`
55
+ - **Confidence Score:** `70/100` (High Confidence)
56
+ - **Cluster:** `cluster-client-leak`
57
+ - **Description:** Service role key or raw database connection string reference in frontend code
58
+ ```
59
+
60
+ // Finding 1: TG-CLIENT-001 - Backend admin key exposed in client-accessible code
61
+ export const SUPABASE_SERVICE_ROLE_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.demo_secret_token_1234567890";
62
+
63
+ interface UserRecord {
64
+ ```
65
+
66
+ ### [Critical] TG-SSRF-002 - Missing Internal Network Protection
67
+ - **Finding ID:** `TG-SSRF-002-d08ed1ca`
68
+ - **Location:** `examples/hardened-react-express/client/vite.config.js:7`
69
+ - **Confidence Score:** `70/100` (High Confidence)
70
+ - **Cluster:** `cluster-ssrf`
71
+ - **Description:** Hardcoded internal loopback or cloud metadata endpoint target
72
+ ```
73
+ plugins: [react()],
74
+ build: { sourcemap: false },
75
+ server: { port: 5173, proxy: { '/api': 'http://localhost:3001' } },
76
+ });
77
+ ```
78
+
79
+ ### [Critical] TG-SSRF-002 - Missing Internal Network Protection
80
+ - **Finding ID:** `TG-SSRF-002-a79cf464`
81
+ - **Location:** `examples/hardened-react-express/server/index.js:121`
82
+ - **Confidence Score:** `70/100` (High Confidence)
83
+ - **Cluster:** `cluster-ssrf`
84
+ - **Description:** Hardcoded internal loopback or cloud metadata endpoint target
85
+ ```
86
+ });
87
+
88
+ seed().then(() => app.listen(PORT, () => console.log(`Hardened demo http://localhost:${PORT}`)));
89
+ ```
90
+
91
+ ### [Critical] TG-SSRF-004 - Unbounded Outbound Request Without Timeout
92
+ - **Finding ID:** `TG-SSRF-004-dcf3f71e`
93
+ - **Location:** `examples/python/fastapi-hardened/main.py:30`
94
+ - **Confidence Score:** `70/100` (High Confidence)
95
+ - **Cluster:** `cluster-ssrf`
96
+ - **Description:** Python requests call without explicit timeout parameter
97
+ ```
98
+ if not is_safe_url(url):
99
+ raise HTTPException(status_code=400, detail="Invalid destination address")
100
+ response = requests.get(url, timeout=5)
101
+ return {"status": response.status_code, "content": response.text}
102
+
103
+ ```
104
+
105
+ ### [Critical] TG-SSRF-004 - Unbounded Outbound Request Without Timeout
106
+ - **Finding ID:** `TG-SSRF-004-d8472223`
107
+ - **Location:** `examples/python/fastapi-vuln/main.py:9`
108
+ - **Confidence Score:** `70/100` (High Confidence)
109
+ - **Cluster:** `cluster-ssrf`
110
+ - **Description:** Python requests call without explicit timeout parameter
111
+ ```
112
+ @app.get("/fetch")
113
+ def fetch_url(url: str):
114
+ response = requests.get(url)
115
+ return {"status": response.status_code, "content": response.text}
116
+
117
+ ```
118
+
119
+ ### [Critical] TG-SSRF-002 - Missing Internal Network Protection
120
+ - **Finding ID:** `TG-SSRF-002-3c5a7c3c`
121
+ - **Location:** `examples/vulnerable-react-express/client/src/App.jsx:42`
122
+ - **Confidence Score:** `70/100` (High Confidence)
123
+ - **Cluster:** `cluster-ssrf`
124
+ - **Description:** Hardcoded internal loopback or cloud metadata endpoint target
125
+ ```
126
+ <div style={{ maxWidth: 560, margin: '2rem auto', fontFamily: 'sans-serif' }}>
127
+ <h1>Vulnerable Demo</h1>
128
+ <p style={{ color: 'crimson' }}>Intentionally insecure — localhost lab only</p>
129
+
130
+ <form onSubmit={login}>
131
+ ```
132
+
133
+ ### [Critical] TG-SSRF-002 - Missing Internal Network Protection
134
+ - **Finding ID:** `TG-SSRF-002-13c81e3a`
135
+ - **Location:** `examples/vulnerable-react-express/client/src/config.js:5`
136
+ - **Confidence Score:** `70/100` (High Confidence)
137
+ - **Cluster:** `cluster-ssrf`
138
+ - **Description:** Hardcoded internal loopback or cloud metadata endpoint target
139
+ ```
140
+ apiUrl: import.meta.env.VITE_API_URL,
141
+ // FAKE DEMO ONLY — never put real database URLs in client code
142
+ demoDbUrl: 'postgresql://demo:FAKE_PASSWORD@localhost:5432/demo',
143
+ };
144
+ ```
145
+
146
+ ### [Critical] TG-SSRF-002 - Missing Internal Network Protection
147
+ - **Finding ID:** `TG-SSRF-002-b0f87c06`
148
+ - **Location:** `examples/vulnerable-react-express/client/vite.config.js:10`
149
+ - **Confidence Score:** `70/100` (High Confidence)
150
+ - **Cluster:** `cluster-ssrf`
151
+ - **Description:** Hardcoded internal loopback or cloud metadata endpoint target
152
+ ```
153
+ server: {
154
+ port: 5173,
155
+ proxy: { '/api': 'http://localhost:3001' },
156
+ },
157
+ });
158
+ ```
159
+
160
+ ### [Critical] TG-SSRF-002 - Missing Internal Network Protection
161
+ - **Finding ID:** `TG-SSRF-002-ee77c629`
162
+ - **Location:** `examples/vulnerable-react-express/server/index.js:82`
163
+ - **Confidence Score:** `70/100` (High Confidence)
164
+ - **Cluster:** `cluster-ssrf`
165
+ - **Description:** Hardcoded internal loopback or cloud metadata endpoint target
166
+ ```
167
+ });
168
+
169
+ app.listen(PORT, () => console.log(`Vulnerable demo server http://localhost:${PORT}`));
170
+ ```
171
+
172
+ ### [Critical] TG-SSRF-002 - Missing Internal Network Protection
173
+ - **Finding ID:** `TG-SSRF-002-a0d1eac8`
174
+ - **Location:** `skills/torusguard/payload/config/scope.json:4`
175
+ - **Confidence Score:** `70/100` (High Confidence)
176
+ - **Cluster:** `cluster-ssrf`
177
+ - **Description:** Hardcoded internal loopback or cloud metadata endpoint target
178
+ ```
179
+ "$schema": "../schemas/authorization.schema.json",
180
+ "authorization": {
181
+ "target": "localhost",
182
+ "owner_confirmed": false,
183
+ "scope_type": "source_code_only",
184
+ ```
185
+
186
+ ### [Critical] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
187
+ - **Finding ID:** `TG-DIFF-001-7db54483`
188
+ - **Location:** `skills/torusguard/payload/scripts/rules_sync.py:180`
189
+ - **Confidence Score:** `70/100` (High Confidence)
190
+ - **Cluster:** `cluster-transport-security`
191
+ - **Description:** Disabled TLS certificate verification (verify=False)
192
+ ```
193
+
194
+ if not bypass_guards:
195
+ bypass_rule = "4. **No Security Bypasses:** Never insert `# nosec`, `verify=False`, `@csrf_exempt`, or `bypass_auth=True`."
196
+ else:
197
+ bypass_rule = f"4. **No Security Bypasses:** Never insert `# nosec`, `verify=False`, or {', '.join(bypass_guards[:2])}."
198
+ ```
199
+
200
+ ### [Critical] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
201
+ - **Finding ID:** `TG-DIFF-001-77bc2f9b`
202
+ - **Location:** `skills/torusguard/payload/scripts/rules_sync.py:157`
203
+ - **Confidence Score:** `70/100` (High Confidence)
204
+ - **Cluster:** `cluster-transport-security`
205
+ - **Description:** Disabled Go TLS certificate verification (InsecureSkipVerify: true)
206
+ ```
207
+ if "go" in stack_lower:
208
+ sql_guards.append("`db.Query(..., args)` / GORM")
209
+ bypass_guards.append("`InsecureSkipVerify: true`")
210
+ if "rust" in stack_lower:
211
+ sql_guards.append("`sqlx::query!` / Diesel")
212
+ ```
213
+
214
+ ### [Critical] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
215
+ - **Finding ID:** `TG-DIFF-001-cb5ae7e9`
216
+ - **Location:** `skills/torusguard/payload/scripts/rules_sync.py:172`
217
+ - **Confidence Score:** `70/100` (High Confidence)
218
+ - **Cluster:** `cluster-transport-security`
219
+ - **Description:** Disabled Node.js TLS rejectUnauthorized
220
+ ```
221
+ if "typescript" in stack_lower or "javascript" in stack_lower or "next" in stack_lower or "express" in stack_lower:
222
+ sql_guards.append("Prisma / Drizzle binders")
223
+ bypass_guards.append("`rejectUnauthorized: false`")
224
+
225
+ if not sql_guards:
226
+ ```
227
+
228
+ ### [Critical] TG-DIFF-001 - Accidental Security Check Bypass in Patch Additions
229
+ - **Finding ID:** `TG-DIFF-001-0e4204af`
230
+ - **Location:** `skills/torusguard/payload/scripts/rules_sync.py:169`
231
+ - **Confidence Score:** `70/100` (High Confidence)
232
+ - **Cluster:** `cluster-transport-security`
233
+ - **Description:** Disabled PHP curl SSL verification
234
+ ```
235
+ if "php" in stack_lower:
236
+ sql_guards.append("PDO prepared statements / Eloquent")
237
+ bypass_guards.append("`CURLOPT_SSL_VERIFYPEER => false`")
238
+ if "typescript" in stack_lower or "javascript" in stack_lower or "next" in stack_lower or "express" in stack_lower:
239
+ sql_guards.append("Prisma / Drizzle binders")
240
+ ```
241
+
242
+ ### [High] TG-INPUT-003 - Unsafe Dynamic Code or HTML Execution
243
+ - **Finding ID:** `TG-INPUT-003-fea9421e`
244
+ - **Location:** `examples/vulnerable-react-express/client/src/App.jsx:53`
245
+ - **Confidence Score:** `80/100` (High Confidence)
246
+ - **Cluster:** `cluster-injection`
247
+ - **Description:** React dangerouslySetInnerHTML rendering raw unescaped HTML
248
+ ```
249
+
250
+ {/* TG-INPUT-003: Unsafe HTML rendering */}
251
+ <div dangerouslySetInnerHTML={{ __html: bio }} />
252
+
253
+ <button onClick={fetchUser}>Fetch user (IDOR demo)</button>
254
+ ```
255
+
256
+ ### [High] TG-PLATFORM-001 - Wildcard CORS With Credentials
257
+ - **Finding ID:** `TG-PLATFORM-001-7dd35cb4`
258
+ - **Location:** `examples/vulnerable-react-express/server/index.js:12`
259
+ - **Confidence Score:** `80/100` (High Confidence)
260
+ - **Cluster:** `cluster-auth-bypass`
261
+ - **Description:** Wildcard CORS origin configured in Express middleware
262
+ ```
263
+
264
+ // TG-PLATFORM-001: Wildcard CORS with credentials
265
+ app.use(cors({ origin: '*', credentials: true }));
266
+
267
+ // TG-PLATFORM-004: No explicit JSON body size limit
268
+ ```
269
+
270
+ ### [High] TG-INPUT-001 - Missing Server-Side Request Validation
271
+ - **Finding ID:** `TG-INPUT-001-c7457f38`
272
+ - **Location:** `examples/vulnerable-react-express/server/index.js:27`
273
+ - **Confidence Score:** `70/100` (High Confidence)
274
+ - **Cluster:** `cluster-injection`
275
+ - **Description:** Destructuring unvalidated req.body without schema validation
276
+ ```
277
+ // TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)
278
+ app.post('/api/login', (req, res) => {
279
+ const { email, password } = req.body;
280
+ console.log('Login attempt:', { email, password }); // TG-SEC-004
281
+ const user = users.find((u) => u.email === email && u.password === password);
282
+ ```
283
+
284
+ ### [High] TG-RATE-001 - Unlimited Authentication Endpoint
285
+ - **Finding ID:** `TG-RATE-001-dcd0a3c7`
286
+ - **Location:** `examples/vulnerable-react-express/server/index.js:26`
287
+ - **Confidence Score:** `70/100` (High Confidence)
288
+ - **Cluster:** `cluster-rate-limiting`
289
+ - **Description:** Authentication POST endpoint defined without rate-limiting middleware
290
+ ```
291
+ // TG-SEC-004: Logs sensitive data
292
+ // TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)
293
+ app.post('/api/login', (req, res) => {
294
+ const { email, password } = req.body;
295
+ console.log('Login attempt:', { email, password }); // TG-SEC-004
296
+ ```
297
+
298
+ ### [High] TG-AUTH-004 - Insecure Session Cookie Configuration
299
+ - **Finding ID:** `TG-AUTH-004-f60870ef`
300
+ - **Location:** `skills/torusguard/payload/scripts/rules_sync.py:180`
301
+ - **Confidence Score:** `70/100` (High Confidence)
302
+ - **Cluster:** `cluster-auth-bypass`
303
+ - **Description:** Decorator disabling route-level authentication or CSRF protection
304
+ ```
305
+
306
+ if not bypass_guards:
307
+ bypass_rule = "4. **No Security Bypasses:** Never insert `# nosec`, `verify=False`, `@csrf_exempt`, or `bypass_auth=True`."
308
+ else:
309
+ bypass_rule = f"4. **No Security Bypasses:** Never insert `# nosec`, `verify=False`, or {', '.join(bypass_guards[:2])}."
310
+ ```
311
+
312
+ ### [High] TG-AUTH-004 - Insecure Session Cookie Configuration
313
+ - **Finding ID:** `TG-AUTH-004-6b0c7ebf`
314
+ - **Location:** `skills/torusguard/payload/scripts/rules_sync.py:166`
315
+ - **Confidence Score:** `70/100` (High Confidence)
316
+ - **Cluster:** `cluster-auth-bypass`
317
+ - **Description:** Attribute disabling ASP.NET authentication
318
+ ```
319
+ if "c#" in stack_lower or "dotnet" in stack_lower:
320
+ sql_guards.append("EF Core LINQ / `FromSqlInterpolated`")
321
+ bypass_guards.append("`[AllowAnonymous]`")
322
+ if "php" in stack_lower:
323
+ sql_guards.append("PDO prepared statements / Eloquent")
324
+ ```
325
+
326
+ ### [High] TG-AUTH-003 - Missing Object-Level Authorization (IDOR)
327
+ - **Finding ID:** `TG-AUTH-003-6a05e509`
328
+ - **Location:** `examples/hardened-react-express/server/index.js:49`
329
+ - **Confidence Score:** `55/100` (Medium Confidence)
330
+ - **Cluster:** `cluster-auth-bypass`
331
+ - **Description:** JWT verification missing explicit algorithms restriction parameter
332
+ ```
333
+ if (!token) return res.status(401).json({ error: 'Unauthorized' });
334
+ try {
335
+ req.user = jwt.verify(token, process.env.JWT_SECRET);
336
+ next();
337
+ } catch {
338
+ ```
339
+
340
+ ### [Medium] TG-PLATFORM-002 - Missing Security Headers
341
+ - **Finding ID:** `TG-PLATFORM-002-1f383dcf`
342
+ - **Location:** `examples/hardened-react-express/server/index.js:17`
343
+ - **Confidence Score:** `70/100` (High Confidence)
344
+ - **Cluster:** `cluster-platform`
345
+ - **Description:** Express application initialized without helmet security headers middleware
346
+ ```
347
+ }
348
+
349
+ const app = express();
350
+ const PORT = 3001;
351
+ const isProd = process.env.NODE_ENV === 'production';
352
+ ```
353
+
354
+ ### [Medium] TG-SEC-004 - Sensitive Information in Logs
355
+ - **Finding ID:** `TG-SEC-004-dbbc17f7`
356
+ - **Location:** `examples/vulnerable-react-express/client/src/App.jsx:30`
357
+ - **Confidence Score:** `70/100` (High Confidence)
358
+ - **Cluster:** `cluster-credentials-exposure`
359
+ - **Description:** Plaintext credential or token logged to output sink
360
+ ```
361
+ const data = await res.json();
362
+ // TG-CLIENT-002: Sensitive console logging
363
+ console.log('Login token:', data.token, 'config:', clientConfig);
364
+ setMessage(JSON.stringify(data));
365
+ }
366
+ ```
367
+
368
+ ### [Medium] TG-CLIENT-001 - Public Production Source Maps
369
+ - **Finding ID:** `TG-CLIENT-001-1ba4789e`
370
+ - **Location:** `examples/vulnerable-react-express/client/vite.config.js:7`
371
+ - **Confidence Score:** `70/100` (High Confidence)
372
+ - **Cluster:** `cluster-client-leak`
373
+ - **Description:** Build config emitting unminified source maps in production output
374
+ ```
375
+ export default defineConfig({
376
+ plugins: [react()],
377
+ build: { sourcemap: true },
378
+ server: {
379
+ port: 5173,
380
+ ```
381
+
382
+ ### [Medium] TG-SEC-004 - Sensitive Information in Logs
383
+ - **Finding ID:** `TG-SEC-004-08753da5`
384
+ - **Location:** `examples/vulnerable-react-express/server/index.js:28`
385
+ - **Confidence Score:** `70/100` (High Confidence)
386
+ - **Cluster:** `cluster-credentials-exposure`
387
+ - **Description:** Plaintext credential or token logged to output sink
388
+ ```
389
+ app.post('/api/login', (req, res) => {
390
+ const { email, password } = req.body;
391
+ console.log('Login attempt:', { email, password }); // TG-SEC-004
392
+ const user = users.find((u) => u.email === email && u.password === password);
393
+ if (!user) return res.status(401).json({ error: 'User not found' }); // enumeration
394
+ ```
395
+
396
+ ### [Medium] TG-RATE-002 - Unlimited Public Write Endpoint
397
+ - **Finding ID:** `TG-RATE-002-d67d7c98`
398
+ - **Location:** `examples/vulnerable-react-express/server/index.js:54`
399
+ - **Confidence Score:** `70/100` (High Confidence)
400
+ - **Cluster:** `cluster-rate-limiting`
401
+ - **Description:** Public submission endpoint defined without rate-limiting or captcha defense
402
+ ```
403
+ // TG-INPUT-001: No validation
404
+ // TG-RATE-002: Unlimited contact endpoint
405
+ app.post('/api/contact', (req, res) => {
406
+ res.json({ received: req.body });
407
+ });
408
+ ```
409
+
410
+ ### [Medium] TG-PLATFORM-002 - Missing Security Headers
411
+ - **Finding ID:** `TG-PLATFORM-002-eef342ec`
412
+ - **Location:** `examples/vulnerable-react-express/server/index.js:5`
413
+ - **Confidence Score:** `70/100` (High Confidence)
414
+ - **Cluster:** `cluster-platform`
415
+ - **Description:** Express application initialized without helmet security headers middleware
416
+ ```
417
+ const jwt = require('jsonwebtoken');
418
+
419
+ const app = express();
420
+ const PORT = 3001;
421
+
422
+ ```
@@ -0,0 +1,12 @@
1
+ {
2
+ "run_id": "run-20260912-214813-audit",
3
+ "command": "audit",
4
+ "target_name": "TorusGuard",
5
+ "created_at": "2026-09-12 21:48:13 IST",
6
+ "created_at_iso": "2026-09-12T21:48:13.470732+05:30",
7
+ "status": "completed",
8
+ "torusguard_version": "1.3.0",
9
+ "findings_count": 30,
10
+ "confirmed_fixed_count": 0,
11
+ "regressed_count": 0
12
+ }
@@ -0,0 +1,5 @@
1
+ # TorusGuard Audit Summary: run-20260912-214813-audit
2
+ - Scanned Scope: C:\Users\Admin\Desktop\TorusGuard
3
+ - Total Findings: 30
4
+ - Root-Cause Clusters: 8
5
+ - Generated: 2026-09-12 21:48:13 IST
@@ -0,0 +1,17 @@
1
+ {
2
+ "bundle_id": "bnd-tg-auth-003-49-7c96f3",
3
+ "finding_id": "TG-AUTH-003-6a05e509",
4
+ "rule_id": "TG-AUTH-003",
5
+ "title": "Missing Object-Level Authorization (IDOR)",
6
+ "target_file": "examples/hardened-react-express/server/index.js",
7
+ "line_number": 49,
8
+ "target_line": " req.user = jwt.verify(token, process.env.JWT_SECRET);",
9
+ "replacement_line": " req.user = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'] });",
10
+ "what_is_wrong": "JWT verification missing explicit algorithms restriction parameter",
11
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
12
+ "what_should_change": "Restricted JWT verification to explicit algorithm list ['HS256']",
13
+ "proposed_diff": "--- a/examples/hardened-react-express/server/index.js\n+++ b/examples/hardened-react-express/server/index.js\n@@ -47,5 +47,5 @@\n if (!token) return res.status(401).json({ error: 'Unauthorized' });\n try {\n- req.user = jwt.verify(token, process.env.JWT_SECRET);\n+ req.user = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'] });\n next();\n } catch {\n",
14
+ "additions": 1,
15
+ "deletions": 1,
16
+ "patched_content": "require('dotenv').config();\nconst express = require('express');\nconst helmet = require('helmet');\nconst cors = require('cors');\nconst cookieParser = require('cookie-parser');\nconst rateLimit = require('express-rate-limit');\nconst bcrypt = require('bcrypt');\nconst jwt = require('jsonwebtoken');\nconst crypto = require('crypto');\nconst { z } = require('zod');\n\nif (!process.env.JWT_SECRET) {\n console.error('Missing JWT_SECRET');\n process.exit(1);\n}\n\nconst app = express();\nconst PORT = 3001;\nconst isProd = process.env.NODE_ENV === 'production';\n\napp.use(helmet());\napp.use(cors({ origin: process.env.CLIENT_ORIGIN, credentials: true }));\napp.use(express.json({ limit: '100kb' }));\napp.use(cookieParser());\n\nconst loginLimiter = rateLimit({ windowMs: 15 * 60 * 1000, max: 5 });\nconst resetLimiter = rateLimit({ windowMs: 60 * 60 * 1000, max: 3 });\nconst publicWriteLimiter = rateLimit({ windowMs: 60 * 60 * 1000, max: 10 });\n\nconst users = [];\nconst resetTokens = new Map();\n\nasync function seed() {\n if (users.length) return;\n const hash = await bcrypt.hash('DemoPass123!', 12);\n users.push({ id: '1', email: 'alice@demo.local', passwordHash: hash, name: 'Alice', role: 'user' });\n users.push({ id: '2', email: 'bob@demo.local', passwordHash: hash, name: 'Bob', role: 'user' });\n}\n\nconst loginSchema = z.object({\n email: z.string().email().max(255),\n password: z.string().min(8).max(128),\n});\n\nfunction auth(req, res, next) {\n const token = req.cookies.token;\n if (!token) return res.status(401).json({ error: 'Unauthorized' });\n try {\n req.user = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'] });\n next();\n } catch {\n return res.status(401).json({ error: 'Unauthorized' });\n }\n}\n\napp.post('/api/login', loginLimiter, async (req, res) => {\n const parsed = loginSchema.safeParse(req.body);\n if (!parsed.success) return res.status(400).json({ error: 'Invalid input' });\n const { email, password } = parsed.data;\n const user = users.find((u) => u.email === email);\n if (!user || !(await bcrypt.compare(password, user.passwordHash))) {\n return res.status(401).json({ error: 'Invalid email or password' });\n }\n const token = jwt.sign({ id: user.id, role: user.role }, process.env.JWT_SECRET, { expiresIn: '1h' });\n res.cookie('token', token, {\n httpOnly: true,\n secure: isProd,\n sameSite: 'lax',\n maxAge: 3600000,\n });\n res.json({ message: 'Login successful' });\n});\n\napp.get('/api/users/me', auth, (req, res) => {\n const user = users.find((u) => u.id === req.user.id);\n if (!user) return res.status(404).json({ error: 'Not found' });\n res.json({ id: user.id, email: user.email, name: user.name });\n});\n\napp.get('/api/search', auth, (req, res) => {\n const q = String(req.query.q || '').slice(0, 100);\n const results = users\n .filter((u) => u.email.includes(q))\n .slice(0, 20)\n .map(({ id, email, name }) => ({ id, email, name }));\n res.json({ results });\n});\n\nconst contactSchema = z.object({ message: z.string().min(1).max(2000) });\napp.post('/api/contact', publicWriteLimiter, (req, res) => {\n const parsed = contactSchema.safeParse(req.body);\n if (!parsed.success) return res.status(400).json({ error: 'Invalid input' });\n res.json({ ok: true });\n});\n\napp.post('/api/ai', auth, publicWriteLimiter, (req, res) => {\n const prompt = String(req.body.prompt || '').slice(0, 4000);\n res.json({ reply: 'demo response', length: prompt.length });\n});\n\napp.post('/api/reset', resetLimiter, (req, res) => {\n const email = String(req.body.email || '');\n const user = users.find((u) => u.email === email);\n if (user) {\n const token = crypto.randomBytes(32).toString('hex');\n resetTokens.set(token, { userId: user.id, expires: Date.now() + 900000 });\n }\n res.json({ message: 'If an account exists, a reset link was sent.' });\n});\n\napp.get('/api/admin/stats', auth, (req, res) => {\n if (req.user.role !== 'admin') return res.status(403).json({ error: 'Forbidden' });\n res.json({ users: users.length });\n});\n\napp.use((err, req, res, next) => {\n console.error('Error', { message: err.message });\n res.status(500).json({ error: isProd ? 'Internal server error' : err.message });\n});\n\nseed().then(() => app.listen(PORT, () => console.log(`Hardened demo http://localhost:${PORT}`)));"
17
+ }
@@ -0,0 +1,21 @@
1
+ # Remediation Plan: bnd-tg-auth-003-49-7c96f3
2
+ - **Rule ID:** `TG-AUTH-003`
3
+ - **Target File:** `examples/hardened-react-express/server/index.js:49`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Restricted JWT verification to explicit algorithm list ['HS256']
8
+
9
+ ## Unified Diff Preview
10
+ ```diff
11
+ --- a/examples/hardened-react-express/server/index.js
12
+ +++ b/examples/hardened-react-express/server/index.js
13
+ @@ -47,5 +47,5 @@
14
+ if (!token) return res.status(401).json({ error: 'Unauthorized' });
15
+ try {
16
+ - req.user = jwt.verify(token, process.env.JWT_SECRET);
17
+ + req.user = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'] });
18
+ next();
19
+ } catch {
20
+
21
+ ```
@@ -0,0 +1,9 @@
1
+ --- a/examples/hardened-react-express/server/index.js
2
+ +++ b/examples/hardened-react-express/server/index.js
3
+ @@ -47,5 +47,5 @@
4
+ if (!token) return res.status(401).json({ error: 'Unauthorized' });
5
+ try {
6
+ - req.user = jwt.verify(token, process.env.JWT_SECRET);
7
+ + req.user = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'] });
8
+ next();
9
+ } catch {
@@ -0,0 +1,17 @@
1
+ {
2
+ "bundle_id": "bnd-tg-input-003-53-d167b4",
3
+ "finding_id": "TG-INPUT-003-fea9421e",
4
+ "rule_id": "TG-INPUT-003",
5
+ "title": "Unsafe Dynamic Code or HTML Execution",
6
+ "target_file": "examples/vulnerable-react-express/client/src/App.jsx",
7
+ "line_number": 53,
8
+ "target_line": " <div dangerouslySetInnerHTML={{ __html: bio }} />",
9
+ "replacement_line": " <div>{bio}</div>",
10
+ "what_is_wrong": "React dangerouslySetInnerHTML rendering raw unescaped HTML",
11
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
12
+ "what_should_change": "Replaced raw dangerouslySetInnerHTML injection with safe React text interpolation",
13
+ "proposed_diff": "--- a/examples/vulnerable-react-express/client/src/App.jsx\n+++ b/examples/vulnerable-react-express/client/src/App.jsx\n@@ -51,5 +51,5 @@\n \n {/* TG-INPUT-003: Unsafe HTML rendering */}\n- <div dangerouslySetInnerHTML={{ __html: bio }} />\n+ <div>{bio}</div>\n \n <button onClick={fetchUser}>Fetch user (IDOR demo)</button>\n",
14
+ "additions": 1,
15
+ "deletions": 1,
16
+ "patched_content": "import { useState } from 'react';\nimport { clientConfig } from './config';\n\n// TG-DB-001: SQL query construction in frontend (never do this)\nfunction buildSearchQuery(email) {\n return `SELECT id, email FROM users WHERE email LIKE '%${email}%'`;\n}\n\n// TG-DB-003: Documented anti-pattern \u2014 Prisma must never run in browser\n// import { PrismaClient } from '@prisma/client'; // FORBIDDEN in client\n\nexport default function App() {\n const [email, setEmail] = useState('');\n const [password, setPassword] = useState('');\n const [bio, setBio] = useState('<img src=x onerror=alert(1)>');\n const [userId, setUserId] = useState('1');\n const [isAdmin] = useState(localStorage.getItem('role') === 'admin'); // TG-AUTH-002\n const [message, setMessage] = useState('');\n\n async function login(e) {\n e.preventDefault();\n const res = await fetch('/api/login', {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n credentials: 'include',\n body: JSON.stringify({ email, password }),\n });\n const data = await res.json();\n // TG-CLIENT-002: Sensitive console logging\n console.log('Login token:', data.token, 'config:', clientConfig);\n setMessage(JSON.stringify(data));\n }\n\n async function fetchUser() {\n const res = await fetch(`/api/users/${userId}`);\n setMessage(await res.text());\n }\n\n return (\n <div style={{ maxWidth: 560, margin: '2rem auto', fontFamily: 'sans-serif' }}>\n <h1>Vulnerable Demo</h1>\n <p style={{ color: 'crimson' }}>Intentionally insecure \u2014 localhost lab only</p>\n\n <form onSubmit={login}>\n <input value={email} onChange={(e) => setEmail(e.target.value)} placeholder=\"email\" />\n <input value={password} onChange={(e) => setPassword(e.target.value)} placeholder=\"password\" type=\"password\" />\n <button type=\"submit\">Login</button>\n </form>\n\n <p>Frontend SQL preview: {buildSearchQuery(email)}</p>\n\n {/* TG-INPUT-003: Unsafe HTML rendering */}\n <div>{bio}</div>\n\n <button onClick={fetchUser}>Fetch user (IDOR demo)</button>\n\n {/* TG-AUTH-002: Client-only admin gate */}\n {isAdmin && <section><h2>Admin Panel</h2><p>Visible if localStorage role=admin \u2014 not real security</p></section>}\n\n {message && <pre>{message}</pre>}\n </div>\n );\n}"
17
+ }
@@ -0,0 +1,21 @@
1
+ # Remediation Plan: bnd-tg-input-003-53-d167b4
2
+ - **Rule ID:** `TG-INPUT-003`
3
+ - **Target File:** `examples/vulnerable-react-express/client/src/App.jsx:53`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Replaced raw dangerouslySetInnerHTML injection with safe React text interpolation
8
+
9
+ ## Unified Diff Preview
10
+ ```diff
11
+ --- a/examples/vulnerable-react-express/client/src/App.jsx
12
+ +++ b/examples/vulnerable-react-express/client/src/App.jsx
13
+ @@ -51,5 +51,5 @@
14
+
15
+ {/* TG-INPUT-003: Unsafe HTML rendering */}
16
+ - <div dangerouslySetInnerHTML={{ __html: bio }} />
17
+ + <div>{bio}</div>
18
+
19
+ <button onClick={fetchUser}>Fetch user (IDOR demo)</button>
20
+
21
+ ```
@@ -0,0 +1,9 @@
1
+ --- a/examples/vulnerable-react-express/client/src/App.jsx
2
+ +++ b/examples/vulnerable-react-express/client/src/App.jsx
3
+ @@ -51,5 +51,5 @@
4
+
5
+ {/* TG-INPUT-003: Unsafe HTML rendering */}
6
+ - <div dangerouslySetInnerHTML={{ __html: bio }} />
7
+ + <div>{bio}</div>
8
+
9
+ <button onClick={fetchUser}>Fetch user (IDOR demo)</button>
@@ -0,0 +1,17 @@
1
+ {
2
+ "bundle_id": "bnd-tg-platform-001-12-cf8156",
3
+ "finding_id": "TG-PLATFORM-001-7dd35cb4",
4
+ "rule_id": "TG-PLATFORM-001",
5
+ "title": "Wildcard CORS With Credentials",
6
+ "target_file": "examples/vulnerable-react-express/server/index.js",
7
+ "line_number": 12,
8
+ "target_line": "app.use(cors({ origin: '*', credentials: true }));",
9
+ "replacement_line": "app.use(cors({ origin: process.env.ALLOWED_ORIGIN || 'http://localhost:5173', credentials: true }));",
10
+ "what_is_wrong": "Wildcard CORS origin configured in Express middleware",
11
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
12
+ "what_should_change": "Constrained wildcard CORS origin to process.env.ALLOWED_ORIGIN with secure fallback",
13
+ "proposed_diff": "--- a/examples/vulnerable-react-express/server/index.js\n+++ b/examples/vulnerable-react-express/server/index.js\n@@ -10,5 +10,5 @@\n \n // TG-PLATFORM-001: Wildcard CORS with credentials\n-app.use(cors({ origin: '*', credentials: true }));\n+app.use(cors({ origin: process.env.ALLOWED_ORIGIN || 'http://localhost:5173', credentials: true }));\n \n // TG-PLATFORM-004: No explicit JSON body size limit\n",
14
+ "additions": 1,
15
+ "deletions": 1,
16
+ "patched_content": "const express = require('express');\nconst cors = require('cors');\nconst jwt = require('jsonwebtoken');\n\nconst app = express();\nconst PORT = 3001;\n\n// TG-SEC-001: Hardcoded JWT secret\nconst JWT_SECRET = 'FAKE_DEMO_JWT_SECRET_NOT_FOR_PRODUCTION';\n\n// TG-PLATFORM-001: Wildcard CORS with credentials\napp.use(cors({ origin: process.env.ALLOWED_ORIGIN || 'http://localhost:5173', credentials: true }));\n\n// TG-PLATFORM-004: No explicit JSON body size limit\napp.use(express.json());\n\nconst users = [\n { id: '1', email: 'alice@demo.local', password: 'password123', name: 'Alice' },\n { id: '2', email: 'bob@demo.local', password: 'secret456', name: 'Bob' },\n];\n\n// TG-RATE-001: No rate limit on login\n// TG-AUTH-001: Plaintext password comparison\n// TG-SEC-004: Logs sensitive data\n// TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)\napp.post('/api/login', (req, res) => {\n const { email, password } = req.body;\n console.log('Login attempt:', { email, password }); // TG-SEC-004\n const user = users.find((u) => u.email === email && u.password === password);\n if (!user) return res.status(401).json({ error: 'User not found' }); // enumeration\n const token = jwt.sign({ id: user.id }, JWT_SECRET);\n res.cookie('token', token);\n res.json({ message: 'ok', token, user });\n});\n\n// TG-AUTH-003: IDOR \u2014 no ownership check\napp.get('/api/users/:id', (req, res) => {\n const user = users.find((u) => u.id === req.params.id);\n if (!user) return res.status(404).json({ error: 'Not found' });\n res.json(user);\n});\n\n// TG-INPUT-002: SQL concatenation (simulated query string)\n// TG-RATE-003: Unbounded results\napp.get('/api/search', (req, res) => {\n const q = req.query.q || '';\n const fakeSql = `SELECT * FROM users WHERE email LIKE '%${q}%'`;\n const results = users.filter((u) => u.email.includes(q));\n res.json({ query: fakeSql, results });\n});\n\n// TG-INPUT-001: No validation\n// TG-RATE-002: Unlimited contact endpoint\napp.post('/api/contact', (req, res) => {\n res.json({ received: req.body });\n});\n\n// TG-RATE-002: Unlimited AI endpoint\napp.post('/api/ai', (req, res) => {\n res.json({ reply: 'demo', prompt: req.body.prompt });\n});\n\n// TG-INPUT-004: Unrestricted upload (stub)\napp.post('/api/upload', (req, res) => {\n res.json({ saved: req.body.filename });\n});\n\n// TG-AUTH-005: Unsafe password reset\napp.post('/api/reset', (req, res) => {\n const { email } = req.body;\n const user = users.find((u) => u.email === email);\n if (!user) return res.status(404).json({ error: 'Email not registered' }); // enumeration\n const token = `reset-${user.id}-12345`; // predictable\n res.json({ resetToken: token });\n});\n\napp.use((err, req, res, next) => {\n // TG-PLATFORM-003: Stack trace exposed\n res.status(500).json({ error: err.message, stack: err.stack });\n});\n\napp.listen(PORT, () => console.log(`Vulnerable demo server http://localhost:${PORT}`));"
17
+ }
@@ -0,0 +1,21 @@
1
+ # Remediation Plan: bnd-tg-platform-001-12-cf8156
2
+ - **Rule ID:** `TG-PLATFORM-001`
3
+ - **Target File:** `examples/vulnerable-react-express/server/index.js:12`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Constrained wildcard CORS origin to process.env.ALLOWED_ORIGIN with secure fallback
8
+
9
+ ## Unified Diff Preview
10
+ ```diff
11
+ --- a/examples/vulnerable-react-express/server/index.js
12
+ +++ b/examples/vulnerable-react-express/server/index.js
13
+ @@ -10,5 +10,5 @@
14
+
15
+ // TG-PLATFORM-001: Wildcard CORS with credentials
16
+ -app.use(cors({ origin: '*', credentials: true }));
17
+ +app.use(cors({ origin: process.env.ALLOWED_ORIGIN || 'http://localhost:5173', credentials: true }));
18
+
19
+ // TG-PLATFORM-004: No explicit JSON body size limit
20
+
21
+ ```
@@ -0,0 +1,9 @@
1
+ --- a/examples/vulnerable-react-express/server/index.js
2
+ +++ b/examples/vulnerable-react-express/server/index.js
3
+ @@ -10,5 +10,5 @@
4
+
5
+ // TG-PLATFORM-001: Wildcard CORS with credentials
6
+ -app.use(cors({ origin: '*', credentials: true }));
7
+ +app.use(cors({ origin: process.env.ALLOWED_ORIGIN || 'http://localhost:5173', credentials: true }));
8
+
9
+ // TG-PLATFORM-004: No explicit JSON body size limit
@@ -0,0 +1,17 @@
1
+ {
2
+ "bundle_id": "bnd-tg-rate-001-26-affcfa",
3
+ "finding_id": "TG-RATE-001-dcd0a3c7",
4
+ "rule_id": "TG-RATE-001",
5
+ "title": "Unlimited Authentication Endpoint",
6
+ "target_file": "examples/vulnerable-react-express/server/index.js",
7
+ "line_number": 26,
8
+ "target_line": "app.post('/api/login', (req, res) => {",
9
+ "replacement_line": "app.post('/api/login', authLimiter, (req, res) => {",
10
+ "what_is_wrong": "Authentication POST endpoint defined without rate-limiting middleware",
11
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
12
+ "what_should_change": "Injected authLimiter rate-limiting middleware to protect authentication endpoint from brute force",
13
+ "proposed_diff": "--- a/examples/vulnerable-react-express/server/index.js\n+++ b/examples/vulnerable-react-express/server/index.js\n@@ -24,5 +24,5 @@\n // TG-SEC-004: Logs sensitive data\n // TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)\n-app.post('/api/login', (req, res) => {\n+app.post('/api/login', authLimiter, (req, res) => {\n const { email, password } = req.body;\n console.log('Login attempt:', { email, password }); // TG-SEC-004\n",
14
+ "additions": 1,
15
+ "deletions": 1,
16
+ "patched_content": "const express = require('express');\nconst cors = require('cors');\nconst jwt = require('jsonwebtoken');\n\nconst app = express();\nconst PORT = 3001;\n\n// TG-SEC-001: Hardcoded JWT secret\nconst JWT_SECRET = 'FAKE_DEMO_JWT_SECRET_NOT_FOR_PRODUCTION';\n\n// TG-PLATFORM-001: Wildcard CORS with credentials\napp.use(cors({ origin: '*', credentials: true }));\n\n// TG-PLATFORM-004: No explicit JSON body size limit\napp.use(express.json());\n\nconst users = [\n { id: '1', email: 'alice@demo.local', password: 'password123', name: 'Alice' },\n { id: '2', email: 'bob@demo.local', password: 'secret456', name: 'Bob' },\n];\n\n// TG-RATE-001: No rate limit on login\n// TG-AUTH-001: Plaintext password comparison\n// TG-SEC-004: Logs sensitive data\n// TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)\napp.post('/api/login', authLimiter, (req, res) => {\n const { email, password } = req.body;\n console.log('Login attempt:', { email, password }); // TG-SEC-004\n const user = users.find((u) => u.email === email && u.password === password);\n if (!user) return res.status(401).json({ error: 'User not found' }); // enumeration\n const token = jwt.sign({ id: user.id }, JWT_SECRET);\n res.cookie('token', token);\n res.json({ message: 'ok', token, user });\n});\n\n// TG-AUTH-003: IDOR \u2014 no ownership check\napp.get('/api/users/:id', (req, res) => {\n const user = users.find((u) => u.id === req.params.id);\n if (!user) return res.status(404).json({ error: 'Not found' });\n res.json(user);\n});\n\n// TG-INPUT-002: SQL concatenation (simulated query string)\n// TG-RATE-003: Unbounded results\napp.get('/api/search', (req, res) => {\n const q = req.query.q || '';\n const fakeSql = `SELECT * FROM users WHERE email LIKE '%${q}%'`;\n const results = users.filter((u) => u.email.includes(q));\n res.json({ query: fakeSql, results });\n});\n\n// TG-INPUT-001: No validation\n// TG-RATE-002: Unlimited contact endpoint\napp.post('/api/contact', (req, res) => {\n res.json({ received: req.body });\n});\n\n// TG-RATE-002: Unlimited AI endpoint\napp.post('/api/ai', (req, res) => {\n res.json({ reply: 'demo', prompt: req.body.prompt });\n});\n\n// TG-INPUT-004: Unrestricted upload (stub)\napp.post('/api/upload', (req, res) => {\n res.json({ saved: req.body.filename });\n});\n\n// TG-AUTH-005: Unsafe password reset\napp.post('/api/reset', (req, res) => {\n const { email } = req.body;\n const user = users.find((u) => u.email === email);\n if (!user) return res.status(404).json({ error: 'Email not registered' }); // enumeration\n const token = `reset-${user.id}-12345`; // predictable\n res.json({ resetToken: token });\n});\n\napp.use((err, req, res, next) => {\n // TG-PLATFORM-003: Stack trace exposed\n res.status(500).json({ error: err.message, stack: err.stack });\n});\n\napp.listen(PORT, () => console.log(`Vulnerable demo server http://localhost:${PORT}`));"
17
+ }