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,17 @@
1
+ {
2
+ "bundle_id": "bnd-tg-platform-002-17-876973",
3
+ "finding_id": "TG-PLATFORM-002-1f383dcf",
4
+ "rule_id": "TG-PLATFORM-002",
5
+ "title": "Missing Security Headers",
6
+ "target_file": "examples/hardened-react-express/server/index.js",
7
+ "line_number": 17,
8
+ "target_line": "const app = express();",
9
+ "replacement_line": "const helmet = require(\"helmet\");\nconst app = express();\napp.use(helmet());",
10
+ "what_is_wrong": "Express application initialized without helmet security headers middleware",
11
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
12
+ "what_should_change": "Injected helmet security headers middleware into Express application",
13
+ "proposed_diff": "--- a/examples/hardened-react-express/server/index.js\n+++ b/examples/hardened-react-express/server/index.js\n@@ -15,5 +15,5 @@\n }\n \n-const app = express();\n+const helmet = require(\"helmet\");\nconst app = express();\napp.use(helmet());\n const PORT = 3001;\n const isProd = process.env.NODE_ENV === 'production';\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 helmet = require(\"helmet\");\nconst app = express();\napp.use(helmet());\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,23 @@
1
+ # Remediation Plan: bnd-tg-platform-002-17-876973
2
+ - **Rule ID:** `TG-PLATFORM-002`
3
+ - **Target File:** `examples/hardened-react-express/server/index.js:17`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Injected helmet security headers middleware into Express application
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
+ @@ -15,5 +15,5 @@
14
+ }
15
+
16
+ -const app = express();
17
+ +const helmet = require("helmet");
18
+ const app = express();
19
+ app.use(helmet());
20
+ const PORT = 3001;
21
+ const isProd = process.env.NODE_ENV === 'production';
22
+
23
+ ```
@@ -0,0 +1,11 @@
1
+ --- a/examples/hardened-react-express/server/index.js
2
+ +++ b/examples/hardened-react-express/server/index.js
3
+ @@ -15,5 +15,5 @@
4
+ }
5
+
6
+ -const app = express();
7
+ +const helmet = require("helmet");
8
+ const app = express();
9
+ app.use(helmet());
10
+ const PORT = 3001;
11
+ const isProd = process.env.NODE_ENV === 'production';
@@ -0,0 +1,17 @@
1
+ {
2
+ "bundle_id": "bnd-tg-platform-002-5-40c794",
3
+ "finding_id": "TG-PLATFORM-002-eef342ec",
4
+ "rule_id": "TG-PLATFORM-002",
5
+ "title": "Missing Security Headers",
6
+ "target_file": "examples/vulnerable-react-express/server/index.js",
7
+ "line_number": 5,
8
+ "target_line": "const app = express();",
9
+ "replacement_line": "const helmet = require(\"helmet\");\nconst app = express();\napp.use(helmet());",
10
+ "what_is_wrong": "Express application initialized without helmet security headers middleware",
11
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
12
+ "what_should_change": "Injected helmet security headers middleware into Express application",
13
+ "proposed_diff": "--- a/examples/vulnerable-react-express/server/index.js\n+++ b/examples/vulnerable-react-express/server/index.js\n@@ -3,5 +3,5 @@\n const jwt = require('jsonwebtoken');\n \n-const app = express();\n+const helmet = require(\"helmet\");\nconst app = express();\napp.use(helmet());\n const PORT = 3001;\n \n",
14
+ "additions": 1,
15
+ "deletions": 1,
16
+ "patched_content": "const express = require('express');\nconst cors = require('cors');\nconst jwt = require('jsonwebtoken');\n\nconst helmet = require(\"helmet\");\nconst app = express();\napp.use(helmet());\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', (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,23 @@
1
+ # Remediation Plan: bnd-tg-platform-002-5-40c794
2
+ - **Rule ID:** `TG-PLATFORM-002`
3
+ - **Target File:** `examples/vulnerable-react-express/server/index.js:5`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Injected helmet security headers middleware into Express application
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
+ @@ -3,5 +3,5 @@
14
+ const jwt = require('jsonwebtoken');
15
+
16
+ -const app = express();
17
+ +const helmet = require("helmet");
18
+ const app = express();
19
+ app.use(helmet());
20
+ const PORT = 3001;
21
+
22
+
23
+ ```
@@ -0,0 +1,11 @@
1
+ --- a/examples/vulnerable-react-express/server/index.js
2
+ +++ b/examples/vulnerable-react-express/server/index.js
3
+ @@ -3,5 +3,5 @@
4
+ const jwt = require('jsonwebtoken');
5
+
6
+ -const app = express();
7
+ +const helmet = require("helmet");
8
+ const app = express();
9
+ app.use(helmet());
10
+ const PORT = 3001;
11
+
@@ -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
+ }
@@ -0,0 +1,21 @@
1
+ # Remediation Plan: bnd-tg-rate-001-26-affcfa
2
+ - **Rule ID:** `TG-RATE-001`
3
+ - **Target File:** `examples/vulnerable-react-express/server/index.js:26`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Injected authLimiter rate-limiting middleware to protect authentication endpoint from brute force
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
+ @@ -24,5 +24,5 @@
14
+ // TG-SEC-004: Logs sensitive data
15
+ // TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)
16
+ -app.post('/api/login', (req, res) => {
17
+ +app.post('/api/login', authLimiter, (req, res) => {
18
+ const { email, password } = req.body;
19
+ console.log('Login attempt:', { email, password }); // TG-SEC-004
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
+ @@ -24,5 +24,5 @@
4
+ // TG-SEC-004: Logs sensitive data
5
+ // TG-AUTH-004: Insecure cookie (no httpOnly/Secure/SameSite)
6
+ -app.post('/api/login', (req, res) => {
7
+ +app.post('/api/login', authLimiter, (req, res) => {
8
+ const { email, password } = req.body;
9
+ console.log('Login attempt:', { email, password }); // TG-SEC-004
@@ -0,0 +1,17 @@
1
+ {
2
+ "bundle_id": "bnd-tg-rate-002-54-0b38d2",
3
+ "finding_id": "TG-RATE-002-d67d7c98",
4
+ "rule_id": "TG-RATE-002",
5
+ "title": "Unlimited Public Write Endpoint",
6
+ "target_file": "examples/vulnerable-react-express/server/index.js",
7
+ "line_number": 54,
8
+ "target_line": "app.post('/api/contact', (req, res) => {",
9
+ "replacement_line": "app.post('/api/contact', writeLimiter, (req, res) => {",
10
+ "what_is_wrong": "Public submission endpoint defined without rate-limiting or captcha defense",
11
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
12
+ "what_should_change": "Injected writeLimiter rate-limiting middleware to public write endpoint",
13
+ "proposed_diff": "--- a/examples/vulnerable-react-express/server/index.js\n+++ b/examples/vulnerable-react-express/server/index.js\n@@ -52,5 +52,5 @@\n // TG-INPUT-001: No validation\n // TG-RATE-002: Unlimited contact endpoint\n-app.post('/api/contact', (req, res) => {\n+app.post('/api/contact', writeLimiter, (req, res) => {\n res.json({ received: req.body });\n });\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', (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', writeLimiter, (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-rate-002-54-0b38d2
2
+ - **Rule ID:** `TG-RATE-002`
3
+ - **Target File:** `examples/vulnerable-react-express/server/index.js:54`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Injected writeLimiter rate-limiting middleware to public write endpoint
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
+ @@ -52,5 +52,5 @@
14
+ // TG-INPUT-001: No validation
15
+ // TG-RATE-002: Unlimited contact endpoint
16
+ -app.post('/api/contact', (req, res) => {
17
+ +app.post('/api/contact', writeLimiter, (req, res) => {
18
+ res.json({ received: req.body });
19
+ });
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
+ @@ -52,5 +52,5 @@
4
+ // TG-INPUT-001: No validation
5
+ // TG-RATE-002: Unlimited contact endpoint
6
+ -app.post('/api/contact', (req, res) => {
7
+ +app.post('/api/contact', writeLimiter, (req, res) => {
8
+ res.json({ received: req.body });
9
+ });
@@ -0,0 +1,17 @@
1
+ {
2
+ "bundle_id": "bnd-tg-sec-001-18-a3c1e8",
3
+ "finding_id": "TG-SEC-001-c393d596",
4
+ "rule_id": "TG-SEC-001",
5
+ "title": "Hardcoded Secret or API Key in Tracked Source",
6
+ "target_file": "examples/vulnerable-react-express/server/index.js",
7
+ "line_number": 18,
8
+ "target_line": " { id: '1', email: 'alice@demo.local', password: 'password123', name: 'Alice' },",
9
+ "replacement_line": " { id: '1', email: 'alice@demo.local', password: process.env.DEMO_USER_PASSWORD || \"REDACTED_PASSWORD\", name: 'Alice' },",
10
+ "what_is_wrong": "Hardcoded credential or API secret string",
11
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
12
+ "what_should_change": "Replaced hardcoded password with environment variable process.env.DEMO_USER_PASSWORD",
13
+ "proposed_diff": "--- a/examples/vulnerable-react-express/server/index.js\n+++ b/examples/vulnerable-react-express/server/index.js\n@@ -16,5 +16,5 @@\n \n const users = [\n- { id: '1', email: 'alice@demo.local', password: 'password123', name: 'Alice' },\n+ { id: '1', email: 'alice@demo.local', password: process.env.DEMO_USER_PASSWORD || \"REDACTED_PASSWORD\", name: 'Alice' },\n { id: '2', email: 'bob@demo.local', password: 'secret456', name: 'Bob' },\n ];\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: process.env.DEMO_USER_PASSWORD || \"REDACTED_PASSWORD\", 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-sec-001-18-a3c1e8
2
+ - **Rule ID:** `TG-SEC-001`
3
+ - **Target File:** `examples/vulnerable-react-express/server/index.js:18`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Replaced hardcoded password with environment variable process.env.DEMO_USER_PASSWORD
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
+ @@ -16,5 +16,5 @@
14
+
15
+ const users = [
16
+ - { id: '1', email: 'alice@demo.local', password: 'password123', name: 'Alice' },
17
+ + { id: '1', email: 'alice@demo.local', password: process.env.DEMO_USER_PASSWORD || "REDACTED_PASSWORD", name: 'Alice' },
18
+ { id: '2', email: 'bob@demo.local', password: 'secret456', name: 'Bob' },
19
+ ];
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
+ @@ -16,5 +16,5 @@
4
+
5
+ const users = [
6
+ - { id: '1', email: 'alice@demo.local', password: 'password123', name: 'Alice' },
7
+ + { id: '1', email: 'alice@demo.local', password: process.env.DEMO_USER_PASSWORD || "REDACTED_PASSWORD", name: 'Alice' },
8
+ { id: '2', email: 'bob@demo.local', password: 'secret456', name: 'Bob' },
9
+ ];
@@ -0,0 +1,17 @@
1
+ {
2
+ "bundle_id": "bnd-tg-sec-001-9-e22e50",
3
+ "finding_id": "TG-SEC-001-bb5e4b77",
4
+ "rule_id": "TG-SEC-001",
5
+ "title": "Hardcoded Secret or API Key in Tracked Source",
6
+ "target_file": "examples/vulnerable-react-express/server/index.js",
7
+ "line_number": 9,
8
+ "target_line": "const JWT_SECRET = 'FAKE_DEMO_JWT_SECRET_NOT_FOR_PRODUCTION';",
9
+ "replacement_line": "const JWT_SECRET = process.env.JWT_SECRET || \"\";",
10
+ "what_is_wrong": "Hardcoded JWT signing secret",
11
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
12
+ "what_should_change": "Migrated hardcoded JWT secret to environment variable process.env.JWT_SECRET",
13
+ "proposed_diff": "--- a/examples/vulnerable-react-express/server/index.js\n+++ b/examples/vulnerable-react-express/server/index.js\n@@ -7,5 +7,5 @@\n \n // TG-SEC-001: Hardcoded JWT secret\n-const JWT_SECRET = 'FAKE_DEMO_JWT_SECRET_NOT_FOR_PRODUCTION';\n+const JWT_SECRET = process.env.JWT_SECRET || \"\";\n \n // TG-PLATFORM-001: Wildcard CORS with credentials\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 = process.env.JWT_SECRET || \"\";\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', (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-sec-001-9-e22e50
2
+ - **Rule ID:** `TG-SEC-001`
3
+ - **Target File:** `examples/vulnerable-react-express/server/index.js:9`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Migrated hardcoded JWT secret to environment variable process.env.JWT_SECRET
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
+ @@ -7,5 +7,5 @@
14
+
15
+ // TG-SEC-001: Hardcoded JWT secret
16
+ -const JWT_SECRET = 'FAKE_DEMO_JWT_SECRET_NOT_FOR_PRODUCTION';
17
+ +const JWT_SECRET = process.env.JWT_SECRET || "";
18
+
19
+ // TG-PLATFORM-001: Wildcard CORS with credentials
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
+ @@ -7,5 +7,5 @@
4
+
5
+ // TG-SEC-001: Hardcoded JWT secret
6
+ -const JWT_SECRET = 'FAKE_DEMO_JWT_SECRET_NOT_FOR_PRODUCTION';
7
+ +const JWT_SECRET = process.env.JWT_SECRET || "";
8
+
9
+ // TG-PLATFORM-001: Wildcard CORS with credentials
@@ -0,0 +1,17 @@
1
+ {
2
+ "bundle_id": "bnd-tg-sec-004-28-a1a0a1",
3
+ "finding_id": "TG-SEC-004-08753da5",
4
+ "rule_id": "TG-SEC-004",
5
+ "title": "Sensitive Information in Logs",
6
+ "target_file": "examples/vulnerable-react-express/server/index.js",
7
+ "line_number": 28,
8
+ "target_line": " console.log('Login attempt:', { email, password }); // TG-SEC-004",
9
+ "replacement_line": " // Security: Sensitive credential log removed per TG-SEC-004",
10
+ "what_is_wrong": "Plaintext credential or token logged to output sink",
11
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
12
+ "what_should_change": "Redacted console logging of sensitive token or credential",
13
+ "proposed_diff": "--- a/examples/vulnerable-react-express/server/index.js\n+++ b/examples/vulnerable-react-express/server/index.js\n@@ -26,5 +26,5 @@\n app.post('/api/login', (req, res) => {\n const { email, password } = req.body;\n- console.log('Login attempt:', { email, password }); // TG-SEC-004\n+ // Security: Sensitive credential log removed per 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",
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', (req, res) => {\n const { email, password } = req.body;\n // Security: Sensitive credential log removed per 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-sec-004-28-a1a0a1
2
+ - **Rule ID:** `TG-SEC-004`
3
+ - **Target File:** `examples/vulnerable-react-express/server/index.js:28`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Redacted console logging of sensitive token or credential
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
+ @@ -26,5 +26,5 @@
14
+ app.post('/api/login', (req, res) => {
15
+ const { email, password } = req.body;
16
+ - console.log('Login attempt:', { email, password }); // TG-SEC-004
17
+ + // Security: Sensitive credential log removed per TG-SEC-004
18
+ const user = users.find((u) => u.email === email && u.password === password);
19
+ if (!user) return res.status(401).json({ error: 'User not found' }); // enumeration
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
+ @@ -26,5 +26,5 @@
4
+ app.post('/api/login', (req, res) => {
5
+ const { email, password } = req.body;
6
+ - console.log('Login attempt:', { email, password }); // TG-SEC-004
7
+ + // Security: Sensitive credential log removed per TG-SEC-004
8
+ const user = users.find((u) => u.email === email && u.password === password);
9
+ if (!user) return res.status(401).json({ error: 'User not found' }); // enumeration
@@ -0,0 +1,17 @@
1
+ {
2
+ "bundle_id": "bnd-tg-sec-004-30-00569e",
3
+ "finding_id": "TG-SEC-004-dbbc17f7",
4
+ "rule_id": "TG-SEC-004",
5
+ "title": "Sensitive Information in Logs",
6
+ "target_file": "examples/vulnerable-react-express/client/src/App.jsx",
7
+ "line_number": 30,
8
+ "target_line": " console.log('Login token:', data.token, 'config:', clientConfig);",
9
+ "replacement_line": " // Security: Sensitive credential log removed per TG-SEC-004",
10
+ "what_is_wrong": "Plaintext credential or token logged to output sink",
11
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
12
+ "what_should_change": "Redacted console logging of sensitive token or credential",
13
+ "proposed_diff": "--- a/examples/vulnerable-react-express/client/src/App.jsx\n+++ b/examples/vulnerable-react-express/client/src/App.jsx\n@@ -28,5 +28,5 @@\n const data = await res.json();\n // TG-CLIENT-002: Sensitive console logging\n- console.log('Login token:', data.token, 'config:', clientConfig);\n+ // Security: Sensitive credential log removed per TG-SEC-004\n setMessage(JSON.stringify(data));\n }\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 // Security: Sensitive credential log removed per TG-SEC-004\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 dangerouslySetInnerHTML={{ __html: bio }} />\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-sec-004-30-00569e
2
+ - **Rule ID:** `TG-SEC-004`
3
+ - **Target File:** `examples/vulnerable-react-express/client/src/App.jsx:30`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Redacted console logging of sensitive token or credential
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
+ @@ -28,5 +28,5 @@
14
+ const data = await res.json();
15
+ // TG-CLIENT-002: Sensitive console logging
16
+ - console.log('Login token:', data.token, 'config:', clientConfig);
17
+ + // Security: Sensitive credential log removed per TG-SEC-004
18
+ setMessage(JSON.stringify(data));
19
+ }
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
+ @@ -28,5 +28,5 @@
4
+ const data = await res.json();
5
+ // TG-CLIENT-002: Sensitive console logging
6
+ - console.log('Login token:', data.token, 'config:', clientConfig);
7
+ + // Security: Sensitive credential log removed per TG-SEC-004
8
+ setMessage(JSON.stringify(data));
9
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "bundle_id": "bnd-tg-ssrf-004-9-9803ad",
3
+ "finding_id": "TG-SSRF-004-d8472223",
4
+ "rule_id": "TG-SSRF-004",
5
+ "title": "Unbounded Outbound Request Without Timeout",
6
+ "target_file": "examples/python/fastapi-vuln/main.py",
7
+ "line_number": 9,
8
+ "target_line": " response = requests.get(url)",
9
+ "replacement_line": " response = requests.get(url, timeout=10)",
10
+ "what_is_wrong": "Python requests call without explicit timeout parameter",
11
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
12
+ "what_should_change": "Injected explicit 10-second request timeout to prevent resource exhaustion",
13
+ "proposed_diff": "--- a/examples/python/fastapi-vuln/main.py\n+++ b/examples/python/fastapi-vuln/main.py\n@@ -7,5 +7,5 @@\n @app.get(\"/fetch\")\n def fetch_url(url: str):\n- response = requests.get(url)\n+ response = requests.get(url, timeout=10)\n return {\"status\": response.status_code, \"content\": response.text}\n \n",
14
+ "additions": 1,
15
+ "deletions": 1,
16
+ "patched_content": "from fastapi import FastAPI\nimport requests\n\napp = FastAPI()\n\n# \u274c TG-SSRF-001: Unvalidated outbound URL fetching\n@app.get(\"/fetch\")\ndef fetch_url(url: str):\n response = requests.get(url, timeout=10)\n return {\"status\": response.status_code, \"content\": response.text}\n\n# \u274c TG-WEBHOOK-001: Unverified webhook payload\n@app.post(\"/webhook\")\ndef receive_webhook(payload: dict):\n return {\"status\": \"success\", \"data\": payload}\n\n# \u274c TG-AUTH-006: Unfiltered dict mass assignment\n@app.post(\"/update_profile\")\ndef update_profile(user_id: int, updates: dict):\n return {\"status\": \"updated\", \"user_id\": user_id, \"updates\": updates}"
17
+ }
@@ -0,0 +1,21 @@
1
+ # Remediation Plan: bnd-tg-ssrf-004-9-9803ad
2
+ - **Rule ID:** `TG-SSRF-004`
3
+ - **Target File:** `examples/python/fastapi-vuln/main.py:9`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Injected explicit 10-second request timeout to prevent resource exhaustion
8
+
9
+ ## Unified Diff Preview
10
+ ```diff
11
+ --- a/examples/python/fastapi-vuln/main.py
12
+ +++ b/examples/python/fastapi-vuln/main.py
13
+ @@ -7,5 +7,5 @@
14
+ @app.get("/fetch")
15
+ def fetch_url(url: str):
16
+ - response = requests.get(url)
17
+ + response = requests.get(url, timeout=10)
18
+ return {"status": response.status_code, "content": response.text}
19
+
20
+
21
+ ```
@@ -0,0 +1,9 @@
1
+ --- a/examples/python/fastapi-vuln/main.py
2
+ +++ b/examples/python/fastapi-vuln/main.py
3
+ @@ -7,5 +7,5 @@
4
+ @app.get("/fetch")
5
+ def fetch_url(url: str):
6
+ - response = requests.get(url)
7
+ + response = requests.get(url, timeout=10)
8
+ return {"status": response.status_code, "content": response.text}
9
+