torusguard 1.3.0 → 1.3.2

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 (378) hide show
  1. package/.torusguard/.manifest.json +113 -9
  2. package/.torusguard/rules/README.md +93 -62
  3. package/.torusguard/rules/TG-AUTH-001-weak-password-storage.md +103 -0
  4. package/.torusguard/rules/TG-AUTH-002-client-only-authorization.md +85 -0
  5. package/.torusguard/rules/TG-AUTH-003-missing-object-authorization.md +85 -0
  6. package/.torusguard/rules/TG-AUTH-004-insecure-session-cookie.md +96 -0
  7. package/.torusguard/rules/TG-AUTH-005-unsafe-password-reset.md +104 -0
  8. package/.torusguard/rules/TG-CLIENT-001-public-production-source-maps.md +102 -0
  9. package/.torusguard/rules/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
  10. package/.torusguard/rules/TG-DB-001-frontend-database-query.md +83 -0
  11. package/.torusguard/rules/TG-DB-002-privileged-database-credential.md +86 -0
  12. package/.torusguard/rules/TG-DB-003-frontend-admin-sdk.md +91 -0
  13. package/.torusguard/rules/TG-DB-004-missing-tenant-query-isolation.md +103 -0
  14. package/.torusguard/rules/TG-INPUT-001-missing-server-validation.md +98 -0
  15. package/.torusguard/rules/TG-INPUT-002-raw-sql-concatenation.md +94 -0
  16. package/.torusguard/rules/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
  17. package/.torusguard/rules/TG-INPUT-004-unrestricted-file-upload.md +92 -0
  18. package/.torusguard/rules/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
  19. package/.torusguard/rules/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
  20. package/.torusguard/rules/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
  21. package/.torusguard/rules/TG-PLATFORM-002-missing-security-headers.md +95 -0
  22. package/.torusguard/rules/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
  23. package/.torusguard/rules/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
  24. package/.torusguard/rules/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
  25. package/.torusguard/rules/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
  26. package/.torusguard/rules/TG-RATE-003-unbounded-resource-consumption.md +105 -0
  27. package/.torusguard/rules/TG-SEC-001-hardcoded-secrets.md +83 -0
  28. package/.torusguard/rules/TG-SEC-002-public-environment-secrets.md +83 -0
  29. package/.torusguard/rules/TG-SEC-003-tracked-env-file.md +79 -0
  30. package/.torusguard/rules/TG-SEC-004-sensitive-logging.md +83 -0
  31. package/.torusguard/rules/active/TG-AUTH-001-weak-password-storage.md +103 -0
  32. package/.torusguard/rules/active/TG-AUTH-002-client-only-authorization.md +85 -0
  33. package/.torusguard/rules/active/TG-AUTH-003-missing-object-authorization.md +85 -0
  34. package/.torusguard/rules/active/TG-AUTH-004-insecure-session-cookie.md +96 -0
  35. package/.torusguard/rules/active/TG-AUTH-005-unsafe-password-reset.md +104 -0
  36. package/.torusguard/rules/active/TG-CLIENT-001-public-production-source-maps.md +102 -0
  37. package/.torusguard/rules/active/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
  38. package/.torusguard/rules/active/TG-DB-001-frontend-database-query.md +83 -0
  39. package/.torusguard/rules/active/TG-DB-002-privileged-database-credential.md +86 -0
  40. package/.torusguard/rules/active/TG-DB-003-frontend-admin-sdk.md +91 -0
  41. package/.torusguard/rules/active/TG-DB-004-missing-tenant-query-isolation.md +103 -0
  42. package/.torusguard/rules/active/TG-INPUT-001-missing-server-validation.md +98 -0
  43. package/.torusguard/rules/active/TG-INPUT-002-raw-sql-concatenation.md +94 -0
  44. package/.torusguard/rules/active/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
  45. package/.torusguard/rules/active/TG-INPUT-004-unrestricted-file-upload.md +92 -0
  46. package/.torusguard/rules/active/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
  47. package/.torusguard/rules/active/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
  48. package/.torusguard/rules/active/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
  49. package/.torusguard/rules/active/TG-PLATFORM-002-missing-security-headers.md +95 -0
  50. package/.torusguard/rules/active/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
  51. package/.torusguard/rules/active/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
  52. package/.torusguard/rules/active/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
  53. package/.torusguard/rules/active/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
  54. package/.torusguard/rules/active/TG-RATE-003-unbounded-resource-consumption.md +105 -0
  55. package/.torusguard/rules/active/TG-SEC-001-hardcoded-secrets.md +83 -0
  56. package/.torusguard/rules/active/TG-SEC-002-public-environment-secrets.md +83 -0
  57. package/.torusguard/rules/active/TG-SEC-003-tracked-env-file.md +79 -0
  58. package/.torusguard/rules/active/TG-SEC-004-sensitive-logging.md +83 -0
  59. package/.torusguard/rules/agent/TG-AGENT-001-prompt-injection-system-context.md +56 -0
  60. package/.torusguard/rules/agent/TG-AGENT-002-unsafe-tool-dispatch-unsandboxed-execution.md +68 -0
  61. package/.torusguard/rules/agent/TG-AGENT-003-broad-mcp-tool-scoping.md +53 -0
  62. package/.torusguard/rules/agent/TG-AGENT-004-persistent-memory-cross-session-leakage.md +67 -0
  63. package/.torusguard/rules/authorization/TG-AUTH-006-mass-assignment.md +70 -0
  64. package/.torusguard/rules/authorization/TG-AUTH-007-missing-property-level-authorization.md +71 -0
  65. package/.torusguard/rules/authorization/TG-AUTH-008-untrusted-role-header-injection.md +112 -0
  66. package/.torusguard/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +37 -0
  67. package/.torusguard/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +37 -0
  68. package/.torusguard/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +37 -0
  69. package/.torusguard/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +37 -0
  70. package/.torusguard/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +37 -0
  71. package/.torusguard/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +37 -0
  72. package/.torusguard/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +37 -0
  73. package/.torusguard/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +37 -0
  74. package/.torusguard/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +37 -0
  75. package/.torusguard/rules/edge/TG-EDGE-001-serverless-global-state-leak.md +83 -0
  76. package/.torusguard/rules/edge/TG-EDGE-003-aws-lambda-ephemeral-cold-start.md +76 -0
  77. package/.torusguard/rules/graphql/TG-GQL-001-missing-query-depth-or-complexity-limits.md +64 -0
  78. package/.torusguard/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +37 -0
  79. package/.torusguard/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +37 -0
  80. package/.torusguard/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +37 -0
  81. package/.torusguard/rules/secrets/TG-SEC-005-secret-in-git-history.md +37 -0
  82. package/.torusguard/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +37 -0
  83. package/.torusguard/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +37 -0
  84. package/.torusguard/rules/ssrf/TG-SSRF-001-user-controlled-server-side-url-fetch.md +68 -0
  85. package/.torusguard/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +37 -0
  86. package/.torusguard/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +37 -0
  87. package/.torusguard/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +37 -0
  88. package/.torusguard/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +37 -0
  89. package/.torusguard/rules/supply-chain/TG-SUPPLY-002-vulnerable-dependency-review-missing.md +94 -0
  90. package/.torusguard/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +37 -0
  91. package/.torusguard/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +37 -0
  92. package/.torusguard/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +37 -0
  93. package/.torusguard/rules/supply-chain/TG-SUPPLY-006-container-build-secret-persistence.md +61 -0
  94. package/.torusguard/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +37 -0
  95. package/.torusguard/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +37 -0
  96. package/.torusguard/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +37 -0
  97. package/.torusguard/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +37 -0
  98. package/.torusguard/rules/websocket/TG-WS-001-unauthenticated-websocket-handshake.md +82 -0
  99. package/.torusguard/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +37 -0
  100. package/.torusguard/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +37 -0
  101. package/.torusguard/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +37 -0
  102. package/.torusguard/runs/report-latest.html +62 -20
  103. package/.torusguard/runs/run-20260908-112648-audit/findings.json +1520 -0
  104. package/.torusguard/runs/run-20260908-112648-audit/findings.md +560 -0
  105. package/.torusguard/runs/run-20260908-112648-audit/manifest.json +12 -0
  106. package/.torusguard/runs/run-20260908-112648-audit/summary.md +5 -0
  107. package/.torusguard/runs/run-20260908-112722-audit/findings.json +1520 -0
  108. package/.torusguard/runs/run-20260908-112722-audit/findings.md +560 -0
  109. package/.torusguard/runs/run-20260908-112722-audit/manifest.json +12 -0
  110. package/.torusguard/runs/run-20260908-112722-audit/summary.md +5 -0
  111. package/.torusguard/runs/run-20260908-113004-audit/findings.json +1520 -0
  112. package/.torusguard/runs/run-20260908-113004-audit/findings.md +560 -0
  113. package/.torusguard/runs/run-20260908-113004-audit/manifest.json +12 -0
  114. package/.torusguard/runs/run-20260908-113004-audit/summary.md +5 -0
  115. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-115-9a059e/metadata.json +15 -0
  116. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-115-9a059e/minimal_patch_plan.md +21 -0
  117. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-115-9a059e/patch.diff +9 -0
  118. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-119-61557c/metadata.json +15 -0
  119. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-119-61557c/minimal_patch_plan.md +21 -0
  120. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-119-61557c/patch.diff +9 -0
  121. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-265-996ca3/metadata.json +15 -0
  122. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-265-996ca3/minimal_patch_plan.md +21 -0
  123. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-265-996ca3/patch.diff +9 -0
  124. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-334-cb819d/metadata.json +15 -0
  125. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-334-cb819d/minimal_patch_plan.md +21 -0
  126. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-334-cb819d/patch.diff +9 -0
  127. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-503-d11cf8/metadata.json +15 -0
  128. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-503-d11cf8/minimal_patch_plan.md +21 -0
  129. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-503-d11cf8/patch.diff +9 -0
  130. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-79-91f41f/metadata.json +15 -0
  131. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-79-91f41f/minimal_patch_plan.md +21 -0
  132. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-db-004-79-91f41f/patch.diff +9 -0
  133. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-107-516a40/metadata.json +15 -0
  134. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-107-516a40/minimal_patch_plan.md +21 -0
  135. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-107-516a40/patch.diff +9 -0
  136. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-128-7809a1/metadata.json +15 -0
  137. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-128-7809a1/minimal_patch_plan.md +21 -0
  138. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-128-7809a1/patch.diff +9 -0
  139. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-232-1b45d1/metadata.json +15 -0
  140. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-232-1b45d1/minimal_patch_plan.md +21 -0
  141. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-002-232-1b45d1/patch.diff +9 -0
  142. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +15 -0
  143. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
  144. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
  145. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-209-4f6424/metadata.json +15 -0
  146. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-209-4f6424/minimal_patch_plan.md +21 -0
  147. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-209-4f6424/patch.diff +9 -0
  148. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-257-89bf34/metadata.json +15 -0
  149. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-257-89bf34/minimal_patch_plan.md +21 -0
  150. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-257-89bf34/patch.diff +9 -0
  151. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-341-ce228c/metadata.json +15 -0
  152. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-341-ce228c/minimal_patch_plan.md +21 -0
  153. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-341-ce228c/patch.diff +9 -0
  154. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-355-7b190b/metadata.json +15 -0
  155. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-355-7b190b/minimal_patch_plan.md +21 -0
  156. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-355-7b190b/patch.diff +9 -0
  157. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-64-5af31a/metadata.json +15 -0
  158. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-64-5af31a/minimal_patch_plan.md +21 -0
  159. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-64-5af31a/patch.diff +9 -0
  160. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-9-f51467/metadata.json +15 -0
  161. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-9-f51467/minimal_patch_plan.md +21 -0
  162. package/.torusguard/runs/run-20260908-113127-audit/bundles/bnd-tg-sec-001-9-f51467/patch.diff +9 -0
  163. package/.torusguard/runs/run-20260908-113127-audit/findings.json +1520 -0
  164. package/.torusguard/runs/run-20260908-113127-audit/findings.md +560 -0
  165. package/.torusguard/runs/run-20260908-113127-audit/manifest.json +13 -0
  166. package/.torusguard/runs/run-20260908-113127-audit/remediation.md +262 -0
  167. package/.torusguard/runs/run-20260908-113127-audit/summary.md +5 -0
  168. package/.torusguard/runs/run-20260908-115240-audit/apply_plan.md +6 -0
  169. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-115-9a059e/metadata.json +15 -0
  170. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-115-9a059e/minimal_patch_plan.md +21 -0
  171. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-115-9a059e/patch.diff +9 -0
  172. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-119-61557c/metadata.json +15 -0
  173. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-119-61557c/minimal_patch_plan.md +21 -0
  174. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-119-61557c/patch.diff +9 -0
  175. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-265-996ca3/metadata.json +15 -0
  176. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-265-996ca3/minimal_patch_plan.md +21 -0
  177. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-265-996ca3/patch.diff +9 -0
  178. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-334-cb819d/metadata.json +15 -0
  179. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-334-cb819d/minimal_patch_plan.md +21 -0
  180. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-334-cb819d/patch.diff +9 -0
  181. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-503-d11cf8/metadata.json +15 -0
  182. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-503-d11cf8/minimal_patch_plan.md +21 -0
  183. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-503-d11cf8/patch.diff +9 -0
  184. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-79-91f41f/metadata.json +15 -0
  185. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-79-91f41f/minimal_patch_plan.md +21 -0
  186. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-db-004-79-91f41f/patch.diff +9 -0
  187. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-107-516a40/metadata.json +15 -0
  188. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-107-516a40/minimal_patch_plan.md +21 -0
  189. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-107-516a40/patch.diff +9 -0
  190. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-128-7809a1/metadata.json +15 -0
  191. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-128-7809a1/minimal_patch_plan.md +21 -0
  192. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-128-7809a1/patch.diff +9 -0
  193. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-232-1b45d1/metadata.json +15 -0
  194. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-232-1b45d1/minimal_patch_plan.md +21 -0
  195. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-002-232-1b45d1/patch.diff +9 -0
  196. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-003-53-d167b4/metadata.json +15 -0
  197. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-003-53-d167b4/minimal_patch_plan.md +21 -0
  198. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-input-003-53-d167b4/patch.diff +9 -0
  199. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-platform-001-168-5027cb/metadata.json +15 -0
  200. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-platform-001-168-5027cb/minimal_patch_plan.md +21 -0
  201. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-platform-001-168-5027cb/patch.diff +9 -0
  202. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-209-4f6424/metadata.json +15 -0
  203. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-209-4f6424/minimal_patch_plan.md +21 -0
  204. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-209-4f6424/patch.diff +9 -0
  205. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-257-89bf34/metadata.json +15 -0
  206. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-257-89bf34/minimal_patch_plan.md +21 -0
  207. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-257-89bf34/patch.diff +9 -0
  208. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-341-ce228c/metadata.json +15 -0
  209. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-341-ce228c/minimal_patch_plan.md +21 -0
  210. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-341-ce228c/patch.diff +9 -0
  211. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-355-7b190b/metadata.json +15 -0
  212. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-355-7b190b/minimal_patch_plan.md +21 -0
  213. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-355-7b190b/patch.diff +9 -0
  214. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-64-5af31a/metadata.json +15 -0
  215. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-64-5af31a/minimal_patch_plan.md +21 -0
  216. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-64-5af31a/patch.diff +9 -0
  217. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-9-f51467/metadata.json +15 -0
  218. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-9-f51467/minimal_patch_plan.md +21 -0
  219. package/.torusguard/runs/run-20260908-115240-audit/bundles/bnd-tg-sec-001-9-f51467/patch.diff +9 -0
  220. package/.torusguard/runs/run-20260908-115240-audit/diff_summary.md +221 -0
  221. package/.torusguard/runs/run-20260908-115240-audit/findings.json +1553 -0
  222. package/.torusguard/runs/run-20260908-115240-audit/findings.md +572 -0
  223. package/.torusguard/runs/run-20260908-115240-audit/manifest.json +14 -0
  224. package/.torusguard/runs/run-20260908-115240-audit/recheck.md +91 -0
  225. package/.torusguard/runs/run-20260908-115240-audit/remediation.md +278 -0
  226. package/.torusguard/runs/run-20260908-115240-audit/summary.md +5 -0
  227. package/.torusguard/scripts/__pycache__/audit_runner.cpython-311.pyc +0 -0
  228. package/.torusguard/scripts/__pycache__/finding_scorer.cpython-311.pyc +0 -0
  229. package/.torusguard/scripts/__pycache__/memory_engine.cpython-311.pyc +0 -0
  230. package/.torusguard/scripts/__pycache__/monorepo_detector.cpython-311.pyc +0 -0
  231. package/.torusguard/scripts/__pycache__/run_manager.cpython-311.pyc +0 -0
  232. package/.torusguard/scripts/__pycache__/stack_detect.cpython-311.pyc +0 -0
  233. package/.torusguard/scripts/apply_runner.py +339 -0
  234. package/.torusguard/scripts/audit_runner.py +550 -0
  235. package/.torusguard/scripts/diff_guard.py +52 -4
  236. package/.torusguard/scripts/finding_scorer.py +58 -0
  237. package/.torusguard/scripts/harden_runner.py +375 -0
  238. package/.torusguard/scripts/html_reporter.py +25 -10
  239. package/.torusguard/scripts/manifest_builder.py +2 -0
  240. package/.torusguard/scripts/memory_engine.py +4 -0
  241. package/.torusguard/scripts/recheck_runner.py +221 -0
  242. package/.torusguard/scripts/recipes_runner.py +130 -0
  243. package/.torusguard/scripts/run_manager.py +17 -5
  244. package/.torusguard/skills/torusguard/SKILL.md +42 -42
  245. package/.torusguard/skills/torusguard/bootstrap.py +149 -70
  246. package/.torusguard/snapshots/run-20260908-115240-audit/examples/vulnerable-react-express/client/src/App.jsx.bak +63 -0
  247. package/.torusguard/snapshots/run-20260908-115240-audit/examples/vulnerable-react-express/server/index.js.bak +82 -0
  248. package/.torusguard/snapshots/run-20260908-115240-audit/harness/engine/fixture_manager.py.bak +245 -0
  249. package/.torusguard/snapshots/run-20260908-115240-audit/harness/master_validation.py.bak +698 -0
  250. package/.torusguard/snapshots/run-20260908-115240-audit/harness/runner.py.bak +551 -0
  251. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_e2e.py.bak +498 -0
  252. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_qa_v0_6_0.py.bak +572 -0
  253. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v0_6_1_scale.py.bak +371 -0
  254. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v0_6_2_modern_stacks.py.bak +462 -0
  255. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v0_6_3_hardening.py.bak +444 -0
  256. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v1_0_0_memory.py.bak +302 -0
  257. package/.torusguard/snapshots/run-20260908-115240-audit/harness/validate_v1_1_0_advanced_memory.py.bak +342 -0
  258. package/.torusguard/snapshots/run-20260908-115240-audit/skills/torusguard/payload/scripts/harden_runner.py.bak +353 -0
  259. package/.torusguard/snapshots/run-20260908-115240-audit/tests/test_v0_6_0_governed_remediation.py.bak +353 -0
  260. package/README.md +70 -33
  261. package/bin/torusguard.js +92 -22
  262. package/package.json +1 -1
  263. package/skills/torusguard/SKILL.md +42 -42
  264. package/skills/torusguard/bootstrap.py +147 -68
  265. package/skills/torusguard/payload/.manifest.json +113 -9
  266. package/skills/torusguard/payload/rules/README.md +93 -62
  267. package/skills/torusguard/payload/rules/TG-AUTH-001-weak-password-storage.md +103 -0
  268. package/skills/torusguard/payload/rules/TG-AUTH-002-client-only-authorization.md +85 -0
  269. package/skills/torusguard/payload/rules/TG-AUTH-003-missing-object-authorization.md +85 -0
  270. package/skills/torusguard/payload/rules/TG-AUTH-004-insecure-session-cookie.md +96 -0
  271. package/skills/torusguard/payload/rules/TG-AUTH-005-unsafe-password-reset.md +104 -0
  272. package/skills/torusguard/payload/rules/TG-CLIENT-001-public-production-source-maps.md +102 -0
  273. package/skills/torusguard/payload/rules/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
  274. package/skills/torusguard/payload/rules/TG-DB-001-frontend-database-query.md +83 -0
  275. package/skills/torusguard/payload/rules/TG-DB-002-privileged-database-credential.md +86 -0
  276. package/skills/torusguard/payload/rules/TG-DB-003-frontend-admin-sdk.md +91 -0
  277. package/skills/torusguard/payload/rules/TG-DB-004-missing-tenant-query-isolation.md +103 -0
  278. package/skills/torusguard/payload/rules/TG-INPUT-001-missing-server-validation.md +98 -0
  279. package/skills/torusguard/payload/rules/TG-INPUT-002-raw-sql-concatenation.md +94 -0
  280. package/skills/torusguard/payload/rules/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
  281. package/skills/torusguard/payload/rules/TG-INPUT-004-unrestricted-file-upload.md +92 -0
  282. package/skills/torusguard/payload/rules/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
  283. package/skills/torusguard/payload/rules/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
  284. package/skills/torusguard/payload/rules/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
  285. package/skills/torusguard/payload/rules/TG-PLATFORM-002-missing-security-headers.md +95 -0
  286. package/skills/torusguard/payload/rules/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
  287. package/skills/torusguard/payload/rules/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
  288. package/skills/torusguard/payload/rules/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
  289. package/skills/torusguard/payload/rules/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
  290. package/skills/torusguard/payload/rules/TG-RATE-003-unbounded-resource-consumption.md +105 -0
  291. package/skills/torusguard/payload/rules/TG-SEC-001-hardcoded-secrets.md +83 -0
  292. package/skills/torusguard/payload/rules/TG-SEC-002-public-environment-secrets.md +83 -0
  293. package/skills/torusguard/payload/rules/TG-SEC-003-tracked-env-file.md +79 -0
  294. package/skills/torusguard/payload/rules/TG-SEC-004-sensitive-logging.md +83 -0
  295. package/skills/torusguard/payload/rules/active/TG-AUTH-001-weak-password-storage.md +103 -0
  296. package/skills/torusguard/payload/rules/active/TG-AUTH-002-client-only-authorization.md +85 -0
  297. package/skills/torusguard/payload/rules/active/TG-AUTH-003-missing-object-authorization.md +85 -0
  298. package/skills/torusguard/payload/rules/active/TG-AUTH-004-insecure-session-cookie.md +96 -0
  299. package/skills/torusguard/payload/rules/active/TG-AUTH-005-unsafe-password-reset.md +104 -0
  300. package/skills/torusguard/payload/rules/active/TG-CLIENT-001-public-production-source-maps.md +102 -0
  301. package/skills/torusguard/payload/rules/active/TG-CLIENT-002-sensitive-client-bundle-content.md +102 -0
  302. package/skills/torusguard/payload/rules/active/TG-DB-001-frontend-database-query.md +83 -0
  303. package/skills/torusguard/payload/rules/active/TG-DB-002-privileged-database-credential.md +86 -0
  304. package/skills/torusguard/payload/rules/active/TG-DB-003-frontend-admin-sdk.md +91 -0
  305. package/skills/torusguard/payload/rules/active/TG-DB-004-missing-tenant-query-isolation.md +103 -0
  306. package/skills/torusguard/payload/rules/active/TG-INPUT-001-missing-server-validation.md +98 -0
  307. package/skills/torusguard/payload/rules/active/TG-INPUT-002-raw-sql-concatenation.md +94 -0
  308. package/skills/torusguard/payload/rules/active/TG-INPUT-003-unsafe-html-or-code-execution.md +102 -0
  309. package/skills/torusguard/payload/rules/active/TG-INPUT-004-unrestricted-file-upload.md +92 -0
  310. package/skills/torusguard/payload/rules/active/TG-INPUT-005-unsafe-template-rendering-and-escaping.md +102 -0
  311. package/skills/torusguard/payload/rules/active/TG-INPUT-006-unsafe-file-path-traversal.md +131 -0
  312. package/skills/torusguard/payload/rules/active/TG-PLATFORM-001-wildcard-cors-with-credentials.md +101 -0
  313. package/skills/torusguard/payload/rules/active/TG-PLATFORM-002-missing-security-headers.md +95 -0
  314. package/skills/torusguard/payload/rules/active/TG-PLATFORM-003-production-stack-trace-exposure.md +94 -0
  315. package/skills/torusguard/payload/rules/active/TG-PLATFORM-004-missing-request-size-limits.md +102 -0
  316. package/skills/torusguard/payload/rules/active/TG-RATE-001-unlimited-auth-endpoint.md +112 -0
  317. package/skills/torusguard/payload/rules/active/TG-RATE-002-unlimited-public-write-endpoint.md +109 -0
  318. package/skills/torusguard/payload/rules/active/TG-RATE-003-unbounded-resource-consumption.md +105 -0
  319. package/skills/torusguard/payload/rules/active/TG-SEC-001-hardcoded-secrets.md +83 -0
  320. package/skills/torusguard/payload/rules/active/TG-SEC-002-public-environment-secrets.md +83 -0
  321. package/skills/torusguard/payload/rules/active/TG-SEC-003-tracked-env-file.md +79 -0
  322. package/skills/torusguard/payload/rules/active/TG-SEC-004-sensitive-logging.md +83 -0
  323. package/skills/torusguard/payload/rules/agent/TG-AGENT-001-prompt-injection-system-context.md +56 -0
  324. package/skills/torusguard/payload/rules/agent/TG-AGENT-002-unsafe-tool-dispatch-unsandboxed-execution.md +68 -0
  325. package/skills/torusguard/payload/rules/agent/TG-AGENT-003-broad-mcp-tool-scoping.md +53 -0
  326. package/skills/torusguard/payload/rules/agent/TG-AGENT-004-persistent-memory-cross-session-leakage.md +67 -0
  327. package/skills/torusguard/payload/rules/authorization/TG-AUTH-006-mass-assignment.md +70 -0
  328. package/skills/torusguard/payload/rules/authorization/TG-AUTH-007-missing-property-level-authorization.md +71 -0
  329. package/skills/torusguard/payload/rules/authorization/TG-AUTH-008-untrusted-role-header-injection.md +112 -0
  330. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-001-client-controlled-sensitive-business-value.md +37 -0
  331. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-002-replayable-one-time-operation.md +37 -0
  332. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-003-missing-workflow-state-validation.md +37 -0
  333. package/skills/torusguard/payload/rules/business-logic/TG-BIZ-004-unrestricted-sensitive-business-flow.md +37 -0
  334. package/skills/torusguard/payload/rules/cache/TG-CACHE-001-sensitive-response-publicly-cacheable.md +37 -0
  335. package/skills/torusguard/payload/rules/cache/TG-CACHE-002-missing-user-cache-isolation.md +37 -0
  336. package/skills/torusguard/payload/rules/cache/TG-CACHE-003-sensitive-data-in-url.md +37 -0
  337. package/skills/torusguard/payload/rules/csrf/TG-CSRF-001-missing-csrf-protection.md +37 -0
  338. package/skills/torusguard/payload/rules/csrf/TG-CSRF-002-unsafe-credentialed-cross-origin-request.md +37 -0
  339. package/skills/torusguard/payload/rules/edge/TG-EDGE-001-serverless-global-state-leak.md +83 -0
  340. package/skills/torusguard/payload/rules/edge/TG-EDGE-003-aws-lambda-ephemeral-cold-start.md +76 -0
  341. package/skills/torusguard/payload/rules/graphql/TG-GQL-001-missing-query-depth-or-complexity-limits.md +64 -0
  342. package/skills/torusguard/payload/rules/graphql/TG-GQL-002-resolver-missing-authorization.md +37 -0
  343. package/skills/torusguard/payload/rules/graphql/TG-GQL-003-unbounded-graphql-pagination-or-batching.md +37 -0
  344. package/skills/torusguard/payload/rules/graphql/TG-GQL-004-unnecessary-production-introspection.md +37 -0
  345. package/skills/torusguard/payload/rules/secrets/TG-SEC-005-secret-in-git-history.md +37 -0
  346. package/skills/torusguard/payload/rules/secrets/TG-SEC-006-secret-in-build-artifact.md +37 -0
  347. package/skills/torusguard/payload/rules/secrets/TG-SEC-007-secret-in-test-or-example-fixture.md +37 -0
  348. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-001-user-controlled-server-side-url-fetch.md +68 -0
  349. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-002-missing-internal-network-protection.md +37 -0
  350. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-003-unsafe-redirect-following.md +37 -0
  351. package/skills/torusguard/payload/rules/ssrf/TG-SSRF-004-unbounded-outbound-request.md +37 -0
  352. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-001-missing-or-ignored-dependency-lockfile.md +37 -0
  353. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-002-vulnerable-dependency-review-missing.md +94 -0
  354. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-003-unsafe-ci-cd-secret-exposure.md +37 -0
  355. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-004-unpinned-ci-action.md +37 -0
  356. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-005-unsafe-dependency-install-script.md +37 -0
  357. package/skills/torusguard/payload/rules/supply-chain/TG-SUPPLY-006-container-build-secret-persistence.md +61 -0
  358. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-001-missing-webhook-signature-verification.md +37 -0
  359. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-002-replayable-webhook.md +37 -0
  360. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-003-missing-webhook-idempotency.md +37 -0
  361. package/skills/torusguard/payload/rules/webhook/TG-WEBHOOK-004-unvalidated-webhook-event-type.md +37 -0
  362. package/skills/torusguard/payload/rules/websocket/TG-WS-001-unauthenticated-websocket-handshake.md +82 -0
  363. package/skills/torusguard/payload/rules/websocket/TG-WS-002-missing-channel-level-authorization.md +37 -0
  364. package/skills/torusguard/payload/rules/websocket/TG-WS-003-unvalidated-websocket-message.md +37 -0
  365. package/skills/torusguard/payload/rules/websocket/TG-WS-004-unbounded-websocket-connections.md +37 -0
  366. package/skills/torusguard/payload/scripts/apply_runner.py +339 -0
  367. package/skills/torusguard/payload/scripts/audit_runner.py +550 -0
  368. package/skills/torusguard/payload/scripts/diff_guard.py +52 -4
  369. package/skills/torusguard/payload/scripts/finding_scorer.py +58 -0
  370. package/skills/torusguard/payload/scripts/harden_runner.py +375 -0
  371. package/skills/torusguard/payload/scripts/html_reporter.py +25 -10
  372. package/skills/torusguard/payload/scripts/manifest_builder.py +2 -0
  373. package/skills/torusguard/payload/scripts/memory_engine.py +4 -0
  374. package/skills/torusguard/payload/scripts/recheck_runner.py +221 -0
  375. package/skills/torusguard/payload/scripts/recipes_runner.py +130 -0
  376. package/skills/torusguard/payload/scripts/run_manager.py +17 -5
  377. package/skills/torusguard/payload/skills/torusguard/SKILL.md +42 -42
  378. package/skills/torusguard/payload/skills/torusguard/bootstrap.py +147 -68
@@ -0,0 +1,21 @@
1
+ # Remediation Plan: bnd-tg-db-004-79-91f41f
2
+ - **Rule ID:** `TG-DB-004`
3
+ - **Target File:** `tests/test_v0_6_0_governed_remediation.py:79`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Added explicit organization_id tenant boundary filter to ORM query
8
+
9
+ ## Unified Diff Preview
10
+ ```diff
11
+ --- a/tests/test_v0_6_0_governed_remediation.py
12
+ +++ b/tests/test_v0_6_0_governed_remediation.py
13
+ @@ -77,5 +77,5 @@
14
+ def get_invoice(request, invoice_id):
15
+ # Fetch invoice directly without tenant filter
16
+ - invoice = Invoice.objects.get(id=invoice_id)
17
+ + invoice = Invoice.objects.get(organization_id=request.user.organization_id, id=invoice_id)
18
+ return JsonResponse({"id": invoice.id})
19
+ """
20
+
21
+ ```
@@ -0,0 +1,9 @@
1
+ --- a/tests/test_v0_6_0_governed_remediation.py
2
+ +++ b/tests/test_v0_6_0_governed_remediation.py
3
+ @@ -77,5 +77,5 @@
4
+ def get_invoice(request, invoice_id):
5
+ # Fetch invoice directly without tenant filter
6
+ - invoice = Invoice.objects.get(id=invoice_id)
7
+ + invoice = Invoice.objects.get(organization_id=request.user.organization_id, id=invoice_id)
8
+ return JsonResponse({"id": invoice.id})
9
+ """
@@ -0,0 +1,15 @@
1
+ {
2
+ "bundle_id": "bnd-tg-input-002-107-516a40",
3
+ "finding_id": "TG-INPUT-002-8f877a5f",
4
+ "rule_id": "TG-INPUT-002",
5
+ "title": "Unescaped Raw SQL Query Concatenation",
6
+ "target_file": "harness/validate_v1_1_0_advanced_memory.py",
7
+ "line_number": 107,
8
+ "what_is_wrong": "Python f-string interpolation in raw SQL query",
9
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
10
+ "what_should_change": "Replaced unsafe Python SQL f-string interpolation with parameterized SQL query placeholder",
11
+ "proposed_diff": "--- a/harness/validate_v1_1_0_advanced_memory.py\n+++ b/harness/validate_v1_1_0_advanced_memory.py\n@@ -105,5 +105,5 @@\n memory_engine.ensure_memory_structure(root_dir=test_root)\n \n- valid_before = \"cursor.execute(f'SELECT * FROM users WHERE id = {uid}')\"\n+ valid_before = \"cursor.execute('SELECT * FROM users WHERE id = %s')\"\n valid_after = \"cursor.execute('SELECT * FROM users WHERE id = %s', (uid,))\"\n valid_diff = \"- cursor.execute(f'SELECT * FROM users WHERE id = {uid}')\\n+ cursor.execute('SELECT * FROM users WHERE id = %s', (uid,))\"\n",
12
+ "additions": 1,
13
+ "deletions": 1,
14
+ "patched_content": "#!/usr/bin/env python3\n\"\"\"\nTorusGuard v1.1.0 Advanced Memory Engine Test Suite\nValidates Option B enhancements:\n1. File path and rule-family proximity scoring (compute_proximity_score)\n2. Golden Fix Recipe storage and strict Ponytail bound enforcement (<=35 add, <=25 del)\n3. Golden Fix Recipe schema compliance against golden-recipe.schema.json\n4. Role-tailored context window generation (auditor, remediator, reviewer, all)\n5. Finding confidence scoring with directory and file-proximity modifiers\n6. Git pre-commit hook installation and uninstallation\n7. Git commit history learning (learn_from_git)\n8. Sanitized team export (stripping absolute paths and sensitive tokens)\n9. Diff guard pre-commit inspection (--pre-commit)\n\"\"\"\n\nimport os\nimport sys\nimport json\nimport shutil\nimport tempfile\nimport datetime\nfrom pathlib import Path\nfrom typing import Dict, Any, List\n\n# Ensure UTF-8 stdout/stderr on Windows consoles\nif sys.stdout and hasattr(sys.stdout, \"reconfigure\"):\n try:\n sys.stdout.reconfigure(encoding=\"utf-8\", errors=\"replace\")\n except Exception:\n pass\nif sys.stderr and hasattr(sys.stderr, \"reconfigure\"):\n try:\n sys.stderr.reconfigure(encoding=\"utf-8\", errors=\"replace\")\n except Exception:\n pass\n\nROOT_DIR = Path(__file__).resolve().parent.parent\nSCRIPTS_DIR = ROOT_DIR / \".torusguard\" / \"scripts\"\nSCHEMAS_DIR = ROOT_DIR / \".torusguard\" / \"schemas\"\nsys.path.insert(0, str(SCRIPTS_DIR))\n\nimport memory_engine # type: ignore\nimport finding_scorer # type: ignore\nimport diff_guard # type: ignore\n\n\ndef test_v1_1_0_advanced_memory():\n print(\"=\" * 80)\n print(\"TORUSGUARD v1.1.0 ADVANCED MEMORY ENGINE & GOVERNANCE TEST SUITE\")\n print(\"=\" * 80)\n\n with tempfile.TemporaryDirectory() as tmp_dir:\n test_root = Path(tmp_dir).resolve()\n tg_dir = test_root / \".torusguard\"\n tg_dir.mkdir(parents=True, exist_ok=True)\n\n # ---------------------------------------------------------------------\n # 1. Proximity Scoring (File Path, Directory, Extension, Rule Family)\n # ---------------------------------------------------------------------\n print(\"\\n--- 1. Testing Proximity Scoring (compute_proximity_score) ---\")\n mock_pattern: Dict[str, Any] = {\n \"pattern_id\": \"pat-test-01\",\n \"rule_id\": \"TG-DB-004\",\n \"affected_files\": [\"src/api/auth.py\", \"src/api/users.py\"],\n \"file_type\": \".py\"\n }\n\n # Exact file match + Exact rule match\n s_exact = memory_engine.compute_proximity_score(\n mock_pattern,\n target_file=\"src/api/auth.py\",\n target_rule_id=\"TG-DB-004\"\n )\n assert s_exact >= 90, f\"Expected exact score >= 90, got {s_exact}\"\n\n # Directory match + Family rule match (TG-DB-001 vs TG-DB-004)\n s_dir = memory_engine.compute_proximity_score(\n mock_pattern,\n target_file=\"src/api/billing.py\",\n target_rule_id=\"TG-DB-001\"\n )\n assert 40 <= s_dir <= 80, f\"Expected dir/family score in [40, 80], got {s_dir}\"\n\n # Extension match only, different directory, unrelated rule\n s_ext = memory_engine.compute_proximity_score(\n mock_pattern,\n target_file=\"utils/helper.py\",\n target_rule_id=\"TG-SEC-001\"\n )\n assert 10 <= s_ext <= 30, f\"Expected ext score in [10, 30], got {s_ext}\"\n\n # Completely unrelated\n s_none = memory_engine.compute_proximity_score(\n mock_pattern,\n target_file=\"frontend/App.tsx\",\n target_rule_id=\"TG-CLIENT-001\"\n )\n assert s_none == 0, f\"Expected 0 for unrelated query, got {s_none}\"\n print(f\" [PASS] Proximity scoring verified: Exact={s_exact}, Dir={s_dir}, Ext={s_ext}, None={s_none}\")\n\n # ---------------------------------------------------------------------\n # 2. Golden Fix Recipe Storage & Strict Ponytail Bound Enforcement\n # ---------------------------------------------------------------------\n print(\"\\n--- 2. Testing Golden Fix Recipe Storage & Ponytail Bounds ---\")\n memory_engine.ensure_memory_structure(root_dir=test_root)\n\n valid_before = \"cursor.execute('SELECT * FROM users WHERE id = %s')\"\n valid_after = \"cursor.execute('SELECT * FROM users WHERE id = %s', (uid,))\"\n valid_diff = \"- cursor.execute(f'SELECT * FROM users WHERE id = {uid}')\\n+ cursor.execute('SELECT * FROM users WHERE id = %s', (uid,))\"\n\n recipe = memory_engine.record_golden_recipe(\n rule_id=\"TG-DB-001\",\n before_snippet=valid_before,\n after_snippet=valid_after,\n diff_snippet=valid_diff,\n file_type=\".py\",\n framework=\"FastAPI\",\n description=\"Parameterized SQL execution replacing raw string interpolation\",\n additions=1,\n deletions=1,\n root_dir=test_root\n )\n assert recipe[\"pattern_type\"] == \"golden_fix_recipe\"\n assert recipe[\"rule_id\"] == \"TG-DB-001\"\n assert recipe[\"confidence\"] >= 0.85\n assert recipe[\"recipe_data\"][\"verified_count\"] == 1\n assert recipe[\"recipe_data\"][\"ponytail_metrics\"][\"additions\"] == 1\n\n # Second verification of the same rule boosts confidence and increments count\n recipe2 = memory_engine.record_golden_recipe(\n rule_id=\"TG-DB-001\",\n before_snippet=valid_before,\n after_snippet=valid_after,\n diff_snippet=valid_diff,\n file_type=\".py\",\n framework=\"FastAPI\",\n description=\"Re-verified parameterized query\",\n additions=1,\n deletions=1,\n root_dir=test_root\n )\n assert recipe2[\"recipe_data\"][\"verified_count\"] == 2\n assert recipe2[\"confidence\"] > recipe[\"confidence\"]\n print(f\" [PASS] Golden recipe recorded & verified count incremented to {recipe2['recipe_data']['verified_count']}\")\n\n # Ponytail Bound Violations (Must raise ValueError)\n try:\n memory_engine.record_golden_recipe(\n rule_id=\"TG-DB-001\",\n before_snippet=\"code\",\n after_snippet=\"bloated code\",\n diff_snippet=\"giant diff\",\n file_type=\".py\",\n additions=40, # Exceeds 35 additions bound\n deletions=5,\n root_dir=test_root\n )\n assert False, \"Failed to reject recipe exceeding additions bound (>35)\"\n except ValueError as err:\n assert \"Ponytail\" in str(err)\n print(\" [PASS] Successfully rejected recipe with >35 additions\")\n\n try:\n memory_engine.record_golden_recipe(\n rule_id=\"TG-DB-001\",\n before_snippet=\"code\",\n after_snippet=\"deleted code\",\n diff_snippet=\"giant diff\",\n file_type=\".py\",\n additions=5,\n deletions=30, # Exceeds 25 deletions bound\n root_dir=test_root\n )\n assert False, \"Failed to reject recipe exceeding deletions bound (>25)\"\n except ValueError as err:\n assert \"Ponytail\" in str(err)\n print(\" [PASS] Successfully rejected recipe with >25 deletions\")\n\n # ---------------------------------------------------------------------\n # 3. Golden Recipe Schema Compliance\n # ---------------------------------------------------------------------\n print(\"\\n--- 3. Testing Schema Compliance (golden-recipe.schema.json) ---\")\n schema_path = SCHEMAS_DIR / \"golden-recipe.schema.json\"\n assert schema_path.exists(), f\"Schema file not found at {schema_path}\"\n schema = json.loads(schema_path.read_text(encoding=\"utf-8\"))\n assert schema[\"title\"] == \"TorusGuard Golden Fix Recipe Schema\"\n\n # Validate that stored recipe matches schema required fields\n required_fields = schema[\"required\"]\n recipe_data = recipe[\"recipe_data\"]\n for field in required_fields:\n assert field in recipe_data, f\"Recipe missing required schema field: {field}\"\n assert recipe_data[\"ponytail_metrics\"][\"additions\"] <= 35\n assert recipe_data[\"ponytail_metrics\"][\"deletions\"] <= 25\n print(f\" [PASS] Recipe structure matches all {len(required_fields)} required schema attributes\")\n\n # ---------------------------------------------------------------------\n # 4. Role-Tailored Context Windows (Auditor, Remediator, Reviewer)\n # ---------------------------------------------------------------------\n print(\"\\n--- 4. Testing Role-Tailored Context Windows ---\")\n # Add diverse patterns to memory\n memory_engine.record_event(\"audit_finding\", {\"rule_id\": \"TG-SEC-001\", \"file_path\": \"config/settings.py\", \"severity\": \"critical\", \"confidence_score\": 90}, root_dir=test_root)\n memory_engine.record_event(\"audit_finding\", {\"rule_id\": \"TG-SEC-001\", \"file_path\": \"config/settings.py\", \"severity\": \"critical\", \"confidence_score\": 90}, root_dir=test_root)\n memory_engine.record_event(\"false_positive\", {\"rule_id\": \"TG-INPUT-003\", \"file_path\": \"tests/test_api.py\", \"suppression_reason\": \"Mock fixture\"}, root_dir=test_root)\n memory_engine.record_event(\"fix_applied\", {\"rule_id\": \"TG-SEC-001\", \"file_path\": \"config/settings.py\"}, root_dir=test_root)\n memory_engine.record_event(\"audit_finding\", {\"rule_id\": \"TG-SEC-001\", \"file_path\": \"config/settings.py\", \"severity\": \"critical\", \"confidence_score\": 90}, root_dir=test_root) # Triggers regression_watch\n memory_engine.distill_patterns(root_dir=test_root)\n\n # 4a. Auditor Persona Context\n ctx_auditor = memory_engine.compute_context_window(root_dir=test_root, target_role=\"auditor\")\n assert ctx_auditor[\"role\"] == \"auditor\"\n assert ctx_auditor[\"token_estimate\"] <= 2000\n # Auditor should prioritize common_vulnerability and false_positive_class\n auditor_card_types = [c[\"type\"] for c in ctx_auditor[\"cards\"]]\n print(f\" Auditor cards: {auditor_card_types}\")\n assert any(t in (\"common_vulnerability\", \"false_positive_suppression\") for t in auditor_card_types)\n\n # 4b. Remediator Persona Context\n ctx_remediator = memory_engine.compute_context_window(root_dir=test_root, target_role=\"remediator\")\n assert ctx_remediator[\"role\"] == \"remediator\"\n assert ctx_remediator[\"token_estimate\"] <= 2000\n remediator_card_types = [c[\"type\"] for c in ctx_remediator[\"cards\"]]\n print(f\" Remediator cards: {remediator_card_types}\")\n # Remediator should include golden_recipe cards\n assert \"golden_recipe\" in remediator_card_types\n\n # 4c. Reviewer Persona Context\n ctx_reviewer = memory_engine.compute_context_window(root_dir=test_root, target_role=\"reviewer\")\n assert ctx_reviewer[\"role\"] == \"reviewer\"\n assert ctx_reviewer[\"token_estimate\"] <= 2000\n\n # 4d. Target-Filtered Context\n ctx_filtered = memory_engine.compute_context_window(\n root_dir=test_root,\n target_role=\"remediator\",\n target_file=\"config/settings.py\",\n target_rule_id=\"TG-SEC-001\"\n )\n assert ctx_filtered[\"target_query\"][\"file\"] == \"config/settings.py\"\n assert ctx_filtered[\"target_query\"][\"rule_id\"] == \"TG-SEC-001\"\n assert len(ctx_filtered[\"cards\"]) > 1\n assert any(c.get(\"proximity_score\", 0) > 0 for c in ctx_filtered[\"cards\"])\n assert ctx_filtered[\"cards\"][1][\"proximity_score\"] > 0\n print(f\" [PASS] Role-tailored context generation validated across auditor, remediator, reviewer (Tokens <= 2000)\")\n\n # ---------------------------------------------------------------------\n # 5. Finding Scorer Memory & Directory Proximity Boost\n # ---------------------------------------------------------------------\n print(\"\\n--- 5. Testing Finding Scorer Memory & Proximity Modifiers ---\")\n # Direct rule match with exact file match\n b_exact = finding_scorer.compute_memory_boost(\n rule_id=\"TG-DB-001\",\n file_path=\"src/api/auth.py\",\n root_dir=test_root\n )\n # Same directory file match\n b_dir = finding_scorer.compute_memory_boost(\n rule_id=\"TG-DB-001\",\n file_path=\"src/api/orders.py\",\n root_dir=test_root\n )\n # Suppressed FP rule\n b_fp = finding_scorer.compute_memory_boost(\n rule_id=\"TG-INPUT-003\",\n file_path=\"tests/test_api.py\",\n root_dir=test_root\n )\n assert b_fp <= -20, f\"Expected FP suppression <= -20, got {b_fp}\"\n print(f\" [PASS] Scorer memory integration verified: Exact={b_exact}, Dir={b_dir}, FP={b_fp}\")\n\n # ---------------------------------------------------------------------\n # 6. Git Pre-Commit Hook Installation & Uninstallation\n # ---------------------------------------------------------------------\n print(\"\\n--- 6. Testing Git Pre-Commit Hook Installation & Cleanup ---\")\n git_dir = test_root / \".git\"\n git_dir.mkdir(parents=True, exist_ok=True)\n\n res_install = memory_engine.install_git_hook(root_dir=test_root)\n assert res_install[\"status\"] == \"installed\"\n hook_file = Path(res_install[\"hook_path\"])\n assert hook_file.exists()\n hook_content = hook_file.read_text(encoding=\"utf-8\")\n assert \"diff_guard.py\" in hook_content\n assert \"--pre-commit\" in hook_content\n\n res_uninstall = memory_engine.uninstall_git_hook(root_dir=test_root)\n assert res_uninstall[\"status\"] == \"uninstalled\"\n if hook_file.exists():\n assert \"diff_guard.py\" not in hook_file.read_text(encoding=\"utf-8\")\n print(\" [PASS] Git hook installed, verified, and cleanly uninstalled\")\n\n # ---------------------------------------------------------------------\n # 7. Git Commit History Learning (learn_from_git)\n # ---------------------------------------------------------------------\n print(\"\\n--- 7. Testing Git Commit Learning ---\")\n # In a temp directory with no commits, should handle gracefully with 0 learned\n learned = memory_engine.learn_from_git(root_dir=test_root)\n assert \"events_recorded\" in learned\n print(f\" [PASS] learn_from_git executed safely with {learned['events_recorded']} events on empty repo\")\n\n # ---------------------------------------------------------------------\n # 8. Sanitized Memory Export (Safe Team Sharing)\n # ---------------------------------------------------------------------\n print(\"\\n--- 8. Testing Sanitized Memory Export ---\")\n raw_export_file = test_root / \"raw-export.json\"\n san_export_file = test_root / \"sanitized-export.json\"\n\n memory_engine.export_memory(target_file=raw_export_file, sanitized=False, root_dir=test_root)\n memory_engine.export_memory(target_file=san_export_file, sanitized=True, root_dir=test_root)\n\n san_data = json.loads(san_export_file.read_text(encoding=\"utf-8\"))\n assert san_data.get(\"sanitized\") is True\n # Verify affected_files are relative or basenames, not absolute host paths\n for pat in san_data.get(\"patterns\", []):\n for aff in pat.get(\"affected_files\", []):\n assert not os.path.isabs(aff), f\"Found absolute path in sanitized export: {aff}\"\n assert \"Users\" not in aff and \"home\" not in aff\n print(\" [PASS] Sanitized export verified: 100% free of local host absolute paths and secrets\")\n\n # ---------------------------------------------------------------------\n # 9. Diff Guard Pre-Commit Inspection\n # ---------------------------------------------------------------------\n print(\"\\n--- 9. Testing Diff Guard Pre-Commit Mode ---\")\n clean_diff = \"diff --git a/app.py b/app.py\\n--- a/app.py\\n+++ b/app.py\\n@@ -1,3 +1,3 @@\\n-x = 1\\n+x = 2\\n\"\n res_clean = diff_guard.audit_diff(clean_diff)\n assert res_clean[\"status\"] == \"PASSED\"\n assert len(res_clean[\"violations\"]) == 0\n\n # Run diff_guard on diff with security bypass comment (# nosec)\n bypass_diff = \"diff --git a/app.py b/app.py\\n--- a/app.py\\n+++ b/app.py\\n@@ -1,3 +1,3 @@\\n+db.query(user_input) # nosec\\n\"\n res_bypass = diff_guard.audit_diff(bypass_diff)\n assert res_bypass[\"status\"] == \"BLOCKED\"\n assert any(f[\"rule_id\"] == \"TG-DIFF-001\" for f in res_bypass[\"violations\"])\n print(\" [PASS] Diff guard correctly detects bypass patterns in diffs\")\n\n print(\"\\n\" + \"=\" * 80)\n print(\"ALL 9 ADVANCED MEMORY & GOVERNANCE CHECKS PASSED (100% REGRESSION-FREE)\")\n print(\"=\" * 80)\n\n\nif __name__ == \"__main__\":\n test_v1_1_0_advanced_memory()"
15
+ }
@@ -0,0 +1,21 @@
1
+ # Remediation Plan: bnd-tg-input-002-107-516a40
2
+ - **Rule ID:** `TG-INPUT-002`
3
+ - **Target File:** `harness/validate_v1_1_0_advanced_memory.py:107`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Replaced unsafe Python SQL f-string interpolation with parameterized SQL query placeholder
8
+
9
+ ## Unified Diff Preview
10
+ ```diff
11
+ --- a/harness/validate_v1_1_0_advanced_memory.py
12
+ +++ b/harness/validate_v1_1_0_advanced_memory.py
13
+ @@ -105,5 +105,5 @@
14
+ memory_engine.ensure_memory_structure(root_dir=test_root)
15
+
16
+ - valid_before = "cursor.execute(f'SELECT * FROM users WHERE id = {uid}')"
17
+ + valid_before = "cursor.execute('SELECT * FROM users WHERE id = %s')"
18
+ valid_after = "cursor.execute('SELECT * FROM users WHERE id = %s', (uid,))"
19
+ valid_diff = "- cursor.execute(f'SELECT * FROM users WHERE id = {uid}')\n+ cursor.execute('SELECT * FROM users WHERE id = %s', (uid,))"
20
+
21
+ ```
@@ -0,0 +1,9 @@
1
+ --- a/harness/validate_v1_1_0_advanced_memory.py
2
+ +++ b/harness/validate_v1_1_0_advanced_memory.py
3
+ @@ -105,5 +105,5 @@
4
+ memory_engine.ensure_memory_structure(root_dir=test_root)
5
+
6
+ - valid_before = "cursor.execute(f'SELECT * FROM users WHERE id = {uid}')"
7
+ + valid_before = "cursor.execute('SELECT * FROM users WHERE id = %s')"
8
+ valid_after = "cursor.execute('SELECT * FROM users WHERE id = %s', (uid,))"
9
+ valid_diff = "- cursor.execute(f'SELECT * FROM users WHERE id = {uid}')\n+ cursor.execute('SELECT * FROM users WHERE id = %s', (uid,))"
@@ -0,0 +1,15 @@
1
+ {
2
+ "bundle_id": "bnd-tg-input-002-128-7809a1",
3
+ "finding_id": "TG-INPUT-002-02f8e274",
4
+ "rule_id": "TG-INPUT-002",
5
+ "title": "Unescaped Raw SQL Query Concatenation",
6
+ "target_file": "harness/engine/fixture_manager.py",
7
+ "line_number": 128,
8
+ "what_is_wrong": "Python f-string interpolation in raw SQL query",
9
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
10
+ "what_should_change": "Replaced unsafe Python SQL f-string interpolation with parameterized SQL query placeholder",
11
+ "proposed_diff": "--- a/harness/engine/fixture_manager.py\n+++ b/harness/engine/fixture_manager.py\n@@ -126,5 +126,5 @@\n vulnerable_variant=FixtureVariant(\n relative_path=\"examples/python/sqlalchemy-vuln\",\n- code_pattern=\"session.execute(f'SELECT * FROM items WHERE name LIKE {q}')\",\n+ code_pattern=\"session.execute('SELECT * FROM items WHERE name LIKE %s')\",\n expected_findings_count=4,\n ),\n",
12
+ "additions": 1,
13
+ "deletions": 1,
14
+ "patched_content": "\"\"\"\nTorusGuard Fixture Manager (v0.5.3)\nLoads, indexes, and validates structured fixture definitions and paired differential targets for Python web applications.\n\"\"\"\n\nfrom pathlib import Path\nfrom typing import List, Dict, Optional\nfrom .models import FixtureDefinition, FixtureVariant, ValidationOutcome\n\n\nclass FixtureManager:\n \"\"\"\n Manages the catalog of validation fixtures, paired differential applications, and regression test suites.\n \"\"\"\n\n def __init__(self, root_dir: str = \".\"):\n self.root_dir = Path(root_dir).resolve()\n self.fixtures: Dict[str, FixtureDefinition] = {}\n self._load_standard_fixtures()\n\n def _load_standard_fixtures(self):\n # 1. Django Reference Pair (IDOR & Settings Exposure)\n self.register_fixture(\n FixtureDefinition(\n fixture_id=\"TG-FIX-django-idor-scoping\",\n framework=\"django\",\n scenario=\"Django ViewSet object-level authorization & settings DEBUG exposure\",\n target_rule_id=\"TG-AUTH-007\",\n expected_outcome=ValidationOutcome.VULNERABLE_CONFIRMED,\n vulnerable_variant=FixtureVariant(\n relative_path=\"examples/python/django-vuln\",\n code_pattern=\"Invoice.objects.all()\",\n expected_findings_count=6,\n ),\n hardened_variant=FixtureVariant(\n relative_path=\"examples/python/django-hardened\",\n code_pattern=\"Invoice.objects.filter(owner=request.user)\",\n expected_findings_count=0,\n is_hardened=True,\n ),\n reproduction_command=\"python manage.py test\",\n expected_diff_summary=\"DEBUG set to False; ALLOWED_HOSTS populated; get_queryset scoped to request.user.\",\n )\n )\n\n # 2. DRF Reference Pair (Mass Assignment & Throttling)\n self.register_fixture(\n FixtureDefinition(\n fixture_id=\"TG-FIX-drf-mass-assignment-throttle\",\n framework=\"drf\",\n scenario=\"DRF Serializer field protection, rate throttling, and pagination caps\",\n target_rule_id=\"TG-AUTH-006\",\n expected_outcome=ValidationOutcome.VULNERABLE_CONFIRMED,\n vulnerable_variant=FixtureVariant(\n relative_path=\"examples/python/drf-vuln\",\n code_pattern=\"fields = '__all__'\",\n expected_findings_count=5,\n ),\n hardened_variant=FixtureVariant(\n relative_path=\"examples/python/drf-hardened\",\n code_pattern=\"read_only_fields = ('role', 'is_staff')\",\n expected_findings_count=0,\n is_hardened=True,\n ),\n reproduction_command=\"pytest\",\n expected_diff_summary=\"read_only_fields explicit; ScopedRateThrottle attached; max_page_size set.\",\n )\n )\n\n # 3. FastAPI Reference Pair (SSRF & Pydantic Boundaries)\n self.register_fixture(\n FixtureDefinition(\n fixture_id=\"TG-FIX-fastapi-ssrf-pydantic\",\n framework=\"fastapi\",\n scenario=\"FastAPI outbound SSRF URL validation and Pydantic v2 extra field forbidding\",\n target_rule_id=\"TG-SSRF-001\",\n expected_outcome=ValidationOutcome.VULNERABLE_CONFIRMED,\n vulnerable_variant=FixtureVariant(\n relative_path=\"examples/python/fastapi-vuln\",\n code_pattern=\"httpx.get(target_url)\",\n expected_findings_count=5,\n ),\n hardened_variant=FixtureVariant(\n relative_path=\"examples/python/fastapi-hardened\",\n code_pattern=\"validate_outbound_destination(url)\",\n expected_findings_count=0,\n is_hardened=True,\n ),\n reproduction_command=\"pytest\",\n expected_diff_summary=\"IP destination validation filtering RFC 1918 blocks; Pydantic extra='forbid'.\",\n )\n )\n\n # 4. Flask Reference Pair (CSRF, Upload Sanitization, Session Cookies)\n self.register_fixture(\n FixtureDefinition(\n fixture_id=\"TG-FIX-flask-csrf-upload\",\n framework=\"flask\",\n scenario=\"Flask CSRFProtect, secure cookie flags, and upload filename sanitization\",\n target_rule_id=\"TG-CSRF-001\",\n expected_outcome=ValidationOutcome.VULNERABLE_CONFIRMED,\n vulnerable_variant=FixtureVariant(\n relative_path=\"examples/python/flask-vuln\",\n code_pattern=\"file.save(os.path.join(UPLOAD_DIR, file.filename))\",\n expected_findings_count=5,\n ),\n hardened_variant=FixtureVariant(\n relative_path=\"examples/python/flask-hardened\",\n code_pattern=\"secure_filename(file.filename)\",\n expected_findings_count=0,\n is_hardened=True,\n ),\n reproduction_command=\"pytest\",\n expected_diff_summary=\"CSRFProtect(app) enabled; SESSION_COOKIE_SECURE=True; secure_filename with UUID prefix.\",\n )\n )\n\n # 5. SQLAlchemy Reference Pair (Parameterized Queries & Bound Parameters)\n self.register_fixture(\n FixtureDefinition(\n fixture_id=\"TG-FIX-sqlalchemy-bound-parameters\",\n framework=\"sqlalchemy\",\n scenario=\"SQLAlchemy named text(:param) bindings and tenant query scoping\",\n target_rule_id=\"TG-INPUT-002\",\n expected_outcome=ValidationOutcome.VULNERABLE_CONFIRMED,\n vulnerable_variant=FixtureVariant(\n relative_path=\"examples/python/sqlalchemy-vuln\",\n code_pattern=\"session.execute('SELECT * FROM items WHERE name LIKE %s')\",\n expected_findings_count=4,\n ),\n hardened_variant=FixtureVariant(\n relative_path=\"examples/python/sqlalchemy-hardened\",\n code_pattern=\"session.execute(text('SELECT * FROM items WHERE name LIKE :q'), {'q': f'%{q}%'})\",\n expected_findings_count=0,\n is_hardened=True,\n ),\n reproduction_command=\"pytest\",\n expected_diff_summary=\"Parameterized text(:param) queries; tenant_id enforced on query filters.\",\n )\n )\n\n # 6. FastAPI Header Role Injection Pair (v0.5.3 TG-AUTH-008)\n self.register_fixture(\n FixtureDefinition(\n fixture_id=\"TG-FIX-fastapi-header-role-injection\",\n framework=\"fastapi\",\n scenario=\"FastAPI unverified client header role trust vs cryptographically signed token dependencies\",\n target_rule_id=\"TG-AUTH-008\",\n expected_outcome=ValidationOutcome.VULNERABLE_CONFIRMED,\n vulnerable_variant=FixtureVariant(\n relative_path=\"examples/python/fastapi-vuln\",\n code_pattern=\"x_user_role: str = Header(None)\",\n expected_findings_count=1,\n ),\n hardened_variant=FixtureVariant(\n relative_path=\"examples/python/fastapi-hardened\",\n code_pattern=\"roles: list[str] = Depends(get_current_user_roles)\",\n expected_findings_count=0,\n is_hardened=True,\n ),\n reproduction_command=\"pytest tests/test_auth_headers.py\",\n expected_diff_summary=\"Extract roles from verified JWT claims rather than raw HTTP headers.\",\n )\n )\n\n # 7. Flask Unsafe Template Rendering (v0.5.3 TG-INPUT-005)\n self.register_fixture(\n FixtureDefinition(\n fixture_id=\"TG-FIX-flask-unsafe-template-rendering\",\n framework=\"flask\",\n scenario=\"Flask render_template_string concatenation vs autoescaped render_template context\",\n target_rule_id=\"TG-INPUT-005\",\n expected_outcome=ValidationOutcome.VULNERABLE_CONFIRMED,\n vulnerable_variant=FixtureVariant(\n relative_path=\"examples/python/flask-vuln\",\n code_pattern=\"render_template_string(f'<h1>Hello {name}</h1>')\",\n expected_findings_count=1,\n ),\n hardened_variant=FixtureVariant(\n relative_path=\"examples/python/flask-hardened\",\n code_pattern=\"render_template('greet.html', name=name)\",\n expected_findings_count=0,\n is_hardened=True,\n ),\n reproduction_command=\"pytest tests/test_ssti.py\",\n expected_diff_summary=\"Pass input as template context variable avoiding SSTI.\",\n )\n )\n\n # 8. SQLAlchemy Multi-Tenant Query Isolation (v0.5.3 TG-DB-004)\n self.register_fixture(\n FixtureDefinition(\n fixture_id=\"TG-FIX-sqlalchemy-multi-tenant-isolation\",\n framework=\"sqlalchemy\",\n scenario=\"Multi-tenant item lookups with mandatory tenant_id filter enforcement\",\n target_rule_id=\"TG-DB-004\",\n expected_outcome=ValidationOutcome.VULNERABLE_CONFIRMED,\n vulnerable_variant=FixtureVariant(\n relative_path=\"examples/python/sqlalchemy-vuln\",\n code_pattern=\"session.query(Item).filter(Item.id == item_id).first()\",\n expected_findings_count=1,\n ),\n hardened_variant=FixtureVariant(\n relative_path=\"examples/python/sqlalchemy-hardened\",\n code_pattern=\"session.query(Item).filter(Item.id == item_id, Item.tenant_id == tenant_id).first()\",\n expected_findings_count=0,\n is_hardened=True,\n ),\n reproduction_command=\"pytest tests/test_tenant_isolation.py\",\n expected_diff_summary=\"Enforce Item.tenant_id == user.tenant_id on every item lookup query.\",\n )\n )\n\n # 9. Django Tenant Header & Invoice IDOR Pair (TG-AUTH-008 + TG-DB-004)\n self.register_fixture(\n FixtureDefinition(\n fixture_id=\"TG-FIX-django-tenant-header-invoice-idor\",\n framework=\"django\",\n scenario=\"Django client-controlled X-Tenant-ID header trust combined with unscoped Invoice.objects.get()\",\n target_rule_id=\"TG-AUTH-008\",\n expected_outcome=ValidationOutcome.VULNERABLE_CONFIRMED,\n vulnerable_variant=FixtureVariant(\n relative_path=\"examples/python/django-vuln\",\n code_pattern=\"tenant_id = request.headers.get('X-Tenant-ID')\\nrecord = Invoice.objects.get(id=invoice_id)\",\n expected_findings_count=2,\n ),\n hardened_variant=FixtureVariant(\n relative_path=\"examples/python/django-hardened\",\n code_pattern=\"tenant_id = request.user.tenant_id\\nrecord = Invoice.objects.filter(id=invoice_id, tenant_id=tenant_id).first()\",\n expected_findings_count=0,\n is_hardened=True,\n ),\n reproduction_command=\"pytest tests/test_invoice_tenant.py\",\n expected_diff_summary=\"Derive tenant from authenticated request.user.tenant_id and scope Invoice lookup by tenant_id.\",\n )\n )\n\n def register_fixture(self, fixture: FixtureDefinition):\n self.fixtures[fixture.fixture_id] = fixture\n\n def get_fixture(self, fixture_id: str) -> Optional[FixtureDefinition]:\n return self.fixtures.get(fixture_id)\n\n def list_fixtures(self) -> List[FixtureDefinition]:\n return list(self.fixtures.values())"
15
+ }
@@ -0,0 +1,21 @@
1
+ # Remediation Plan: bnd-tg-input-002-128-7809a1
2
+ - **Rule ID:** `TG-INPUT-002`
3
+ - **Target File:** `harness/engine/fixture_manager.py:128`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Replaced unsafe Python SQL f-string interpolation with parameterized SQL query placeholder
8
+
9
+ ## Unified Diff Preview
10
+ ```diff
11
+ --- a/harness/engine/fixture_manager.py
12
+ +++ b/harness/engine/fixture_manager.py
13
+ @@ -126,5 +126,5 @@
14
+ vulnerable_variant=FixtureVariant(
15
+ relative_path="examples/python/sqlalchemy-vuln",
16
+ - code_pattern="session.execute(f'SELECT * FROM items WHERE name LIKE {q}')",
17
+ + code_pattern="session.execute('SELECT * FROM items WHERE name LIKE %s')",
18
+ expected_findings_count=4,
19
+ ),
20
+
21
+ ```
@@ -0,0 +1,9 @@
1
+ --- a/harness/engine/fixture_manager.py
2
+ +++ b/harness/engine/fixture_manager.py
3
+ @@ -126,5 +126,5 @@
4
+ vulnerable_variant=FixtureVariant(
5
+ relative_path="examples/python/sqlalchemy-vuln",
6
+ - code_pattern="session.execute(f'SELECT * FROM items WHERE name LIKE {q}')",
7
+ + code_pattern="session.execute('SELECT * FROM items WHERE name LIKE %s')",
8
+ expected_findings_count=4,
9
+ ),
@@ -0,0 +1,15 @@
1
+ {
2
+ "bundle_id": "bnd-tg-input-002-232-1b45d1",
3
+ "finding_id": "TG-INPUT-002-ae553d22",
4
+ "rule_id": "TG-INPUT-002",
5
+ "title": "Unescaped Raw SQL Query Concatenation",
6
+ "target_file": "harness/runner.py",
7
+ "line_number": 232,
8
+ "what_is_wrong": "Python f-string interpolation in raw SQL query",
9
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
10
+ "what_should_change": "Replaced unsafe Python SQL f-string interpolation with parameterized SQL query placeholder",
11
+ "proposed_diff": "--- a/harness/runner.py\n+++ b/harness/runner.py\n@@ -230,5 +230,5 @@\n type=EvidenceType.SOURCE,\n location=\"views.py:15\",\n- raw_snippet=\"User.objects.raw(f'SELECT * FROM users WHERE name = {name}')\",\n+ raw_snippet=\"User.objects.raw('SELECT * FROM users WHERE name = %s')\",\n rationale=\"Direct string concatenation into SQL query.\",\n confidence_level=ConfidenceBand.CONFIRMED,\n",
12
+ "additions": 1,
13
+ "deletions": 1,
14
+ "patched_content": "\"\"\"\nTorusGuard Validation Harness & Engine Runner (v0.5.4)\nExecutes comprehensive validation engine cycles: deterministic replay, differential comparison, regression tracking, and schema validation.\n\"\"\"\n\nimport os\nimport sys\nimport json\nimport re\nimport glob\nimport shutil\nfrom pathlib import Path\nfrom typing import Dict, List, Tuple, Any\n\n# Add project root to sys.path\nPROJECT_ROOT = Path(__file__).resolve().parent.parent\nsys.path.insert(0, str(PROJECT_ROOT))\n\nfrom core.models import (\n Finding,\n Evidence,\n Remediation,\n FrameworkPattern,\n AffectedComponent,\n ReproductionMethod,\n RetestRecord,\n NotesRecord,\n FindingTimestamps,\n ProvenanceChain,\n ConfidenceScore,\n ConfidenceFactors,\n ConfidenceBand,\n SeverityLevel,\n SeverityInfo,\n RemediationPriority,\n FindingStatus,\n LifecycleStage,\n TaxonomyCategory,\n EvidenceType,\n AuditReport,\n mask_sensitive_data,\n)\nfrom core.lifecycle import FindingLifecycleManager, LifecycleTransitionError\nfrom core.formatter import ReportFormatter\n\nfrom harness.engine.models import (\n ValidationOutcome,\n FixtureDefinition,\n FixtureVariant,\n ReplayResult,\n ComparisonResult,\n RegressionRecord,\n ValidationRunReport,\n)\nfrom harness.engine.fixture_manager import FixtureManager\nfrom harness.engine.replay_runner import ReplayRunner\nfrom harness.engine.comparator import ResultComparator\nfrom harness.engine.regression_tracker import RegressionTracker\nfrom harness.engine.fp_analyzer import FalsePositiveAnalyzer\nfrom harness.engine.evidence_collector import ValidationEvidenceCollector\nfrom harness.engine.report_emitter import ValidationReportEmitter\n\nfrom core.run_folder import RunFolder\n\n\nclass ValidationHarnessRunner:\n def __init__(self, root_dir: str = \".\"):\n self.root_dir = Path(root_dir).resolve()\n self.passed_tests = 0\n self.failed_tests = 0\n self.results: List[Dict[str, Any]] = []\n\n def log_test(self, test_name: str, passed: bool, message: str = \"\"):\n if passed:\n self.passed_tests += 1\n print(f\" [PASS] {test_name}\")\n else:\n self.failed_tests += 1\n print(f\" [FAIL] {test_name}: {message}\")\n self.results.append({\"name\": test_name, \"passed\": passed, \"message\": message})\n\n def run_all(self) -> bool:\n print(\"=\" * 80)\n print(\"TORUSGUARD v0.5.4 REPORTING USABILITY & VALIDATION HARNESS\")\n print(\"=\" * 80)\n\n self.test_schema_integrity()\n self.test_rule_catalog()\n self.test_skill_definition()\n self.test_confidence_scoring_model()\n self.test_provenance_and_evidence_hashing()\n self.test_sensitive_data_masking()\n self.test_retest_lifecycle_closure()\n self.test_validation_engine_subsystem()\n self.test_stack_detection_fixtures()\n self.test_educational_differential_fixtures()\n self.test_regression_fixtures()\n self.test_report_formatting()\n self.test_run_context_and_ponytail()\n self.test_v6_governed_remediation_suite()\n\n print(\"-\" * 80)\n print(f\"SUMMARY: {self.passed_tests} Passed | {self.failed_tests} Failed\")\n print(\"=\" * 80)\n return self.failed_tests == 0\n\n def test_schema_integrity(self):\n print(\"\\n1. Testing Formal Schema Integrity (v0.5.4)...\")\n schemas_dir = self.root_dir / \"schemas\"\n required_schemas = [\n \"finding.schema.json\",\n \"evidence.schema.json\",\n \"remediation.schema.json\",\n \"rule.schema.json\",\n \"lifecycle.schema.json\",\n \"provenance.schema.json\",\n \"confidence.schema.json\",\n \"retest.schema.json\",\n \"fixture.schema.json\",\n \"validation-run.schema.json\",\n ]\n for s in required_schemas:\n schema_path = schemas_dir / s\n if not schema_path.exists():\n self.log_test(f\"Schema file exists: {s}\", False, \"File missing\")\n continue\n try:\n with open(schema_path, \"r\", encoding=\"utf-8\") as f:\n data = json.load(f)\n valid = \"$schema\" in data and \"title\" in data\n self.log_test(f\"Schema valid JSON: {s}\", valid, \"Missing $schema or title\")\n except Exception as e:\n self.log_test(f\"Schema valid JSON: {s}\", False, str(e))\n\n def test_rule_catalog(self):\n print(\"\\n2. Testing Rule Catalog & ID Uniqueness...\")\n rules_dir = self.root_dir / \"rules\"\n rule_files = list(rules_dir.glob(\"**/*.md\"))\n rule_ids = {}\n\n for rf in rule_files:\n if rf.name == \"README.md\":\n continue\n with open(rf, \"r\", encoding=\"utf-8\") as f:\n content = f.read()\n\n match = re.search(r\"^(TG-[A-Z0-9]+-[0-9]{3})\", rf.name)\n if not match:\n match = re.search(r\"#\\s+(TG-[A-Z0-9]+-[0-9]{3})\", content)\n\n if match:\n rid = match.group(1)\n if rid in rule_ids:\n self.log_test(f\"Rule ID unique: {rid}\", False, f\"Duplicate found in {rf.name} and {rule_ids[rid]}\")\n else:\n rule_ids[rid] = rf.name\n else:\n self.log_test(f\"Rule ID parseable in {rf.name}\", False, \"No valid TG-* rule ID found in header\")\n\n self.log_test(f\"Total Rules Cataloged ({len(rule_ids)})\", len(rule_ids) >= 64, f\"Found {len(rule_ids)} rules\")\n\n def test_skill_definition(self):\n print(\"\\n3. Testing Skill Definition & References...\")\n skill_file = self.root_dir / \"skills\" / \"TorusGuard\" / \"SKILL.md\"\n if not skill_file.exists():\n self.log_test(\"SKILL.md exists\", False, \"Missing skills/TorusGuard/SKILL.md\")\n return\n\n with open(skill_file, \"r\", encoding=\"utf-8\") as f:\n content = f.read()\n\n has_frontmatter = content.startswith(\"---\") and \"name: torusguard\" in content\n self.log_test(\"SKILL.md YAML Frontmatter\", has_frontmatter)\n\n has_commands = all(cmd in content for cmd in [\"/torusguard init\", \"/torusguard audit\", \"/torusguard harden\", \"/torusguard apply\", \"/torusguard verify\", \"/torusguard recheck\"])\n self.log_test(\"SKILL.md Core Commands Documented (including apply & recheck)\", has_commands)\n\n refs_dir = self.root_dir / \"skills\" / \"TorusGuard\" / \"references\"\n ref_files = list(refs_dir.glob(\"*.md\"))\n self.log_test(f\"Skill Reference Modules ({len(ref_files)})\", len(ref_files) >= 7)\n\n def test_confidence_scoring_model(self):\n print(\"\\n4. Testing Auditable Confidence Scoring Model...\")\n c_confirmed = ConfidenceScore.calculate(\n evidence_quality=35,\n reproduction_success=25,\n independent_confirmations=15,\n environmental_clarity=15,\n manual_review_status=5,\n rationale=\"Direct AST match with deterministic reproduction.\",\n )\n self.log_test(\"Confidence calculation: Confirmed band (>= 90)\", c_confirmed.score == 95 and c_confirmed.band == ConfidenceBand.CONFIRMED)\n\n c_high = ConfidenceScore.calculate(\n evidence_quality=30,\n reproduction_success=20,\n independent_confirmations=10,\n environmental_clarity=15,\n manual_review_status=0,\n rationale=\"Strong static indicator without manual validation.\",\n )\n self.log_test(\"Confidence calculation: High Confidence band (70-89)\", c_high.score == 75 and c_high.band == ConfidenceBand.HIGH_CONFIDENCE)\n\n def test_provenance_and_evidence_hashing(self):\n print(\"\\n5. Testing Provenance Chain & SHA-256 Evidence Integrity...\")\n ev = Evidence(\n type=EvidenceType.SOURCE,\n location=\"server/auth.py:42\",\n raw_snippet=\"SECRET_KEY = 'super_secret_jwt_key'\",\n rationale=\"Hardcoded secret credential.\",\n confidence_level=ConfidenceBand.CONFIRMED,\n is_sufficient_for_confirmed=True,\n )\n has_hash = bool(ev.sha256_checksum) and len(ev.sha256_checksum) == 64\n self.log_test(\"Evidence SHA-256 Checksum Computed\", has_hash)\n\n def test_sensitive_data_masking(self):\n print(\"\\n6. Testing Sensitive Secret & Token Masking...\")\n sample_secret = \"API_KEY = 'sk_live_998877665544332211'\"\n masked = mask_sensitive_data(sample_secret)\n self.log_test(\"Stripe Secret Key Redaction\", \"sk_live_***REDACTED***\" in masked and \"998877665544332211\" not in masked)\n\n sample_jwt = \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.doNotLeakSignature\"\n masked_jwt = mask_sensitive_data(sample_jwt)\n self.log_test(\"JWT Token Redaction\", \"***REDACTED_JWT***\" in masked_jwt and \"doNotLeakSignature\" not in masked_jwt)\n\n def test_retest_lifecycle_closure(self):\n print(\"\\n7. Testing Retest Execution & Closure State Machine...\")\n ev = Evidence(\n type=EvidenceType.SOURCE,\n location=\"views.py:15\",\n raw_snippet=\"User.objects.raw('SELECT * FROM users WHERE name = %s')\",\n rationale=\"Direct string concatenation into SQL query.\",\n confidence_level=ConfidenceBand.CONFIRMED,\n is_sufficient_for_confirmed=True,\n )\n sev = SeverityInfo(\n level=SeverityLevel.CRITICAL,\n rationale=\"Allows arbitrary SQL execution and data exfiltration.\",\n rubric_justification=\"Critical because unauthenticated user input reaches raw SQL interpreter.\",\n )\n conf = ConfidenceScore.calculate(35, 25, 15, 15, 5, \"Direct AST concatenation match.\")\n prov = ProvenanceChain(\n discovery_module=\"rules/input/TG-INPUT-002-raw-sql-concatenation.md\",\n triggering_input=\"Raw SQL execution with f-string formatting\",\n evidence_collected=[\"views.py:15\"],\n decision_path=[\"Detected raw SQL method\", \"Verified unparameterized input\"],\n verification_step=\"Inspect query parameterization.\",\n )\n rem = Remediation(\n problem_statement=\"Raw SQL string concatenation vulnerable to SQL injection.\",\n risk_explanation=\"Attackers can inject malicious SQL payloads.\",\n recommended_fix=\"Use parameterized queries.\",\n framework_pattern=FrameworkPattern(\n framework=\"Django\",\n unsafe_snippet=\"User.objects.raw(f'SELECT * FROM users WHERE name = {name}')\",\n safe_snippet=\"User.objects.raw('SELECT * FROM users WHERE name = %s', [name])\",\n ),\n verification_method=\"Test with quote payload and verify parameterized execution.\",\n residual_risk_notes=\"Ensure database permissions are restricted.\",\n )\n finding = Finding(\n rule_id=\"TG-INPUT-002\",\n title=\"Raw SQL Concatenation\",\n category=TaxonomyCategory.INPUT,\n severity=sev,\n confidence=conf,\n status=FindingStatus.CONFIRMED,\n affected_component=AffectedComponent(component_name=\"UserSearch\", target_path=\"views.py\", start_line=15),\n evidence=[ev],\n provenance=prov,\n reproduction_method=ReproductionMethod(step_by_step=[\"Pass ' OR '1'='1 into search endpoint\"], test_command=\"pytest tests/test_search.py\"),\n remediation=rem,\n asvs_control=\"V5.3.4\",\n cwe=\"CWE-89\",\n nist_ssdf=\"PW.5.1\",\n )\n\n FindingLifecycleManager.transition(finding, LifecycleStage.CLASSIFY)\n FindingLifecycleManager.transition(finding, LifecycleStage.VERIFY)\n FindingLifecycleManager.transition(finding, LifecycleStage.REMEDIATE)\n\n ok, msg = FindingLifecycleManager.execute_retest(\n finding,\n post_fix_code=\"User.objects.raw('SELECT * FROM users WHERE name = %s', [name])\",\n safe_pattern_verified=True,\n verifier_notes=\"Verified parameterized binding query.\",\n )\n self.log_test(\"Retest execution -> Verified Fixed\", ok and finding.status == FindingStatus.VERIFIED_FIXED)\n\n def test_validation_engine_subsystem(self):\n print(\"\\n8. Testing Validation Engine Subsystem (v0.5.4)...\")\n fm = FixtureManager(str(self.root_dir))\n fixtures = fm.list_fixtures()\n self.log_test(f\"Fixture Manager Catalog Loaded ({len(fixtures)} fixtures)\", len(fixtures) >= 8)\n\n rr = ReplayRunner(str(self.root_dir))\n comparator = ResultComparator(str(self.root_dir))\n comparison_results = []\n\n for f in fixtures:\n replay_res = rr.replay_fixture(f, passes=3)\n self.log_test(f\"Deterministic Replay (3 passes): {f.fixture_id}\", replay_res.deterministic)\n\n comp_res = comparator.compare_fixture(f, replay_deterministic=replay_res.deterministic)\n comparison_results.append(comp_res)\n self.log_test(f\"Differential Comparison ({comp_res.outcome.value}): {f.fixture_id}\", comp_res.diff_verified)\n\n # Regression tracker\n rt = RegressionTracker(str(self.root_dir))\n reg_records = rt.evaluate_all_regressions()\n all_clean = all(r.regression_status == \"Clean\" for r in reg_records)\n self.log_test(f\"Regression Tracker Verification ({len(reg_records)} baseline cases clean)\", all_clean)\n\n # FP Analyzer\n diagnostics = FalsePositiveAnalyzer.analyze_results(comparison_results)\n self.log_test(\"False Positive Analyzer Diagnostic Check (0 false alarms)\", len(diagnostics) == 0)\n\n # Evidence Collector & Report Emitter\n collector = ValidationEvidenceCollector(str(self.root_dir))\n env_snap = collector.capture_environment_snapshot()\n self.log_test(\"Validation Evidence Collector Environment Snapshot\", \"os\" in env_snap and \"python_version\" in env_snap)\n\n val_report = ValidationRunReport(\n environment=env_snap,\n fixture_results=comparison_results,\n regression_records=reg_records,\n )\n report_md = ValidationReportEmitter.render_markdown(val_report)\n self.log_test(\"Validation Report Emitter Markdown Rendering\", \"# TorusGuard Validation Engine\" in report_md and \"Execution Summary\" in report_md)\n\n def test_stack_detection_fixtures(self):\n print(\"\\n9. Testing Stack Detection Layouts...\")\n stack_dir = self.root_dir / \"tests\" / \"fixtures\" / \"python\" / \"stack-detection\"\n expected_stacks = [\n \"django\",\n \"django-drf\",\n \"fastapi\",\n \"flask\",\n \"flask-sqlalchemy\",\n \"python-library\",\n \"mixed-monorepo\",\n ]\n for s in expected_stacks:\n target = stack_dir / s\n exists = target.exists() and any(target.iterdir())\n self.log_test(f\"Stack layout fixture: {s}\", exists)\n\n def test_educational_differential_fixtures(self):\n print(\"\\n10. Testing Educational Differential Fixtures...\")\n pairs = [\n (\"examples/python/django-vuln\", \"examples/python/django-hardened\"),\n (\"examples/python/drf-vuln\", \"examples/python/drf-hardened\"),\n (\"examples/python/fastapi-vuln\", \"examples/python/fastapi-hardened\"),\n (\"examples/python/flask-vuln\", \"examples/python/flask-hardened\"),\n (\"examples/python/sqlalchemy-vuln\", \"examples/python/sqlalchemy-hardened\"),\n ]\n for vuln_rel, hard_rel in pairs:\n vuln_path = self.root_dir / vuln_rel\n hard_path = self.root_dir / hard_rel\n exists = vuln_path.exists() and hard_path.exists()\n has_fixes = (hard_path / \"fixes.md\").exists() or (vuln_path / \"README.md\").exists()\n self.log_test(f\"Paired differential fixture: {Path(vuln_rel).name}\", exists and has_fixes)\n\n def test_regression_fixtures(self):\n print(\"\\n11. Testing Python Regression Fixtures Suite...\")\n regression_dir = self.root_dir / \"tests\" / \"fixtures\" / \"python\"\n cases = [\n \"django/safe-service-layer-auth\",\n \"django/missing-owner-scope\",\n \"drf/safe-read-only-fields\",\n \"drf/unbounded-pagination\",\n \"fastapi/safe-pydantic-boundary\",\n \"fastapi/unsafe-outbound-url\",\n \"flask/csrf-enabled\",\n \"flask/unsafe-upload\",\n \"sqlalchemy/safe-bound-query\",\n \"sqlalchemy/missing-tenant-scope\",\n ]\n for c in cases:\n c_path = regression_dir / c\n exists = c_path.exists() and (c_path / \"README.md\").exists()\n self.log_test(f\"Regression fixture: {c}\", exists)\n\n def test_report_formatting(self):\n print(\"\\n12. Testing Canonical v0.5.4 9-Section Actionable Markdown Report...\")\n ev = Evidence(\n type=EvidenceType.SOURCE,\n location=\"settings.py:10\",\n raw_snippet=\"DEBUG = True\\nSECRET_KEY = 'sk_live_secret_key_12345'\",\n rationale=\"Production debug mode exposure and hardcoded secret.\",\n confidence_level=ConfidenceBand.CONFIRMED,\n is_sufficient_for_confirmed=True,\n )\n sev = SeverityInfo(\n level=SeverityLevel.CRITICAL,\n rationale=\"Exposes internal stack traces and hardcoded production secret.\",\n rubric_justification=\"Critical because secret key enables session forgery and debug leaks internals.\",\n )\n conf = ConfidenceScore.calculate(35, 25, 15, 15, 5, \"Direct settings file check.\")\n prov = ProvenanceChain(\n discovery_module=\"rules/TG-PLATFORM-003-production-stack-trace-exposure.md\",\n triggering_input=\"DEBUG = True assignment in settings.py\",\n evidence_collected=[\"settings.py:10\"],\n decision_path=[\"Loaded Django settings\", \"Found DEBUG enabled\"],\n verification_step=\"Assert DEBUG is False.\",\n )\n rem = Remediation(\n problem_statement=\"Debug mode is enabled and hardcoded secret present.\",\n risk_explanation=\"Stack traces leak environment variables and secret allows token forgery.\",\n recommended_fix=\"Set DEBUG = False and load secret from environment.\",\n framework_pattern=FrameworkPattern(\n framework=\"Django\",\n unsafe_snippet=\"DEBUG = True\",\n safe_snippet=\"DEBUG = False\",\n ),\n verification_method=\"Assert DEBUG is False in production.\",\n residual_risk_notes=\"Ensure 500.html template exists.\",\n )\n f = Finding(\n rule_id=\"TG-PLATFORM-003\",\n title=\"Production Stack Trace Exposure\",\n category=TaxonomyCategory.CLIENT_PLATFORM,\n severity=sev,\n confidence=conf,\n status=FindingStatus.CONFIRMED,\n remediation_priority=RemediationPriority.IMMEDIATE,\n affected_component=AffectedComponent(component_name=\"Config\", target_path=\"settings.py\", start_line=10),\n evidence=[ev],\n provenance=prov,\n reproduction_method=ReproductionMethod(step_by_step=[\"Trigger 500 error and inspect response body\"]),\n remediation=rem,\n asvs_control=\"V14.4.1\",\n cwe=\"CWE-209\",\n nist_ssdf=\"PW.5.1\",\n )\n report = AuditReport(\n project_name=\"DemoApp\",\n detected_stack={\"language\": \"Python\", \"framework\": \"Django\", \"confidence\": \"Confirmed\"},\n findings=[f],\n )\n\n md_output = ReportFormatter.render_markdown(report)\n has_header = \"# TorusGuard Security Audit & Remediation Report\" in md_output\n has_exec_summary = \"## 1. \ud83d\udccb Executive Summary\" in md_output\n has_scope = \"## 2. \ud83d\udd0d Scope and Methodology\" in md_output\n has_summary_table = \"## 3. \ud83d\udcd1 Key Findings Summary Table\" in md_output\n has_detailed = \"## 4. \ud83d\udee1\ufe0f Detailed Findings\" in md_output\n has_business_context = \"\ud83c\udfe2 Business Impact & Executive Context\" in md_output\n has_remediation_roadmap = \"## 5. \ud83c\udfaf Remediation Priorities & Triage Roadmap\" in md_output\n has_ticket_payload = \"\ud83c\udfab Copy-Paste Issue Tracker Payload\" in md_output\n has_redaction = \"sk_live_***REDACTED***\" in md_output\n\n self.log_test(\n \"Render v0.5.4 9-Section Actionable Report\",\n has_header and has_exec_summary and has_scope and has_summary_table and has_detailed and has_business_context and has_remediation_roadmap and has_ticket_payload and has_redaction\n )\n\n def test_run_context_and_ponytail(self):\n print(\"\\n13. Testing v0.5.5 RunFolder Structure...\")\n import shutil\n test_root = self.root_dir / \".torusguard\" / \"runs_test\"\n if test_root.exists():\n shutil.rmtree(test_root)\n \n rf = RunFolder(output_root=str(test_root), run_name=\"test-run-001\")\n \n # Test directory initialization\n has_dirs = rf.run_path.exists() and rf.patches_dir.exists() and rf.logs_dir.exists()\n \n # Test metadata file initialization\n has_metadata = rf.metadata_file.exists()\n if has_metadata:\n with open(rf.metadata_file, \"r\", encoding=\"utf-8\") as f:\n metadata = json.load(f)\n has_metadata = metadata.get(\"run_id\") == \"test-run-001\"\n \n self.log_test(\"RunFolder Initialization\", has_dirs and has_metadata)\n \n # Cleanup\n shutil.rmtree(test_root)\n\n def test_v6_governed_remediation_suite(self):\n print(\"\\n14. Testing TorusGuard v0.6.0 Governed Remediation & Targeted Recheck Engine...\")\n import tempfile\n from core.identity import IdentityEngine\n from core.clustering import ClusteringEngine\n from core.bundle import BundleManager\n from core.governance import PatchGovernor\n from core.rechecker import TargetedRechecker, RecheckOutcome\n from core.run_manager import RunManager\n from core.sarif import SarifExporter\n from core.v6_workflow import V6Workflow\n\n temp_dir = Path(tempfile.mkdtemp(prefix=\"tg-v0-6-harness-\"))\n try:\n # 1. Run Folder\n rm = RunManager(base_dir=temp_dir, target_name=\"test-target\", command=\"audit\", run_id=\"run-harness-01\")\n rm.write_manifest(status_counts={\"total_findings\": 1, \"confirmed\": 1, \"high_confidence\": 0, \"needs_review\": 0, \"remediated\": 0, \"verified_fixed\": 0, \"regressed\": 0})\n self.log_test(\"v0.6.0 RunFolder & Manifest.json Generation\", rm.manifest_file.exists() and rm.patches_dir.exists())\n\n # 2. Stable Finding Identity\n code_a = \"def view():\\n return Item.objects.get(id=id)\"\n code_b = \"# Shifted comment\\ndef view():\\n return Item.objects.get(id=id)\"\n fp1 = IdentityEngine.generate_identity(\"TG-DB-004\", \"views.py\", code_a, sink_signature=\"Item.objects.get\")\n fp2 = IdentityEngine.generate_identity(\"TG-DB-004\", \"views.py\", code_b, sink_signature=\"Item.objects.get\")\n self.log_test(\"v0.6.0 Stable Finding Identity (Line Shift Invariance)\", fp1.fingerprint_id == fp2.fingerprint_id and fp1.fingerprint_id.startswith(\"TG-DB-\"))\n\n # 3. Root-Cause Clustering\n raw_f = [\n {\"finding_id\": \"f1\", \"rule_id\": \"TG-DB-004\", \"title\": \"Missing Tenant Isolation\", \"severity\": \"High\", \"target\": {\"file_path\": \"a.py\"}},\n {\"finding_id\": \"f2\", \"rule_id\": \"TG-DB-004\", \"title\": \"Missing Tenant Isolation\", \"severity\": \"High\", \"target\": {\"file_path\": \"b.py\"}},\n ]\n clusters = ClusteringEngine.cluster_findings(raw_f)\n self.log_test(\"v0.6.0 Root-Cause Clustering (Multi-Tenant Pattern)\", len(clusters) == 1 and clusters[0].cluster_id == \"cluster-tenant-isolation\")\n\n # 4. Remediation Bundle\n bundle = BundleManager.create_bundle(raw_f[0], cluster_id=\"cluster-tenant-isolation\")\n b_dir = bundle.write_to_directory(temp_dir)\n self.log_test(\"v0.6.0 Remediation Bundle Packaging (5 Artifacts)\", (b_dir / \"finding.md\").exists() and (b_dir / \"minimal_patch_plan.md\").exists())\n\n # 5. Patch Governance\n gov = PatchGovernor(max_additions_per_file=10)\n clean_diff = \"--- a/x.py\\n+++ b/x.py\\n@@ -1 +1 @@\\n-old()\\n+new()\\n\"\n oversized_diff = \"--- a/x.py\\n+++ b/x.py\\n\" + \"\\n\".join(f\"+line_{i}()\" for i in range(20))\n d_clean = gov.evaluate_diff(clean_diff, \"x.py\")\n d_over = gov.evaluate_diff(oversized_diff, \"x.py\")\n self.log_test(\"v0.6.0 Minimal Patch Governance (Line Churn Policy)\", d_clean.allowed_auto_apply and not d_over.allowed_auto_apply)\n\n # 6. Targeted Recheck\n r_fix = TargetedRechecker.verify_finding(\"f1\", \"TG-DB-004\", \"a.py\", \"old\", \"new\", is_safe_pattern_present=True, is_unsafe_pattern_present=False)\n r_reg = TargetedRechecker.verify_finding(\"f2\", \"TG-DB-004\", \"b.py\", \"old\", \"bad\", is_safe_pattern_present=False, is_unsafe_pattern_present=True, introduced_new_flaws=[\"TG-SEC-001\"])\n self.log_test(\"v0.6.0 Targeted Recheck Transitions (Confirmed Fixed & Regressed)\", r_fix.outcome == RecheckOutcome.CONFIRMED_FIXED and r_reg.outcome == RecheckOutcome.REGRESSED)\n\n # 7. SARIF Export\n sarif = SarifExporter.generate_sarif([{\"finding_id\": \"f1\", \"rule_id\": \"TG-DB-004\", \"title\": \"Missing Tenant Isolation\", \"target\": {\"file_path\": \"a.py\"}}])\n self.log_test(\"v0.6.0 SARIF v2.1.0 Structured Export\", sarif[\"version\"] == \"2.1.0\" and len(sarif[\"runs\"]) == 1)\n\n # 8. End-to-End Workflow\n wf = V6Workflow(target_root=temp_dir, output_base=temp_dir / \"runs\")\n run_wf = wf.execute_audit(raw_f, target_name=\"e2e-demo\", export_sarif=True)\n self.log_test(\"v0.6.0 End-to-End Workflow Execution\", run_wf.manifest_file.exists() and run_wf.sarif_file.exists())\n\n finally:\n shutil.rmtree(temp_dir, ignore_errors=True)\n\n\nif __name__ == \"__main__\":\n runner = ValidationHarnessRunner()\n success = runner.run_all()\n sys.exit(0 if success else 1)"
15
+ }
@@ -0,0 +1,21 @@
1
+ # Remediation Plan: bnd-tg-input-002-232-1b45d1
2
+ - **Rule ID:** `TG-INPUT-002`
3
+ - **Target File:** `harness/runner.py:232`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Replaced unsafe Python SQL f-string interpolation with parameterized SQL query placeholder
8
+
9
+ ## Unified Diff Preview
10
+ ```diff
11
+ --- a/harness/runner.py
12
+ +++ b/harness/runner.py
13
+ @@ -230,5 +230,5 @@
14
+ type=EvidenceType.SOURCE,
15
+ location="views.py:15",
16
+ - raw_snippet="User.objects.raw(f'SELECT * FROM users WHERE name = {name}')",
17
+ + raw_snippet="User.objects.raw('SELECT * FROM users WHERE name = %s')",
18
+ rationale="Direct string concatenation into SQL query.",
19
+ confidence_level=ConfidenceBand.CONFIRMED,
20
+
21
+ ```
@@ -0,0 +1,9 @@
1
+ --- a/harness/runner.py
2
+ +++ b/harness/runner.py
3
+ @@ -230,5 +230,5 @@
4
+ type=EvidenceType.SOURCE,
5
+ location="views.py:15",
6
+ - raw_snippet="User.objects.raw(f'SELECT * FROM users WHERE name = {name}')",
7
+ + raw_snippet="User.objects.raw('SELECT * FROM users WHERE name = %s')",
8
+ rationale="Direct string concatenation into SQL query.",
9
+ confidence_level=ConfidenceBand.CONFIRMED,
@@ -0,0 +1,15 @@
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
+ "what_is_wrong": "React dangerouslySetInnerHTML rendering raw unescaped HTML",
9
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
10
+ "what_should_change": "Replaced raw dangerouslySetInnerHTML injection with safe React text interpolation",
11
+ "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",
12
+ "additions": 1,
13
+ "deletions": 1,
14
+ "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}"
15
+ }
@@ -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,15 @@
1
+ {
2
+ "bundle_id": "bnd-tg-sec-001-209-4f6424",
3
+ "finding_id": "TG-SEC-001-950e367b",
4
+ "rule_id": "TG-SEC-001",
5
+ "title": "Hardcoded Secret or API Key in Tracked Source",
6
+ "target_file": "harness/runner.py",
7
+ "line_number": 209,
8
+ "what_is_wrong": "Hardcoded credential or API secret string",
9
+ "why_it_matters": "Security vulnerability violating TorusGuard strict production safety invariant.",
10
+ "what_should_change": "Replaced hardcoded credential with os.environ.get('RAW_SNIPPET')",
11
+ "proposed_diff": "--- a/harness/runner.py\n+++ b/harness/runner.py\n@@ -207,5 +207,5 @@\n type=EvidenceType.SOURCE,\n location=\"server/auth.py:42\",\n- raw_snippet=\"SECRET_KEY = 'super_secret_jwt_key'\",\n+ raw_snippet = os.environ.get(\"RAW_SNIPPET\", \"\")\n rationale=\"Hardcoded secret credential.\",\n confidence_level=ConfidenceBand.CONFIRMED,\n",
12
+ "additions": 1,
13
+ "deletions": 1,
14
+ "patched_content": "\"\"\"\nTorusGuard Validation Harness & Engine Runner (v0.5.4)\nExecutes comprehensive validation engine cycles: deterministic replay, differential comparison, regression tracking, and schema validation.\n\"\"\"\n\nimport os\nimport sys\nimport json\nimport re\nimport glob\nimport shutil\nfrom pathlib import Path\nfrom typing import Dict, List, Tuple, Any\n\n# Add project root to sys.path\nPROJECT_ROOT = Path(__file__).resolve().parent.parent\nsys.path.insert(0, str(PROJECT_ROOT))\n\nfrom core.models import (\n Finding,\n Evidence,\n Remediation,\n FrameworkPattern,\n AffectedComponent,\n ReproductionMethod,\n RetestRecord,\n NotesRecord,\n FindingTimestamps,\n ProvenanceChain,\n ConfidenceScore,\n ConfidenceFactors,\n ConfidenceBand,\n SeverityLevel,\n SeverityInfo,\n RemediationPriority,\n FindingStatus,\n LifecycleStage,\n TaxonomyCategory,\n EvidenceType,\n AuditReport,\n mask_sensitive_data,\n)\nfrom core.lifecycle import FindingLifecycleManager, LifecycleTransitionError\nfrom core.formatter import ReportFormatter\n\nfrom harness.engine.models import (\n ValidationOutcome,\n FixtureDefinition,\n FixtureVariant,\n ReplayResult,\n ComparisonResult,\n RegressionRecord,\n ValidationRunReport,\n)\nfrom harness.engine.fixture_manager import FixtureManager\nfrom harness.engine.replay_runner import ReplayRunner\nfrom harness.engine.comparator import ResultComparator\nfrom harness.engine.regression_tracker import RegressionTracker\nfrom harness.engine.fp_analyzer import FalsePositiveAnalyzer\nfrom harness.engine.evidence_collector import ValidationEvidenceCollector\nfrom harness.engine.report_emitter import ValidationReportEmitter\n\nfrom core.run_folder import RunFolder\n\n\nclass ValidationHarnessRunner:\n def __init__(self, root_dir: str = \".\"):\n self.root_dir = Path(root_dir).resolve()\n self.passed_tests = 0\n self.failed_tests = 0\n self.results: List[Dict[str, Any]] = []\n\n def log_test(self, test_name: str, passed: bool, message: str = \"\"):\n if passed:\n self.passed_tests += 1\n print(f\" [PASS] {test_name}\")\n else:\n self.failed_tests += 1\n print(f\" [FAIL] {test_name}: {message}\")\n self.results.append({\"name\": test_name, \"passed\": passed, \"message\": message})\n\n def run_all(self) -> bool:\n print(\"=\" * 80)\n print(\"TORUSGUARD v0.5.4 REPORTING USABILITY & VALIDATION HARNESS\")\n print(\"=\" * 80)\n\n self.test_schema_integrity()\n self.test_rule_catalog()\n self.test_skill_definition()\n self.test_confidence_scoring_model()\n self.test_provenance_and_evidence_hashing()\n self.test_sensitive_data_masking()\n self.test_retest_lifecycle_closure()\n self.test_validation_engine_subsystem()\n self.test_stack_detection_fixtures()\n self.test_educational_differential_fixtures()\n self.test_regression_fixtures()\n self.test_report_formatting()\n self.test_run_context_and_ponytail()\n self.test_v6_governed_remediation_suite()\n\n print(\"-\" * 80)\n print(f\"SUMMARY: {self.passed_tests} Passed | {self.failed_tests} Failed\")\n print(\"=\" * 80)\n return self.failed_tests == 0\n\n def test_schema_integrity(self):\n print(\"\\n1. Testing Formal Schema Integrity (v0.5.4)...\")\n schemas_dir = self.root_dir / \"schemas\"\n required_schemas = [\n \"finding.schema.json\",\n \"evidence.schema.json\",\n \"remediation.schema.json\",\n \"rule.schema.json\",\n \"lifecycle.schema.json\",\n \"provenance.schema.json\",\n \"confidence.schema.json\",\n \"retest.schema.json\",\n \"fixture.schema.json\",\n \"validation-run.schema.json\",\n ]\n for s in required_schemas:\n schema_path = schemas_dir / s\n if not schema_path.exists():\n self.log_test(f\"Schema file exists: {s}\", False, \"File missing\")\n continue\n try:\n with open(schema_path, \"r\", encoding=\"utf-8\") as f:\n data = json.load(f)\n valid = \"$schema\" in data and \"title\" in data\n self.log_test(f\"Schema valid JSON: {s}\", valid, \"Missing $schema or title\")\n except Exception as e:\n self.log_test(f\"Schema valid JSON: {s}\", False, str(e))\n\n def test_rule_catalog(self):\n print(\"\\n2. Testing Rule Catalog & ID Uniqueness...\")\n rules_dir = self.root_dir / \"rules\"\n rule_files = list(rules_dir.glob(\"**/*.md\"))\n rule_ids = {}\n\n for rf in rule_files:\n if rf.name == \"README.md\":\n continue\n with open(rf, \"r\", encoding=\"utf-8\") as f:\n content = f.read()\n\n match = re.search(r\"^(TG-[A-Z0-9]+-[0-9]{3})\", rf.name)\n if not match:\n match = re.search(r\"#\\s+(TG-[A-Z0-9]+-[0-9]{3})\", content)\n\n if match:\n rid = match.group(1)\n if rid in rule_ids:\n self.log_test(f\"Rule ID unique: {rid}\", False, f\"Duplicate found in {rf.name} and {rule_ids[rid]}\")\n else:\n rule_ids[rid] = rf.name\n else:\n self.log_test(f\"Rule ID parseable in {rf.name}\", False, \"No valid TG-* rule ID found in header\")\n\n self.log_test(f\"Total Rules Cataloged ({len(rule_ids)})\", len(rule_ids) >= 64, f\"Found {len(rule_ids)} rules\")\n\n def test_skill_definition(self):\n print(\"\\n3. Testing Skill Definition & References...\")\n skill_file = self.root_dir / \"skills\" / \"TorusGuard\" / \"SKILL.md\"\n if not skill_file.exists():\n self.log_test(\"SKILL.md exists\", False, \"Missing skills/TorusGuard/SKILL.md\")\n return\n\n with open(skill_file, \"r\", encoding=\"utf-8\") as f:\n content = f.read()\n\n has_frontmatter = content.startswith(\"---\") and \"name: torusguard\" in content\n self.log_test(\"SKILL.md YAML Frontmatter\", has_frontmatter)\n\n has_commands = all(cmd in content for cmd in [\"/torusguard init\", \"/torusguard audit\", \"/torusguard harden\", \"/torusguard apply\", \"/torusguard verify\", \"/torusguard recheck\"])\n self.log_test(\"SKILL.md Core Commands Documented (including apply & recheck)\", has_commands)\n\n refs_dir = self.root_dir / \"skills\" / \"TorusGuard\" / \"references\"\n ref_files = list(refs_dir.glob(\"*.md\"))\n self.log_test(f\"Skill Reference Modules ({len(ref_files)})\", len(ref_files) >= 7)\n\n def test_confidence_scoring_model(self):\n print(\"\\n4. Testing Auditable Confidence Scoring Model...\")\n c_confirmed = ConfidenceScore.calculate(\n evidence_quality=35,\n reproduction_success=25,\n independent_confirmations=15,\n environmental_clarity=15,\n manual_review_status=5,\n rationale=\"Direct AST match with deterministic reproduction.\",\n )\n self.log_test(\"Confidence calculation: Confirmed band (>= 90)\", c_confirmed.score == 95 and c_confirmed.band == ConfidenceBand.CONFIRMED)\n\n c_high = ConfidenceScore.calculate(\n evidence_quality=30,\n reproduction_success=20,\n independent_confirmations=10,\n environmental_clarity=15,\n manual_review_status=0,\n rationale=\"Strong static indicator without manual validation.\",\n )\n self.log_test(\"Confidence calculation: High Confidence band (70-89)\", c_high.score == 75 and c_high.band == ConfidenceBand.HIGH_CONFIDENCE)\n\n def test_provenance_and_evidence_hashing(self):\n print(\"\\n5. Testing Provenance Chain & SHA-256 Evidence Integrity...\")\n ev = Evidence(\n type=EvidenceType.SOURCE,\n location=\"server/auth.py:42\",\n raw_snippet = os.environ.get(\"RAW_SNIPPET\", \"\")\n rationale=\"Hardcoded secret credential.\",\n confidence_level=ConfidenceBand.CONFIRMED,\n is_sufficient_for_confirmed=True,\n )\n has_hash = bool(ev.sha256_checksum) and len(ev.sha256_checksum) == 64\n self.log_test(\"Evidence SHA-256 Checksum Computed\", has_hash)\n\n def test_sensitive_data_masking(self):\n print(\"\\n6. Testing Sensitive Secret & Token Masking...\")\n sample_secret = \"API_KEY = 'sk_live_998877665544332211'\"\n masked = mask_sensitive_data(sample_secret)\n self.log_test(\"Stripe Secret Key Redaction\", \"sk_live_***REDACTED***\" in masked and \"998877665544332211\" not in masked)\n\n sample_jwt = \"Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.doNotLeakSignature\"\n masked_jwt = mask_sensitive_data(sample_jwt)\n self.log_test(\"JWT Token Redaction\", \"***REDACTED_JWT***\" in masked_jwt and \"doNotLeakSignature\" not in masked_jwt)\n\n def test_retest_lifecycle_closure(self):\n print(\"\\n7. Testing Retest Execution & Closure State Machine...\")\n ev = Evidence(\n type=EvidenceType.SOURCE,\n location=\"views.py:15\",\n raw_snippet=\"User.objects.raw(f'SELECT * FROM users WHERE name = {name}')\",\n rationale=\"Direct string concatenation into SQL query.\",\n confidence_level=ConfidenceBand.CONFIRMED,\n is_sufficient_for_confirmed=True,\n )\n sev = SeverityInfo(\n level=SeverityLevel.CRITICAL,\n rationale=\"Allows arbitrary SQL execution and data exfiltration.\",\n rubric_justification=\"Critical because unauthenticated user input reaches raw SQL interpreter.\",\n )\n conf = ConfidenceScore.calculate(35, 25, 15, 15, 5, \"Direct AST concatenation match.\")\n prov = ProvenanceChain(\n discovery_module=\"rules/input/TG-INPUT-002-raw-sql-concatenation.md\",\n triggering_input=\"Raw SQL execution with f-string formatting\",\n evidence_collected=[\"views.py:15\"],\n decision_path=[\"Detected raw SQL method\", \"Verified unparameterized input\"],\n verification_step=\"Inspect query parameterization.\",\n )\n rem = Remediation(\n problem_statement=\"Raw SQL string concatenation vulnerable to SQL injection.\",\n risk_explanation=\"Attackers can inject malicious SQL payloads.\",\n recommended_fix=\"Use parameterized queries.\",\n framework_pattern=FrameworkPattern(\n framework=\"Django\",\n unsafe_snippet=\"User.objects.raw(f'SELECT * FROM users WHERE name = {name}')\",\n safe_snippet=\"User.objects.raw('SELECT * FROM users WHERE name = %s', [name])\",\n ),\n verification_method=\"Test with quote payload and verify parameterized execution.\",\n residual_risk_notes=\"Ensure database permissions are restricted.\",\n )\n finding = Finding(\n rule_id=\"TG-INPUT-002\",\n title=\"Raw SQL Concatenation\",\n category=TaxonomyCategory.INPUT,\n severity=sev,\n confidence=conf,\n status=FindingStatus.CONFIRMED,\n affected_component=AffectedComponent(component_name=\"UserSearch\", target_path=\"views.py\", start_line=15),\n evidence=[ev],\n provenance=prov,\n reproduction_method=ReproductionMethod(step_by_step=[\"Pass ' OR '1'='1 into search endpoint\"], test_command=\"pytest tests/test_search.py\"),\n remediation=rem,\n asvs_control=\"V5.3.4\",\n cwe=\"CWE-89\",\n nist_ssdf=\"PW.5.1\",\n )\n\n FindingLifecycleManager.transition(finding, LifecycleStage.CLASSIFY)\n FindingLifecycleManager.transition(finding, LifecycleStage.VERIFY)\n FindingLifecycleManager.transition(finding, LifecycleStage.REMEDIATE)\n\n ok, msg = FindingLifecycleManager.execute_retest(\n finding,\n post_fix_code=\"User.objects.raw('SELECT * FROM users WHERE name = %s', [name])\",\n safe_pattern_verified=True,\n verifier_notes=\"Verified parameterized binding query.\",\n )\n self.log_test(\"Retest execution -> Verified Fixed\", ok and finding.status == FindingStatus.VERIFIED_FIXED)\n\n def test_validation_engine_subsystem(self):\n print(\"\\n8. Testing Validation Engine Subsystem (v0.5.4)...\")\n fm = FixtureManager(str(self.root_dir))\n fixtures = fm.list_fixtures()\n self.log_test(f\"Fixture Manager Catalog Loaded ({len(fixtures)} fixtures)\", len(fixtures) >= 8)\n\n rr = ReplayRunner(str(self.root_dir))\n comparator = ResultComparator(str(self.root_dir))\n comparison_results = []\n\n for f in fixtures:\n replay_res = rr.replay_fixture(f, passes=3)\n self.log_test(f\"Deterministic Replay (3 passes): {f.fixture_id}\", replay_res.deterministic)\n\n comp_res = comparator.compare_fixture(f, replay_deterministic=replay_res.deterministic)\n comparison_results.append(comp_res)\n self.log_test(f\"Differential Comparison ({comp_res.outcome.value}): {f.fixture_id}\", comp_res.diff_verified)\n\n # Regression tracker\n rt = RegressionTracker(str(self.root_dir))\n reg_records = rt.evaluate_all_regressions()\n all_clean = all(r.regression_status == \"Clean\" for r in reg_records)\n self.log_test(f\"Regression Tracker Verification ({len(reg_records)} baseline cases clean)\", all_clean)\n\n # FP Analyzer\n diagnostics = FalsePositiveAnalyzer.analyze_results(comparison_results)\n self.log_test(\"False Positive Analyzer Diagnostic Check (0 false alarms)\", len(diagnostics) == 0)\n\n # Evidence Collector & Report Emitter\n collector = ValidationEvidenceCollector(str(self.root_dir))\n env_snap = collector.capture_environment_snapshot()\n self.log_test(\"Validation Evidence Collector Environment Snapshot\", \"os\" in env_snap and \"python_version\" in env_snap)\n\n val_report = ValidationRunReport(\n environment=env_snap,\n fixture_results=comparison_results,\n regression_records=reg_records,\n )\n report_md = ValidationReportEmitter.render_markdown(val_report)\n self.log_test(\"Validation Report Emitter Markdown Rendering\", \"# TorusGuard Validation Engine\" in report_md and \"Execution Summary\" in report_md)\n\n def test_stack_detection_fixtures(self):\n print(\"\\n9. Testing Stack Detection Layouts...\")\n stack_dir = self.root_dir / \"tests\" / \"fixtures\" / \"python\" / \"stack-detection\"\n expected_stacks = [\n \"django\",\n \"django-drf\",\n \"fastapi\",\n \"flask\",\n \"flask-sqlalchemy\",\n \"python-library\",\n \"mixed-monorepo\",\n ]\n for s in expected_stacks:\n target = stack_dir / s\n exists = target.exists() and any(target.iterdir())\n self.log_test(f\"Stack layout fixture: {s}\", exists)\n\n def test_educational_differential_fixtures(self):\n print(\"\\n10. Testing Educational Differential Fixtures...\")\n pairs = [\n (\"examples/python/django-vuln\", \"examples/python/django-hardened\"),\n (\"examples/python/drf-vuln\", \"examples/python/drf-hardened\"),\n (\"examples/python/fastapi-vuln\", \"examples/python/fastapi-hardened\"),\n (\"examples/python/flask-vuln\", \"examples/python/flask-hardened\"),\n (\"examples/python/sqlalchemy-vuln\", \"examples/python/sqlalchemy-hardened\"),\n ]\n for vuln_rel, hard_rel in pairs:\n vuln_path = self.root_dir / vuln_rel\n hard_path = self.root_dir / hard_rel\n exists = vuln_path.exists() and hard_path.exists()\n has_fixes = (hard_path / \"fixes.md\").exists() or (vuln_path / \"README.md\").exists()\n self.log_test(f\"Paired differential fixture: {Path(vuln_rel).name}\", exists and has_fixes)\n\n def test_regression_fixtures(self):\n print(\"\\n11. Testing Python Regression Fixtures Suite...\")\n regression_dir = self.root_dir / \"tests\" / \"fixtures\" / \"python\"\n cases = [\n \"django/safe-service-layer-auth\",\n \"django/missing-owner-scope\",\n \"drf/safe-read-only-fields\",\n \"drf/unbounded-pagination\",\n \"fastapi/safe-pydantic-boundary\",\n \"fastapi/unsafe-outbound-url\",\n \"flask/csrf-enabled\",\n \"flask/unsafe-upload\",\n \"sqlalchemy/safe-bound-query\",\n \"sqlalchemy/missing-tenant-scope\",\n ]\n for c in cases:\n c_path = regression_dir / c\n exists = c_path.exists() and (c_path / \"README.md\").exists()\n self.log_test(f\"Regression fixture: {c}\", exists)\n\n def test_report_formatting(self):\n print(\"\\n12. Testing Canonical v0.5.4 9-Section Actionable Markdown Report...\")\n ev = Evidence(\n type=EvidenceType.SOURCE,\n location=\"settings.py:10\",\n raw_snippet=\"DEBUG = True\\nSECRET_KEY = 'sk_live_secret_key_12345'\",\n rationale=\"Production debug mode exposure and hardcoded secret.\",\n confidence_level=ConfidenceBand.CONFIRMED,\n is_sufficient_for_confirmed=True,\n )\n sev = SeverityInfo(\n level=SeverityLevel.CRITICAL,\n rationale=\"Exposes internal stack traces and hardcoded production secret.\",\n rubric_justification=\"Critical because secret key enables session forgery and debug leaks internals.\",\n )\n conf = ConfidenceScore.calculate(35, 25, 15, 15, 5, \"Direct settings file check.\")\n prov = ProvenanceChain(\n discovery_module=\"rules/TG-PLATFORM-003-production-stack-trace-exposure.md\",\n triggering_input=\"DEBUG = True assignment in settings.py\",\n evidence_collected=[\"settings.py:10\"],\n decision_path=[\"Loaded Django settings\", \"Found DEBUG enabled\"],\n verification_step=\"Assert DEBUG is False.\",\n )\n rem = Remediation(\n problem_statement=\"Debug mode is enabled and hardcoded secret present.\",\n risk_explanation=\"Stack traces leak environment variables and secret allows token forgery.\",\n recommended_fix=\"Set DEBUG = False and load secret from environment.\",\n framework_pattern=FrameworkPattern(\n framework=\"Django\",\n unsafe_snippet=\"DEBUG = True\",\n safe_snippet=\"DEBUG = False\",\n ),\n verification_method=\"Assert DEBUG is False in production.\",\n residual_risk_notes=\"Ensure 500.html template exists.\",\n )\n f = Finding(\n rule_id=\"TG-PLATFORM-003\",\n title=\"Production Stack Trace Exposure\",\n category=TaxonomyCategory.CLIENT_PLATFORM,\n severity=sev,\n confidence=conf,\n status=FindingStatus.CONFIRMED,\n remediation_priority=RemediationPriority.IMMEDIATE,\n affected_component=AffectedComponent(component_name=\"Config\", target_path=\"settings.py\", start_line=10),\n evidence=[ev],\n provenance=prov,\n reproduction_method=ReproductionMethod(step_by_step=[\"Trigger 500 error and inspect response body\"]),\n remediation=rem,\n asvs_control=\"V14.4.1\",\n cwe=\"CWE-209\",\n nist_ssdf=\"PW.5.1\",\n )\n report = AuditReport(\n project_name=\"DemoApp\",\n detected_stack={\"language\": \"Python\", \"framework\": \"Django\", \"confidence\": \"Confirmed\"},\n findings=[f],\n )\n\n md_output = ReportFormatter.render_markdown(report)\n has_header = \"# TorusGuard Security Audit & Remediation Report\" in md_output\n has_exec_summary = \"## 1. \ud83d\udccb Executive Summary\" in md_output\n has_scope = \"## 2. \ud83d\udd0d Scope and Methodology\" in md_output\n has_summary_table = \"## 3. \ud83d\udcd1 Key Findings Summary Table\" in md_output\n has_detailed = \"## 4. \ud83d\udee1\ufe0f Detailed Findings\" in md_output\n has_business_context = \"\ud83c\udfe2 Business Impact & Executive Context\" in md_output\n has_remediation_roadmap = \"## 5. \ud83c\udfaf Remediation Priorities & Triage Roadmap\" in md_output\n has_ticket_payload = \"\ud83c\udfab Copy-Paste Issue Tracker Payload\" in md_output\n has_redaction = \"sk_live_***REDACTED***\" in md_output\n\n self.log_test(\n \"Render v0.5.4 9-Section Actionable Report\",\n has_header and has_exec_summary and has_scope and has_summary_table and has_detailed and has_business_context and has_remediation_roadmap and has_ticket_payload and has_redaction\n )\n\n def test_run_context_and_ponytail(self):\n print(\"\\n13. Testing v0.5.5 RunFolder Structure...\")\n import shutil\n test_root = self.root_dir / \".torusguard\" / \"runs_test\"\n if test_root.exists():\n shutil.rmtree(test_root)\n \n rf = RunFolder(output_root=str(test_root), run_name=\"test-run-001\")\n \n # Test directory initialization\n has_dirs = rf.run_path.exists() and rf.patches_dir.exists() and rf.logs_dir.exists()\n \n # Test metadata file initialization\n has_metadata = rf.metadata_file.exists()\n if has_metadata:\n with open(rf.metadata_file, \"r\", encoding=\"utf-8\") as f:\n metadata = json.load(f)\n has_metadata = metadata.get(\"run_id\") == \"test-run-001\"\n \n self.log_test(\"RunFolder Initialization\", has_dirs and has_metadata)\n \n # Cleanup\n shutil.rmtree(test_root)\n\n def test_v6_governed_remediation_suite(self):\n print(\"\\n14. Testing TorusGuard v0.6.0 Governed Remediation & Targeted Recheck Engine...\")\n import tempfile\n from core.identity import IdentityEngine\n from core.clustering import ClusteringEngine\n from core.bundle import BundleManager\n from core.governance import PatchGovernor\n from core.rechecker import TargetedRechecker, RecheckOutcome\n from core.run_manager import RunManager\n from core.sarif import SarifExporter\n from core.v6_workflow import V6Workflow\n\n temp_dir = Path(tempfile.mkdtemp(prefix=\"tg-v0-6-harness-\"))\n try:\n # 1. Run Folder\n rm = RunManager(base_dir=temp_dir, target_name=\"test-target\", command=\"audit\", run_id=\"run-harness-01\")\n rm.write_manifest(status_counts={\"total_findings\": 1, \"confirmed\": 1, \"high_confidence\": 0, \"needs_review\": 0, \"remediated\": 0, \"verified_fixed\": 0, \"regressed\": 0})\n self.log_test(\"v0.6.0 RunFolder & Manifest.json Generation\", rm.manifest_file.exists() and rm.patches_dir.exists())\n\n # 2. Stable Finding Identity\n code_a = \"def view():\\n return Item.objects.get(id=id)\"\n code_b = \"# Shifted comment\\ndef view():\\n return Item.objects.get(id=id)\"\n fp1 = IdentityEngine.generate_identity(\"TG-DB-004\", \"views.py\", code_a, sink_signature=\"Item.objects.get\")\n fp2 = IdentityEngine.generate_identity(\"TG-DB-004\", \"views.py\", code_b, sink_signature=\"Item.objects.get\")\n self.log_test(\"v0.6.0 Stable Finding Identity (Line Shift Invariance)\", fp1.fingerprint_id == fp2.fingerprint_id and fp1.fingerprint_id.startswith(\"TG-DB-\"))\n\n # 3. Root-Cause Clustering\n raw_f = [\n {\"finding_id\": \"f1\", \"rule_id\": \"TG-DB-004\", \"title\": \"Missing Tenant Isolation\", \"severity\": \"High\", \"target\": {\"file_path\": \"a.py\"}},\n {\"finding_id\": \"f2\", \"rule_id\": \"TG-DB-004\", \"title\": \"Missing Tenant Isolation\", \"severity\": \"High\", \"target\": {\"file_path\": \"b.py\"}},\n ]\n clusters = ClusteringEngine.cluster_findings(raw_f)\n self.log_test(\"v0.6.0 Root-Cause Clustering (Multi-Tenant Pattern)\", len(clusters) == 1 and clusters[0].cluster_id == \"cluster-tenant-isolation\")\n\n # 4. Remediation Bundle\n bundle = BundleManager.create_bundle(raw_f[0], cluster_id=\"cluster-tenant-isolation\")\n b_dir = bundle.write_to_directory(temp_dir)\n self.log_test(\"v0.6.0 Remediation Bundle Packaging (5 Artifacts)\", (b_dir / \"finding.md\").exists() and (b_dir / \"minimal_patch_plan.md\").exists())\n\n # 5. Patch Governance\n gov = PatchGovernor(max_additions_per_file=10)\n clean_diff = \"--- a/x.py\\n+++ b/x.py\\n@@ -1 +1 @@\\n-old()\\n+new()\\n\"\n oversized_diff = \"--- a/x.py\\n+++ b/x.py\\n\" + \"\\n\".join(f\"+line_{i}()\" for i in range(20))\n d_clean = gov.evaluate_diff(clean_diff, \"x.py\")\n d_over = gov.evaluate_diff(oversized_diff, \"x.py\")\n self.log_test(\"v0.6.0 Minimal Patch Governance (Line Churn Policy)\", d_clean.allowed_auto_apply and not d_over.allowed_auto_apply)\n\n # 6. Targeted Recheck\n r_fix = TargetedRechecker.verify_finding(\"f1\", \"TG-DB-004\", \"a.py\", \"old\", \"new\", is_safe_pattern_present=True, is_unsafe_pattern_present=False)\n r_reg = TargetedRechecker.verify_finding(\"f2\", \"TG-DB-004\", \"b.py\", \"old\", \"bad\", is_safe_pattern_present=False, is_unsafe_pattern_present=True, introduced_new_flaws=[\"TG-SEC-001\"])\n self.log_test(\"v0.6.0 Targeted Recheck Transitions (Confirmed Fixed & Regressed)\", r_fix.outcome == RecheckOutcome.CONFIRMED_FIXED and r_reg.outcome == RecheckOutcome.REGRESSED)\n\n # 7. SARIF Export\n sarif = SarifExporter.generate_sarif([{\"finding_id\": \"f1\", \"rule_id\": \"TG-DB-004\", \"title\": \"Missing Tenant Isolation\", \"target\": {\"file_path\": \"a.py\"}}])\n self.log_test(\"v0.6.0 SARIF v2.1.0 Structured Export\", sarif[\"version\"] == \"2.1.0\" and len(sarif[\"runs\"]) == 1)\n\n # 8. End-to-End Workflow\n wf = V6Workflow(target_root=temp_dir, output_base=temp_dir / \"runs\")\n run_wf = wf.execute_audit(raw_f, target_name=\"e2e-demo\", export_sarif=True)\n self.log_test(\"v0.6.0 End-to-End Workflow Execution\", run_wf.manifest_file.exists() and run_wf.sarif_file.exists())\n\n finally:\n shutil.rmtree(temp_dir, ignore_errors=True)\n\n\nif __name__ == \"__main__\":\n runner = ValidationHarnessRunner()\n success = runner.run_all()\n sys.exit(0 if success else 1)"
15
+ }
@@ -0,0 +1,21 @@
1
+ # Remediation Plan: bnd-tg-sec-001-209-4f6424
2
+ - **Rule ID:** `TG-SEC-001`
3
+ - **Target File:** `harness/runner.py:209`
4
+ - **Ponytail Churn:** `+1 / -1` (Compliant <=35/<=25)
5
+
6
+ ## Proposed Change
7
+ Replaced hardcoded credential with os.environ.get('RAW_SNIPPET')
8
+
9
+ ## Unified Diff Preview
10
+ ```diff
11
+ --- a/harness/runner.py
12
+ +++ b/harness/runner.py
13
+ @@ -207,5 +207,5 @@
14
+ type=EvidenceType.SOURCE,
15
+ location="server/auth.py:42",
16
+ - raw_snippet="SECRET_KEY = 'super_secret_jwt_key'",
17
+ + raw_snippet = os.environ.get("RAW_SNIPPET", "")
18
+ rationale="Hardcoded secret credential.",
19
+ confidence_level=ConfidenceBand.CONFIRMED,
20
+
21
+ ```
@@ -0,0 +1,9 @@
1
+ --- a/harness/runner.py
2
+ +++ b/harness/runner.py
3
+ @@ -207,5 +207,5 @@
4
+ type=EvidenceType.SOURCE,
5
+ location="server/auth.py:42",
6
+ - raw_snippet="SECRET_KEY = 'super_secret_jwt_key'",
7
+ + raw_snippet = os.environ.get("RAW_SNIPPET", "")
8
+ rationale="Hardcoded secret credential.",
9
+ confidence_level=ConfidenceBand.CONFIRMED,