@clear-capabilities/agentic-security-scanner 0.172.1 → 0.174.0

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 (201) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/bin/agentic-security.js +37 -0
  3. package/dist/119.index.js +197 -0
  4. package/dist/128.index.js +129 -0
  5. package/dist/1293.index.js +5689 -0
  6. package/dist/1351.index.js +133 -0
  7. package/dist/1387.index.js +271 -0
  8. package/dist/1437.index.js +23 -0
  9. package/dist/1445.index.js +110 -0
  10. package/dist/1505.index.js +151 -0
  11. package/dist/1557.index.js +293 -0
  12. package/dist/1621.index.js +311 -0
  13. package/dist/1751.index.js +160 -0
  14. package/dist/1765.index.js +727 -0
  15. package/dist/1861.index.js +690 -0
  16. package/dist/1898.index.js +116 -0
  17. package/dist/1906.index.js +433 -0
  18. package/dist/1920.index.js +1 -291
  19. package/dist/208.index.js +1631 -0
  20. package/dist/2199.index.js +0 -239
  21. package/dist/2223.index.js +159 -0
  22. package/dist/2530.index.js +152 -0
  23. package/dist/2565.index.js +116 -0
  24. package/dist/2574.index.js +127 -0
  25. package/dist/2620.index.js +345 -0
  26. package/dist/2773.index.js +98 -0
  27. package/dist/2775.index.js +32 -0
  28. package/dist/2966.index.js +171 -0
  29. package/dist/2972.index.js +87 -0
  30. package/dist/2991.index.js +131 -0
  31. package/dist/3063.index.js +833 -0
  32. package/dist/3075.index.js +227 -0
  33. package/dist/3121.index.js +297 -0
  34. package/dist/3314.index.js +263 -0
  35. package/dist/3480.index.js +1822 -0
  36. package/dist/3481.index.js +24 -0
  37. package/dist/3506.index.js +268 -0
  38. package/dist/3533.index.js +591 -0
  39. package/dist/3653.index.js +450 -0
  40. package/dist/3822.index.js +131 -0
  41. package/dist/3868.index.js +292 -0
  42. package/dist/3917.index.js +152 -0
  43. package/dist/3918.index.js +192 -0
  44. package/dist/4090.index.js +288 -0
  45. package/dist/4121.index.js +1190 -0
  46. package/dist/4142.index.js +0 -239
  47. package/dist/4336.index.js +436 -0
  48. package/dist/4387.index.js +532 -0
  49. package/dist/4413.index.js +302 -0
  50. package/dist/4476.index.js +4510 -0
  51. package/dist/4491.index.js +133 -0
  52. package/dist/4538.index.js +185 -0
  53. package/dist/4684.index.js +319 -0
  54. package/dist/4740.index.js +165 -0
  55. package/dist/4780.index.js +209 -0
  56. package/dist/4802.index.js +225 -0
  57. package/dist/4812.index.js +379 -0
  58. package/dist/4835.index.js +126 -0
  59. package/dist/494.index.js +226 -0
  60. package/dist/4991.index.js +549 -0
  61. package/dist/5199.index.js +305 -0
  62. package/dist/5216.index.js +109 -0
  63. package/dist/5439.index.js +301 -0
  64. package/dist/5443.index.js +97 -0
  65. package/dist/5496.index.js +377 -0
  66. package/dist/550.index.js +2 -1
  67. package/dist/5801.index.js +588 -0
  68. package/dist/5858.index.js +223 -0
  69. package/dist/5933.index.js +143 -0
  70. package/dist/601.index.js +23 -0
  71. package/dist/6173.index.js +273 -0
  72. package/dist/6291.index.js +1871 -0
  73. package/dist/6312.index.js +666 -0
  74. package/dist/634.index.js +16182 -0
  75. package/dist/644.index.js +87 -0
  76. package/dist/6508.index.js +283 -0
  77. package/dist/6560.index.js +645 -0
  78. package/dist/6576.index.js +422 -0
  79. package/dist/6579.index.js +271 -0
  80. package/dist/6745.index.js +305 -0
  81. package/dist/6818.index.js +21642 -0
  82. package/dist/6972.index.js +167 -0
  83. package/dist/6995.index.js +163 -0
  84. package/dist/7249.index.js +191 -0
  85. package/dist/7372.index.js +1197 -0
  86. package/dist/7546.index.js +541 -0
  87. package/dist/76.index.js +448 -0
  88. package/dist/7879.index.js +163 -0
  89. package/dist/8025.index.js +130 -0
  90. package/dist/8054.index.js +248 -0
  91. package/dist/8097.index.js +201 -0
  92. package/dist/8126.index.js +191 -0
  93. package/dist/8178.index.js +78 -0
  94. package/dist/818.index.js +212 -0
  95. package/dist/8382.index.js +93 -0
  96. package/dist/8408.index.js +261 -0
  97. package/dist/8540.index.js +174 -0
  98. package/dist/8635.index.js +802 -0
  99. package/dist/8688.index.js +410 -0
  100. package/dist/8699.index.js +779 -0
  101. package/dist/8891.index.js +457 -0
  102. package/dist/8916.index.js +885 -0
  103. package/dist/9146.index.js +170 -0
  104. package/dist/9168.index.js +841 -0
  105. package/dist/9292.index.js +369 -0
  106. package/dist/9382.index.js +135 -11
  107. package/dist/9422.index.js +866 -0
  108. package/dist/9440.index.js +453 -0
  109. package/dist/9479.index.js +152 -0
  110. package/dist/9481.index.js +220 -0
  111. package/dist/9539.index.js +100 -0
  112. package/dist/9547.index.js +103 -0
  113. package/dist/9560.index.js +41 -61
  114. package/dist/9692.index.js +90 -0
  115. package/dist/9800.index.js +213 -1
  116. package/dist/9899.index.js +138 -0
  117. package/dist/9981.index.js +206 -0
  118. package/dist/999.index.js +117 -0
  119. package/dist/agentic-security.mjs +27 -27
  120. package/dist/agentic-security.mjs.sha256 +1 -1
  121. package/package.json +31 -6
  122. package/src/context-intelligence/candidates.js +2 -1
  123. package/src/context-intelligence/capabilities.js +2 -1
  124. package/src/context-intelligence/cli.js +2 -0
  125. package/src/context-intelligence/config.js +3 -1
  126. package/src/context-intelligence/controls.js +49 -1
  127. package/src/context-intelligence/counterexample.js +200 -0
  128. package/src/context-intelligence/cross-route.js +111 -0
  129. package/src/context-intelligence/findings.js +166 -0
  130. package/src/context-intelligence/invariants.js +197 -0
  131. package/src/context-intelligence/queue.js +6 -1
  132. package/src/context-intelligence/reachability.js +2 -2
  133. package/src/context-intelligence/review.js +68 -4
  134. package/src/dataflow/access-paths.js +11 -0
  135. package/src/dataflow/analysis-limits.js +66 -0
  136. package/src/dataflow/engine.js +282 -24
  137. package/src/dataflow/service-edges.js +174 -0
  138. package/src/dataflow/summaries.js +7 -1
  139. package/src/discovery/judge.js +2 -1
  140. package/src/engine.js +82 -14
  141. package/src/fix/apply-fix-service.js +55 -8
  142. package/src/fix/batch-journal.js +84 -0
  143. package/src/fix/exploit-replay.js +51 -0
  144. package/src/fix/footprint.js +65 -0
  145. package/src/fix/patch-policy.js +49 -0
  146. package/src/fix/secret-persistence.js +39 -0
  147. package/src/fix/test-commands.js +84 -0
  148. package/src/fix/verification-adapters.js +97 -0
  149. package/src/fix/verification-record.js +243 -0
  150. package/src/fix/verify-patch.js +89 -0
  151. package/src/ir/CLAUDE.md +5 -0
  152. package/src/ir/callgraph.js +23 -1
  153. package/src/ir/module-resolver.js +315 -0
  154. package/src/ir/parser-js.js +21 -2
  155. package/src/ir/semantic-graph.js +245 -0
  156. package/src/language/haskell-findings.js +2 -0
  157. package/src/language/haskell-guards.js +1 -1
  158. package/src/language/haskell-ir.js +3 -1
  159. package/src/language/haskell-models.js +94 -0
  160. package/src/language/haskell-security-rules.js +20 -0
  161. package/src/language/nixos-hardening.js +72 -0
  162. package/src/lineage/build-attested-correlation.js +63 -0
  163. package/src/lineage/deployment-identity.js +76 -0
  164. package/src/mcp/tools.js +13 -34
  165. package/src/pipeline/canonical-output.js +64 -0
  166. package/src/pipeline/detector-runner.js +7 -0
  167. package/src/pipeline/scan-health.js +14 -0
  168. package/src/pipeline/supervised-analyzers.js +125 -0
  169. package/src/pipeline/supervised-child.js +17 -0
  170. package/src/pipeline/telemetry.js +79 -0
  171. package/src/posture/accuracy-scorecard.js +98 -9
  172. package/src/posture/artifact-registry.js +5 -0
  173. package/src/posture/assurance/evidence-registry.js +215 -0
  174. package/src/posture/assurance/release-package-verify.js +135 -0
  175. package/src/posture/assurance/release-package.js +118 -0
  176. package/src/posture/assurance/release-verdict.js +94 -0
  177. package/src/posture/assurance/waiver.js +200 -0
  178. package/src/posture/compliance-truth.js +100 -0
  179. package/src/posture/evaluation/scan-child.js +3 -1
  180. package/src/posture/evaluation/why-missed.js +3 -1
  181. package/src/posture/exploitability-evidence.js +141 -0
  182. package/src/posture/fix-verify.js +4 -2
  183. package/src/posture/fleet/exposure-ranking.js +115 -0
  184. package/src/posture/fleet/service-chain-graph.js +150 -0
  185. package/src/posture/graph-reconciliation.js +154 -0
  186. package/src/posture/provenance/coverage.js +103 -0
  187. package/src/posture/provenance/git-evidence.js +84 -0
  188. package/src/posture/provenance/origin-resolver.js +7 -1
  189. package/src/posture/provenance/predicate-replay.js +14 -4
  190. package/src/posture/runtime-correlation.js +61 -15
  191. package/src/posture/runtime-explanation.js +116 -0
  192. package/src/posture/runtime-trace-ingest.js +194 -0
  193. package/src/posture/scan-checkpoint.js +38 -10
  194. package/src/posture/waf-ingest.js +7 -2
  195. package/src/report/index.js +4 -0
  196. package/src/report/oscal.js +38 -0
  197. package/src/report/perspectives.js +150 -0
  198. package/src/sast/_comment-strip.js +8 -1
  199. package/src/sast/ruby.js +26 -0
  200. package/src/sast/zip-slip.js +79 -0
  201. package/src/util/string-memo.js +38 -0
@@ -1 +1 @@
1
- e7ecb2875e67c227bbc9a9643742632dbf486accded83c1ada02043d1c5307d1 agentic-security.mjs
1
+ 238ea18c5a820dabb585208a014c0bbf8459796faeb0711f25852fb9a37a7c7c agentic-security.mjs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clear-capabilities/agentic-security-scanner",
3
- "version": "0.172.1",
3
+ "version": "0.174.0",
4
4
  "description": "Scanner engine for the agentic-security Claude Code plugin: SAST, SCA with reachability and CISA KEV, secrets, IaC, Haskell and Nix/NixOS, prompt-injection, MCP/agent-tool audit, authZ analysis, SBOM, compliance attestation, and more.",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -67,13 +67,24 @@
67
67
  "test": "node ../scripts/run-unit-tests.mjs",
68
68
  "test:extras": "AGENTIC_SECURITY_CPP_DATAFLOW=1 node --test test/cpp-dataflow.test.js && node --experimental-test-module-mocks --test test/fault-injection.test.js && node --experimental-test-module-mocks --test test/detector-fault-injection.test.js && node --experimental-test-module-mocks --test test/detector-fault-injection-k8s-admission.test.js && node --experimental-test-module-mocks --test test/lineage-fault-injection.test.js && npm run test:python",
69
69
  "loop": "node ../scripts/loop-engineering/run.mjs",
70
+ "test:engineering-excellence": "node --test --test-concurrency=1 test/engineering-excellence/e0-01-inventory.test.js test/engineering-excellence/e0-02-baseline.test.js test/engineering-excellence/e0-03-contract.test.js test/engineering-excellence/e0-04-task-manifest.test.js test/engineering-excellence/e0-05-status-runner.test.js test/engineering-excellence/e0-06-backlog.test.js test/engineering-excellence/e1-01-dataset-provenance.test.js test/engineering-excellence/e1-02-splits.test.js test/engineering-excellence/e1-03-scoring.test.js test/engineering-excellence/e1-04-baseline-run.test.js test/engineering-excellence/e1-05-forensics.test.js test/engineering-excellence/e1-05-baseline-forensics.test.js test/engineering-excellence/e1-06-adversarial-controls.test.js test/engineering-excellence/e1-07-realcode-policy.test.js test/engineering-excellence/e1-07-baseline-gate.test.js test/engineering-excellence/e2-06-cross-language.test.js test/engineering-excellence/e2-08-suppression-attribution.test.js test/engineering-excellence/e2-09-semantic-gates.test.js test/engineering-excellence/e4-06-dci-real-app.test.js test/engineering-excellence/e6-08-perf-budget.test.js test/engineering-excellence/e8-02-e2e-demo.test.js test/engineering-excellence/e8-03-regression-report.test.js test/engineering-excellence/e8-04-docs.test.js test/engineering-excellence/e8-05-handoff.test.js test/engineering-excellence/e8-06-release-decision.test.js test/engineering-excellence/u01-ruby-path-resolver.test.js test/engineering-excellence/e1-08-scorecard.test.js test/engineering-excellence/e3-01-patch-routes.test.js test/engineering-excellence/e3-02-fix-verification-record.test.js test/engineering-excellence/e3-03-central-verifier.test.js test/engineering-excellence/e3-04-exploit-replay.test.js test/engineering-excellence/e3-05-functional-preservation.test.js test/engineering-excellence/e3-06-patch-policy.test.js test/engineering-excellence/e3-07-rollback-crash-safety.test.js test/engineering-excellence/e3-08-fix-benchmark.test.js test/engineering-excellence/e2-01-semantic-graph.test.js test/engineering-excellence/e2-02-cross-file-resolution.test.js test/engineering-excellence/e2-03-heap-fields-aliases.test.js test/engineering-excellence/e2-04-async-callbacks-frameworks.test.js test/engineering-excellence/e2-05-interprocedural-contexts.test.js test/engineering-excellence/e2-07-service-edges.test.js test/engineering-excellence/e4-01-dci-audit.test.js test/engineering-excellence/e4-02-invariants.test.js test/engineering-excellence/e4-03-cross-route.test.js test/engineering-excellence/e4-04-counterexample.test.js test/engineering-excellence/e4-05-llm-safeguards.test.js test/engineering-excellence/e4-07-dci-findings.test.js test/engineering-excellence/e6-01-telemetry.test.js test/engineering-excellence/e5-01-runtime-audit.test.js test/engineering-excellence/e5-02-build-identity.test.js test/engineering-excellence/e5-03-privacy-ingest.test.js test/engineering-excellence/e5-04-graph-reconciliation.test.js test/engineering-excellence/e5-05-exploitability-evidence.test.js test/engineering-excellence/e5-06-service-chain-graph.test.js test/engineering-excellence/e5-07-runtime-explanation.test.js test/engineering-excellence/e6-05-supervised-analyzers.test.js test/engineering-excellence/e6-06-determinism.test.js test/engineering-excellence/e6-07-adversarial-boundaries.test.js test/engineering-excellence/e6-03-shared-preprocessing.test.js test/engineering-excellence/e6-04-analysis-cache.test.js test/engineering-excellence/e7-01-evidence-contracts.test.js test/engineering-excellence/e7-03-release-package.test.js test/engineering-excellence/e7-04-compliance-truth.test.js test/engineering-excellence/e7-05-waivers-tenancy.test.js test/engineering-excellence/e7-02-provenance-coverage.test.js test/engineering-excellence/e7-06-fleet-exposure.test.js test/engineering-excellence/e7-07-perspectives.test.js test/engineering-excellence/e7-08-assurance-e2e.test.js test/engineering-excellence/e6-02-completion.test.js",
71
+ "ee:status": "node ../scripts/engineering-excellence/status.mjs --once",
72
+ "ee:init": "node ../scripts/engineering-excellence/init.mjs",
73
+ "ee:inventory": "node ../scripts/engineering-excellence/inventory.mjs",
74
+ "ee:contract": "node ../scripts/engineering-excellence/contract.mjs",
75
+ "ee:backlog": "node ../scripts/engineering-excellence/backlog.mjs",
76
+ "ee:dataset-audit": "node ../scripts/engineering-excellence/dataset-audit.mjs",
77
+ "ee:independent-baseline": "node ../scripts/engineering-excellence/independent-baseline.mjs",
78
+ "ee:dci-audit": "node ../scripts/engineering-excellence/dci-audit.mjs",
79
+ "ee:runtime-audit": "node ../scripts/engineering-excellence/runtime-audit.mjs",
80
+ "ee:ir-matrix": "node ../scripts/engineering-excellence/ir-matrix.mjs",
70
81
  "test:loop-real-prd": "node --test ../scripts/loop-engineering/test/loop-real-prd.test.js",
71
82
  "test:loop": "node --test --test-concurrency=1 ../scripts/loop-engineering/test/loop-manifest.test.js ../scripts/loop-engineering/test/loop-watchdog.test.js ../scripts/loop-engineering/test/loop-background.test.js ../scripts/loop-engineering/test/loop-dashboard.test.js ../scripts/loop-engineering/test/loop-evidence.test.js ../scripts/loop-engineering/test/loop-recovery.test.js ../scripts/loop-engineering/test/loop-remote.test.js ../scripts/loop-engineering/test/loop-runbook.test.js ../scripts/loop-engineering/test/loop-assurance-profile.test.js ../scripts/loop-engineering/test/loop-assurance-runtime.test.js ../scripts/loop-engineering/test/loop-bounds.test.js ../scripts/loop-engineering/test/loop-spend.test.js ../scripts/loop-engineering/test/loop-ci-attest.test.js",
72
83
  "test:python": "node ../scripts/run-python-tests.mjs",
73
84
  "test:smoke": "node --test test/smoke.test.js test/demo-app.test.js",
74
85
  "test:ollama-e2e": "AGENTIC_SECURITY_OLLAMA_E2E=1 node --test test/ollama-e2e.test.js",
75
86
  "test:glob": "node --test test/glob-compat.test.js",
76
- "test:sast": "node --test test/cpp-hardcoded-secret.test.js test/sibling-guard.test.js test/comment-blindness.test.js test/crypto-specialist.test.js test/llm.test.js test/llm-cost-advisor.test.js test/llm-owasp.test.js test/logic.test.js test/authz.test.js test/model-load.test.js test/prompt-template.test.js test/business-logic.test.js test/python-sinks.test.js test/phase1-detectors.test.js test/phase2-detectors.test.js test/phase3-v3.test.js test/phase7-extensions.test.js test/phase8-extensions.test.js test/new-cwe-detectors.test.js test/file-upload.test.js test/llmsecops-detectors.test.js test/db-taint.test.js test/dart-swift.test.js test/zip-slip-containment-guard.test.js test/redos-anchoring.test.js test/path-guard-validator-call.test.js test/redos-nfa.test.js test/weak-randomness.test.js test/csharp-pipeline.test.js test/csharp-cross-file.test.js test/post-quantum-crypto.test.js test/web3-advanced.test.js test/cloud-iam-k8s.test.js test/crypto-protocol.test.js test/ml-supply-chain.test.js test/mcp-audit-scan.test.js test/wrong-context-sanitizer.test.js test/sanitizer-context.test.js test/frontend-hygiene.test.js test/csv-injection.test.js test/stored-taint.test.js test/tree-sitter-sinks.test.js test/kotlin-structural.test.js test/ruby-php-structural.test.js test/java-csharp-structural.test.js test/java-structural-cross-file.test.js test/guard-recognition.test.js test/guard-window-identifier-correlation.test.js test/js-python-framework-structural.test.js test/go-structural.test.js test/secret-concat.test.js test/secret-redaction.test.js test/xss-reflected-multilang.test.js test/code-injection-multilang.test.js test/xxe-multilang.test.js test/xpath-injection-multilang.test.js test/gapfill-batch13.test.js test/agent-untrusted-flow.test.js test/api-authz.test.js test/event-entrypoint.test.js test/iac-terraform.test.js test/cross-service.test.js test/rbac-consistency.test.js test/adversarial-robustness.test.js test/secret-entropy.test.js test/comment-strip.test.js test/juliet-path-filter-gate.test.js test/java-bench-shape-opt-in.test.js test/java-ast-folding.test.js test/java-bench-extras.test.js test/reachability-missing-callgraph-data.test.js test/rate-limit.test.js test/auth-signals.test.js test/convention-deviation.test.js test/resource-exhaustion.test.js test/resource-exhaustion-realworld.test.js test/redirect-toctou.test.js test/redirect-toctou-realworld.test.js test/codegen-sink.test.js test/ownership-authz.test.js test/ownership-authz-realworld.test.js test/t21-precision-audit.test.js test/secrets-coverage.test.js test/prompt-injection-payloads.test.js test/iac-cloud-templates.test.js test/ruby-path-join.test.js test/sast/manifest-line-tracking.test.js test/rust-sast.test.js test/java-deserialization-precision.test.js test/pipeline-env-secret.test.js test/mark-used-vuln-functions.test.js",
87
+ "test:sast": "node --test test/cpp-hardcoded-secret.test.js test/sibling-guard.test.js test/comment-blindness.test.js test/crypto-specialist.test.js test/llm.test.js test/llm-cost-advisor.test.js test/llm-owasp.test.js test/logic.test.js test/authz.test.js test/model-load.test.js test/prompt-template.test.js test/business-logic.test.js test/python-sinks.test.js test/phase1-detectors.test.js test/phase2-detectors.test.js test/phase3-v3.test.js test/phase7-extensions.test.js test/phase8-extensions.test.js test/new-cwe-detectors.test.js test/file-upload.test.js test/llmsecops-detectors.test.js test/db-taint.test.js test/dart-swift.test.js test/zip-slip-containment-guard.test.js test/zip-slip-go.test.js test/redos-anchoring.test.js test/path-guard-validator-call.test.js test/redos-nfa.test.js test/weak-randomness.test.js test/csharp-pipeline.test.js test/csharp-cross-file.test.js test/post-quantum-crypto.test.js test/web3-advanced.test.js test/cloud-iam-k8s.test.js test/crypto-protocol.test.js test/ml-supply-chain.test.js test/mcp-audit-scan.test.js test/wrong-context-sanitizer.test.js test/sanitizer-context.test.js test/frontend-hygiene.test.js test/csv-injection.test.js test/stored-taint.test.js test/tree-sitter-sinks.test.js test/kotlin-structural.test.js test/ruby-php-structural.test.js test/java-csharp-structural.test.js test/java-structural-cross-file.test.js test/guard-recognition.test.js test/guard-window-identifier-correlation.test.js test/js-python-framework-structural.test.js test/go-structural.test.js test/secret-concat.test.js test/secret-redaction.test.js test/xss-reflected-multilang.test.js test/code-injection-multilang.test.js test/xxe-multilang.test.js test/xpath-injection-multilang.test.js test/gapfill-batch13.test.js test/agent-untrusted-flow.test.js test/api-authz.test.js test/event-entrypoint.test.js test/iac-terraform.test.js test/cross-service.test.js test/rbac-consistency.test.js test/adversarial-robustness.test.js test/secret-entropy.test.js test/comment-strip.test.js test/juliet-path-filter-gate.test.js test/java-bench-shape-opt-in.test.js test/java-ast-folding.test.js test/java-bench-extras.test.js test/reachability-missing-callgraph-data.test.js test/rate-limit.test.js test/auth-signals.test.js test/convention-deviation.test.js test/resource-exhaustion.test.js test/resource-exhaustion-realworld.test.js test/redirect-toctou.test.js test/redirect-toctou-realworld.test.js test/codegen-sink.test.js test/ownership-authz.test.js test/ownership-authz-realworld.test.js test/t21-precision-audit.test.js test/secrets-coverage.test.js test/prompt-injection-payloads.test.js test/iac-cloud-templates.test.js test/ruby-path-join.test.js test/sast/manifest-line-tracking.test.js test/rust-sast.test.js test/java-deserialization-precision.test.js test/pipeline-env-secret.test.js test/mark-used-vuln-functions.test.js",
77
88
  "test:posture": "node --test test/threat-model.test.js test/git-hardening.test.js test/privacy-framework.test.js test/material-change.test.js test/drift.test.js test/scorecard.test.js test/accuracy-scorecard.test.js test/scorecard-gate.test.js test/predeploy-gate.test.js test/release-check.test.js test/pre-push-gate.test.js test/dependency-currency.test.js test/package-contents-check.test.js test/gate-verdict-cache.test.js test/run-unit-tests.test.js test/temp-leak-guard.test.js test/release-workflow.test.js test/release-workflow-structure.test.js test/independent-population.test.js test/why-missed.test.js test/independent-scoring.test.js test/evidence-bundle.test.js test/obligation-evidence-pack.test.js test/policy-bundle.test.js test/discovery-memory.test.js test/mttr.test.js test/license-policy.test.js test/aibom.test.js test/sbom.test.js test/api-inventory.test.js test/iam-policy.test.js test/container.test.js test/container-runtime.test.js test/image-packages.test.js test/kev.test.js test/dep-confusion.test.js test/sca-deprecated.test.js test/sca-batch.test.js test/composite-risk.test.js test/epss-enrich.test.js test/sca-coverage.test.js test/gradle-deps.test.js test/sca-route-reachable.test.js test/sca-policy.test.js test/sca-verdict.test.js test/install-script.test.js test/sca-linked-findings.test.js test/packs.test.js test/flow-narration.test.js test/regression-test-gen.test.js test/deterministic-fix.test.js test/falsification.test.js test/verification-separation.test.js test/logic-claims.test.js test/attestation.test.js test/verify-attestation-cli.test.js test/comparison.test.js test/determinism-cross-machine.test.js test/fix-honesty-gate.test.js test/model-routing.test.js test/root-cause-sweep.test.js test/entrypoint-inventory.test.js test/relevance.test.js test/untrusted.test.js test/agent-hardening.test.js test/rule-synthesis.test.js test/policy-gate.test.js test/agents-memory.test.js test/cve-lookup.test.js test/cve-alert-daemon.test.js test/fix-verify-loop.test.js test/fix-verify-tests.test.js test/fix-acceptance.test.js test/exploitability-probability.test.js test/history-scan.test.js test/viral-features.test.js test/viral-v074.test.js test/state-dir.test.js test/ignore-pragma.test.js test/license-graph.test.js test/secret-live-check.test.js test/attack-taxonomy.test.js test/triage-memory.test.js test/pr-augment.test.js test/chat-batch2.test.js test/chat-batch3.test.js test/chat-batch4.test.js test/chat-batch5.test.js test/chat-batch6.test.js test/risk-scenario-disclosure.test.js test/egress-policy.test.js test/egress-policy-completeness.test.js test/egress-policy-integration.test.js test/router.test.js test/legacy-alias-redirect.test.js test/cache-economics.test.js test/coverage-report.test.js test/corpus-status.test.js test/provenance.test.js test/secret-history.test.js test/execution-proof.test.js test/fix-metrics.test.js test/corpus-enroll.test.js test/prove-findings.test.js test/corpus-match.test.js test/corpus-provenance.test.js test/learning-quorum.test.js test/llm-cache-integrity.test.js test/proof-artifact.test.js test/providers.test.js test/fleet.test.js test/autopilot.test.js test/autopilot-cli.test.js test/verifier-independence.test.js test/integrity-legacy-key.test.js test/suppression-visibility.test.js test/cost-ceiling.test.js test/local-endpoint.test.js test/ollama-provider.test.js test/ollama-capabilities.test.js test/ollama-offline-egress.test.js test/ollama-fix-proposal.test.js test/ollama-explain-proposal.test.js test/ollama-poc-proposal.test.js test/ollama-model-probe.test.js test/ollama-agent-tools.test.js test/ollama-agent-loop.test.js test/ollama-e2e.test.js test/ollama-oom-feedback.test.js test/ollama-doc-drift.test.js test/model-trust.test.js test/vuln-archaeology.test.js test/scan-checkpoint.test.js test/llm-redact.test.js test/world-class-batch2.test.js test/world-class-modules.test.js test/privacy-ir-adapter.test.js test/privacy-taxonomy.test.js test/privacy-sink-policy.test.js test/privacy-governance.test.js test/privacy-inventory.test.js test/integration-end-to-end.test.js test/streak-cli-wiring.test.js test/stack-playbook.test.js test/machine-output-flag.test.js test/stdout-flush.test.js test/format-determinism.test.js test/only-flag-channels.test.js test/confidence.test.js test/security-trend.test.js test/calibration-drift.test.js test/validator-metrics.test.js test/clustering-ir-taint-line.test.js test/concurrency-cwe.test.js test/compliance-mapping-liveness.test.js test/module-artifact-liveness.test.js test/supply-chain-provenance-completeness.test.js test/compliance-severity-threshold.test.js test/compliance-severity-policy.test.js test/compliance-evidence-binding.test.js test/compliance-evidence-signing.test.js test/compliance-file-contains.test.js test/label-isolation.test.js test/evidence-grade-wording.test.js test/llm-model-status.test.js test/egress-policy-constraints.test.js test/egress-redact.test.js test/egress-audit.test.js test/egress-approved-providers.test.js test/family-registry.test.js test/coverage-strength.test.js test/framework-provenance.test.js test/framework-provenance-controlrefs.test.js test/third-party-verification.test.js test/proof-coverage.test.js test/calibration-holdout.test.js test/independent-population-gate.test.js test/catalog-freshness.test.js test/incremental-parity.test.js test/surface-smoke.test.js test/fix-coverage.test.js test/raw-source-carveout.test.js test/mlbom-conformance.test.js test/deploy-gate-replay.test.js test/sbom-conformance.test.js test/unscored-claims.test.js test/mcp-rug-pull.test.js test/agent-boundary-taint.test.js test/confinement-adversarial.test.js test/comment-strip-cost.test.js test/reachability-claim.test.js test/entrypoint-breadth.test.js test/dep-file-admission.test.js test/custom-rules-freshness.test.js test/posture/provenance-schema.test.js test/posture/provenance-cache.test.js test/helpers/build-git-fixture.test.js test/posture/provenance-git-evidence.test.js test/posture/provenance-dag-walk.test.js test/posture/provenance-confidence.test.js test/posture/provenance-predicate-replay.test.js test/posture/provenance-origin-resolver.test.js test/posture/provenance-ai-authorship.test.js test/posture/provenance-branch-entry.test.js test/posture/provenance-evidence-attribution.test.js test/posture/provenance-lifecycle.test.js test/posture/provenance-missing-control-resolver.test.js test/posture/provenance-missing-control-wiring.test.js test/posture/provenance-coordinator.test.js test/posture/provenance-sca-origin.test.js test/posture/provenance-transitive-sca.test.js test/posture/provenance-coordinator-sca.test.js test/posture/provenance-providers.test.js test/posture/provenance-evidence-bundle.test.js test/posture/provenance-repo-lineage.test.js test/posture/provenance-secrets-logic.test.js test/cli/provenance-flags.test.js test/cli/attest-provenance.test.js test/cli/attest-obligations.test.js test/cli/models.test.js test/cli/setup-llm.test.js test/cli/fix-retry.test.js test/cli/compliance-walkthrough-lineage.test.js test/cli/dataflow-export-privacy.test.js test/cli/dataflow-export-briefing.test.js test/cli/lineage-snapshot-persist.test.js test/cli/dataflow-diff.test.js test/cli/dataflow-watch.test.js test/cli/dataflow-recipients.test.js test/cli/dataflow-coverage.test.js test/security/provenance-safety.test.js test/security/provenance-injection.test.js test/posture/remediation-ledger.test.js test/posture/assurance-baseline.test.js test/posture/assurance-contracts.test.js test/posture/assurance-config.test.js test/evidence-issuer.test.js test/load-factor.test.js test/proof-fabric/core.test.js test/proof-fabric/fix-store-runner.test.js test/proof-fabric/fixtures.test.js test/cli/proof-fabric-cli.test.js test/rule-compiler/core.test.js test/cli/rule-compiler-cli.test.js test/fleet/fleet-graph.test.js test/fleet/fleet-manifest.test.js test/fleet/fleet-cli.test.js test/artifact/safe-tar.test.js test/artifact/image-archive.test.js test/artifact/filesystem.test.js test/artifact/layer-secrets.test.js test/artifact/inventory.test.js test/artifact/vuln-correlate.test.js test/artifact/signature.test.js test/artifact/provenance-graph.test.js test/artifact/mismatch.test.js test/artifact/vex.test.js test/cli/artifact-provenance-cli.test.js",
78
89
  "test:dataflow": "node --test test/privacy-catalog.test.js test/privacy-deep-walker.test.js test/privacy-deep-e2e.test.js test/container-taint.test.js test/stored-taint-families.test.js test/py-annotation-sources.test.js test/fn-reach.test.js test/deep-taint.test.js test/calibration.test.js test/holdout-eval.test.js test/cross-lang-meta.test.js test/cross-lang-queues.test.js test/phase5-xlang.test.js test/phase5-coverage.test.js test/phase6-taint.test.js test/llm-validator-consistency.test.js test/llm-validator-default-on.test.js test/llm-validator-preset.test.js test/parser-py-cst.test.js test/chrome-probe.test.js test/parser-cs-kt.test.js test/parser-cs-annotations.test.js test/parser-cs-control-flow.test.js test/parser-kt-control-flow.test.js test/parser-js-annotations.test.js test/parser-java-annotations.test.js test/parser-java-control-flow.test.js test/parser-java-calls.test.js test/parser-go.test.js test/parser-rust.test.js test/rust-taint-flow.test.js test/parser-php-rb.test.js test/parser-php-control-flow.test.js test/interproc-k2.test.js test/proven-clean.test.js test/backward-default.test.js test/incremental-cache.test.js test/string-regex-lattice.test.js test/closure-capture.test.js test/points-to.test.js test/type-stubs.test.js test/soft-taint.test.js test/ifds.test.js test/symbolic-exec-proof.test.js test/ifds-summary-edges.test.js test/stub-aware-filter.test.js test/cross-repo.test.js test/proof-gate.test.js test/layer-recall.test.js test/java-taint-flow.test.js test/kt-taint-flow.test.js test/sanitizer-typed-flow.test.js test/sanitizer-gate-unit.test.js test/proof-safe.test.js test/collection-taint.test.js test/kcfa-context.test.js test/kcfa-callstring.test.js test/flow-parity.test.js test/callgraph-resolve.test.js test/import-reachability.test.js test/ir-stats.test.js test/parser-cpp.test.js test/parser-js-decorators.test.js test/parser-js-if-else-cfg.test.js test/cpp-integration.test.js test/engine-reconnect.test.js test/phase2-scoping.test.js test/engine-recall.test.js test/catalog-annotation-source.test.js test/catalog-cs-p1.test.js test/catalog-expanded.test.js test/builtin-summaries.test.js test/interproc-mutation-crash.test.js test/mutated-param-taint.test.js test/return-sink-check.test.js test/higher-order-inline-callback.test.js test/interproc-findings-discard.test.js test/runscan-deep-option.test.js test/summary-cache-convergence.test.js test/parser-rb-calls.test.js test/parser-rb-module-level.test.js test/balanced-call.test.js test/destructuring-taint.test.js test/computed-member-taint.test.js test/string-interpolation-taint.test.js test/dataflow-deadcode-severity.test.js test/catalog-dotted-callee-lookup.test.js test/builtin-summary-family-blind-kill.test.js test/deep-mode-annotator-pipeline.test.js test/receiver-type-and-nested-calls.test.js test/member-write-and-loop-taint.test.js test/parser-py-module-level.test.js test/parser-php-module-level.test.js test/r14b-module-level-e2e.test.js test/annotation-taint-engine.test.js test/interproc-nested-call-taint.test.js test/catalog-xpath-injection.test.js test/catalog-ldap-injection.test.js test/catalog-xxe.test.js test/catalog-response-splitting.test.js test/catalog-code-injection.test.js test/parser-rb-control-flow.test.js test/catalog-ruby-p1.test.js test/callee-receiver-taint.test.js test/catalog-command-injection-p4.test.js test/catalog-xss-p4.test.js test/catalog-path-ssrf-p3.test.js test/catalog-ai-model-provider-precision.test.js test/catalog-orm-write.test.js test/dataflow/provenance-pipeline-integration.test.js test/dataflow-progress.test.js test/scan-progress.test.js test/sard-leakage-pipeline.test.js test/sard-split-scoring.test.js test/sard-llm-isolation.test.js test/sard-mutation-adversarial.test.js test/sard-baseline-adaptive-tolerance.test.js test/sard-independent-holdout.test.js test/sard-flow-aware-scoring.test.js test/sard-macro-score-support-floor.test.js test/sard-php-split.test.js test/parser-java-nary-concat.test.js test/sard-naive-baseline.test.js test/field-taint-cross-method.test.js test/field-taint-engine-unit.test.js test/coercion-sanitizer-kill.test.js test/constant-propagation-path-sensitivity.test.js test/parser-java-assignments.test.js test/catalog-java-sard.test.js test/parser-cs-juliet-shapes.test.js test/catalog-cs-sard-p2.test.js test/sard-cwe-key-merge.test.js test/parser-php-backtick.test.js test/parser-php-include.test.js test/php-include-merge.test.js test/parser-php-array-field-taint.test.js test/parser-php-cond-assign.test.js test/parser-rust-redos.test.js test/multi-sink-taint-chain.test.js test/static-field-cross-class-call-string.test.js test/regex-guard-narrowing.test.js test/object-instance-field-taint.test.js test/param-type-inference.test.js test/smt-path-feasibility.test.js test/cross-service-taint.test.js test/dataflow-expr-taint-scaling.test.js test/evaluation/guard-dominance.test.js test/evaluation/engine-mechanisms.test.js test/rx-exec-receiver.test.js",
79
90
  "test:mcp": "node --test test/mcp.test.js test/mcp-apply-fix-multifile.test.js test/mcp-protocol-smoke.test.js test/mcp-audit.test.js test/audit-cli.test.js test/mcp-scratchpad.test.js test/mcp-offload.test.js test/sca-upgrade.test.js test/lsp-server.test.js test/mcp-dataflow-tools.test.js test/cli/governance-propose-edit.test.js test/cli/remediation-open-update.test.js test/cli/remediation-verify-reopen.test.js test/cli/dataflow-observations.test.js test/cli/federate-declare-list.test.js test/capabilities/tools.test.js",
@@ -81,8 +92,8 @@
81
92
  "test:lineage": "node --test test/lineage/schema.test.js test/lineage/ids.test.js test/lineage/protection.test.js test/lineage/classification.test.js test/lineage/validate.test.js test/lineage/json-schema-parity.test.js test/lineage/flagship-fixture.test.js test/lineage/flagship-fixture-semantics.test.js test/lineage/field-identity.test.js test/lineage/engine-expr-resolver.test.js test/lineage/engine-walker.test.js test/lineage/engine-integration.test.js test/lineage/engine-receiver-identity.test.js test/lineage/summaries.test.js test/lineage/driver.test.js test/lineage/engine-provenance.test.js test/lineage/engine-provenance-interprocedural.test.js test/lineage/path-store.test.js test/lineage/path-query.test.js test/lineage/flow-grade.test.js test/lineage/source-registry.test.js test/lineage/sink-registry.test.js test/lineage/transform-catalog.test.js test/lineage/handling-analyzer.test.js test/lineage/registry-real-code.test.js test/lineage/source-seeding.test.js test/lineage/graph-builder.test.js test/lineage/coverage.test.js test/lineage/resolve-destination.test.js test/lineage/queue-detail.test.js test/lineage/index.test.js test/lineage/obligation-mapping.test.js test/lineage/obligation-predicates.test.js test/lineage/obligation-predicates-walkthrough.test.js test/lineage/transit-protection.test.js test/lineage/at-rest-protection.test.js test/lineage/protection-summary.test.js test/lineage/ac01-multi-sink.test.js test/lineage/policy-verdict.test.js test/lineage/governance-refs.test.js test/lineage/export-privacy.test.js test/lineage/export-json.test.js test/lineage/export-csv.test.js test/lineage/decision-story.test.js test/lineage/export-briefing.test.js test/lineage/graph-snapshot.test.js test/lineage/graph-diff.test.js test/lineage/drift-policy.test.js test/lineage/recipient-profile.test.js test/lineage/recipient-registry.test.js test/lineage/recipient-wiring.test.js test/lineage/redact-graph.test.js test/lineage-scan-wiring.test.js test/lineage-artifact-write.test.js test/bench-data-lineage-runner.test.js test/bundle-frontend.test.js test/bundle-frontend-golden.test.js test/generate-html-report.test.js test/export-image.test.js test/lineage/scenario.test.js test/lineage/scenario-engine.test.js test/lineage/scenario-diff.test.js test/lineage/scenario-no-obligation-wiring.test.js test/lineage/impact-assessment.test.js test/lineage/impact-engine.test.js test/lineage/impact-no-obligation-wiring.test.js test/lineage/governance-edit.test.js test/lineage/remediation.test.js test/lineage/runtime-observation.test.js test/lineage/observation-correlation.test.js test/lineage/observation-adapters.test.js test/lineage/observation-store.test.js test/lineage/runtime-corroboration-wiring.test.js test/lineage/cross-repo-link.test.js test/lineage/federation-loader.test.js test/lineage/cross-repo-link-wiring.test.js test/lineage/runtime-assurance.test.js test/cli/runtime-twin-cli.test.js",
82
93
  "test:bench-modules": "node --test test/phase4-harness.test.js test/pipeline.test.js test/proof-corpus-lib.test.js test/proof-corpus-runner.test.js",
83
94
  "test:server": "node --test test/server/graph-loader.test.js test/server/security.test.js test/server/routes.test.js test/server/http-server.test.js test/server/cmd-explore.test.js test/server/cmd-dataflow-export.test.js test/server/static-assets.test.js test/server/dataflow-scenario-cli.test.js test/server/dataflow-impact-cli.test.js",
84
- "test:haskell": "node --test test/haskell/haskell-injection.test.js test/haskell/haskell-ir.test.js test/haskell/haskell-manifests.test.js test/haskell/haskell-parser.test.js test/haskell/haskell-remediation.test.js test/haskell/haskell-resolved-graph.test.js test/haskell/haskell-sca.test.js test/haskell/haskell-sca-severity.test.js test/haskell/haskell-web-guards.test.js test/haskell/haskell-advisory-feed.test.js test/haskell/haskell-security-rules.test.js test/haskell/haskell-taint.test.js test/haskell/haskell-boundaries.test.js test/haskell/haskell-live-feed-scan.test.js test/haskell/haskell-supply-bounds.test.js test/haskell/haskell-ir-scaling.test.js",
85
- "test:nix": "node --test test/nix/nix-build-trust.test.js test/nix/nix-eval-isolation.test.js test/nix/nix-input-inventory.test.js test/nix/nix-parser-ir.test.js test/nix/nix-remediation.test.js test/nix/nix-resolved-closure.test.js test/nix/nix-sca-patches.test.js test/nix/nix-sca-severity.test.js test/nix/nix-haskell-closure-names.test.js test/nix/nix-script-taint.test.js test/nix/nix-secrets-store.test.js test/nix/nixos-hardening.test.js test/nix/nixos-module-resolution.test.js test/nix/nix-fix-multifile.test.js test/nix/nixos-evaluator-forms.test.js test/nix/nix-advisory-feed.test.js test/nix/nix-fix-prewrite.test.js",
95
+ "test:haskell": "node --test test/haskell/haskell-models-extended.test.js test/haskell/haskell-rules-extended.test.js test/haskell/haskell-injection.test.js test/haskell/haskell-ir.test.js test/haskell/haskell-manifests.test.js test/haskell/haskell-parser.test.js test/haskell/haskell-remediation.test.js test/haskell/haskell-resolved-graph.test.js test/haskell/haskell-sca.test.js test/haskell/haskell-sca-severity.test.js test/haskell/haskell-web-guards.test.js test/haskell/haskell-advisory-feed.test.js test/haskell/haskell-security-rules.test.js test/haskell/haskell-taint.test.js test/haskell/haskell-boundaries.test.js test/haskell/haskell-live-feed-scan.test.js test/haskell/haskell-supply-bounds.test.js test/haskell/haskell-ir-scaling.test.js",
96
+ "test:nix": "node --test test/nix/nixos-hardening-extended.test.js test/nix/nix-build-trust.test.js test/nix/nix-eval-isolation.test.js test/nix/nix-input-inventory.test.js test/nix/nix-parser-ir.test.js test/nix/nix-remediation.test.js test/nix/nix-resolved-closure.test.js test/nix/nix-sca-patches.test.js test/nix/nix-sca-severity.test.js test/nix/nix-haskell-closure-names.test.js test/nix/nix-script-taint.test.js test/nix/nix-secrets-store.test.js test/nix/nixos-hardening.test.js test/nix/nixos-module-resolution.test.js test/nix/nix-fix-multifile.test.js test/nix/nixos-evaluator-forms.test.js test/nix/nix-advisory-feed.test.js test/nix/nix-fix-prewrite.test.js",
86
97
  "test:language": "node --test test/language/capability-ledger.test.js test/language/language-accuracy-regression.test.js test/language/language-aibom.test.js test/language/language-assurance.test.js test/language/language-bom.test.js test/language/language-compliance.test.js test/language/language-contracts.test.js test/language/language-corpora-integrity.test.js test/language/language-discovery.test.js test/language/language-doc-coverage.test.js test/language/language-evidence-posture.test.js test/language/language-explorer.test.js test/language/language-gap-fixes.test.js test/language/language-gap-fixes-2.test.js test/language/language-governance.test.js test/language/language-integrations.test.js test/language/language-llm-agent.test.js test/language/language-local-ai.test.js test/language/language-polyglot-bridges.test.js test/language/language-privacy-lineage.test.js test/language/language-proof-remediation.test.js test/language/language-report-formats.test.js test/language/language-secrets.test.js test/language/language-trust-boundary.test.js",
87
98
  "test:language-stress": "node --test --test-concurrency=1 test/language/language-stress-offline.test.js",
88
99
  "test:language-tools": "node --test test/haskell/haskell-web-auth.test.js test/haskell/haskell-support-gate.test.js",
@@ -137,6 +148,9 @@
137
148
  "bench:cve-replay:ci": "node ../bench/cve-replay/runner.mjs --ci",
138
149
  "bench:cve-replay:check": "node ../bench/cve-replay/runner.mjs --check-baseline",
139
150
  "bench:cve-replay:update-baseline": "node ../bench/cve-replay/runner.mjs --update-baseline",
151
+ "bench:realcode:report": "node ../bench/independent/realcode.mjs report",
152
+ "bench:realcode:check": "node ../bench/independent/realcode.mjs check --tier release",
153
+ "bench:realcode:check:quick": "node ../bench/independent/realcode.mjs check --tier quick",
140
154
  "bench:independent:gate:check": "node ../scripts/independent-population-gate.mjs",
141
155
  "bench:independent:update-gate-baseline": "node ../scripts/independent-population-gate.mjs --update-baseline",
142
156
  "bench:router-replay": "node ../bench/router-replay/runner.mjs",
@@ -163,9 +177,12 @@
163
177
  "bench:self-scan": "node ../bench/self-scan/measure.mjs",
164
178
  "bench:self-scan:check": "node ../bench/self-scan/check.mjs",
165
179
  "bench:nist-800-171-labels:check": "node ../bench/nist-800-171-labels/check.mjs",
166
- "bench:mutation:check": "node ../bench/mutation/runner.mjs",
180
+ "bench:dci-real-app": "node ../bench/dci-real-app/runner.mjs", "bench:dci-real-app:check": "node ../bench/dci-real-app/runner.mjs --check", "ee:perf-budget": "node ../scripts/engineering-excellence/perf-budget.mjs", "ee:perf-budget:check": "node ../scripts/engineering-excellence/perf-budget.mjs --check", "ee:e2e-demo": "node ../scripts/engineering-excellence/e2e-demo.mjs", "ee:e2e-demo:check": "node ../scripts/engineering-excellence/e2e-demo.mjs --check", "ee:doc-captures": "node ../scripts/engineering-excellence/doc-captures.mjs", "ee:doc-captures:check": "node ../scripts/engineering-excellence/doc-captures.mjs --check", "ee:regression-report": "node ../scripts/engineering-excellence/regression-report.mjs", "ee:regression-report:check": "node ../scripts/engineering-excellence/regression-report.mjs --check", "ee:final-report": "node ../scripts/engineering-excellence/final-report.mjs", "ee:final-report:check": "node ../scripts/engineering-excellence/final-report.mjs --check", "bench:mutation:check": "node ../bench/mutation/runner.mjs",
167
181
  "baseline:capture": "node ../scripts/baseline-capture.mjs",
168
182
  "bench:protection-verdict:check": "node ../bench/protection-verdict/runner.mjs",
183
+ "bench:independent:forensics": "node ../bench/independent/forensics.mjs",
184
+ "bench:fix-verify": "node ../bench/fix-verification/runner.mjs",
185
+ "bench:fix-verify:check": "node ../bench/fix-verification/runner.mjs --check",
169
186
  "bench:fix-correctness": "node ../bench/fix-correctness/runner.mjs",
170
187
  "bench:iac-coverage": "node ../bench/iac-coverage/runner.mjs",
171
188
  "bench:prompt-injection": "node ../bench/prompt-injection/runner.mjs",
@@ -241,7 +258,15 @@
241
258
  "test:nixos-host": "node --test test/nix/nixos-host-runtime.test.js",
242
259
  "test:language-gates": "node --test --test-concurrency=1 test/language/language-benchmark-gates.test.js",
243
260
  "test:language-slow": "node --test --test-concurrency=1 test/language/language-doc-examples-metrics.test.js test/language/language-end-to-end.test.js test/language/language-package-ci.test.js test/language/language-scan-modes.test.js",
244
- "test:chrome": "AGENTIC_SECURITY_CHROME_TESTS=1 node --test test/export-image.test.js test/server/cmd-dataflow-export.test.js"
261
+ "test:chrome": "AGENTIC_SECURITY_CHROME_TESTS=1 node --test test/export-image.test.js test/server/cmd-dataflow-export.test.js",
262
+ "ee:parse-reuse": "node ../scripts/engineering-excellence/parse-reuse-measure.mjs",
263
+ "ee:analysis-cache": "node ../scripts/engineering-excellence/analysis-cache-measure.mjs",
264
+ "ee:evidence-contracts": "node ../scripts/engineering-excellence/evidence-inventory.mjs",
265
+ "release:verify-package": "node ../scripts/verify-release-package.mjs",
266
+ "ee:completion": "node ../scripts/engineering-excellence/completion-analysis.mjs",
267
+ "ee:reproduce-timeouts": "node ../scripts/engineering-excellence/reproduce-timeouts.mjs",
268
+ "ee:provenance-measure": "node ../scripts/engineering-excellence/provenance-measure.mjs",
269
+ "ee:provenance-baseline": "node ../scripts/engineering-excellence/provenance-baseline.mjs"
245
270
  },
246
271
  "author": "Ross Young <ross@clearcapabilities.com>",
247
272
  "license": "PolyForm-Internal-Use-1.0.0",
@@ -101,7 +101,8 @@ export async function adjudicate(candidates, opts = {}) {
101
101
  origin: 'context-intelligence', questionPack: c.questionPack, witnesses: c.witnesses, witnessCount: c.witnesses.length,
102
102
  sourceSpanEvidence: c.sourceSpanEvidence, scopeIntegrity: c.scopeIntegrity, reviewStatus: c.reviewStatus,
103
103
  uncertainties: c.uncertainties, recommendedValidation: c.recommendedValidation,
104
- note: 'A model hypothesis checked for citations, not a proof. Severity comes from the confirmation tier only.',
104
+ ...(c.deterministic ? { deterministic: c.deterministic } : {}),
105
+ note: c.deterministic ? 'Derived from the code analysis and a deterministic counterexample attempt; no model produced this. Severity comes from the confirmation tier only.' : 'A model hypothesis checked for citations, not a proof. Severity comes from the confirmation tier only.',
105
106
  },
106
107
  };
107
108
  };
@@ -16,7 +16,8 @@ const BUILD = [
16
16
  { language: 'javascript/typescript', kind: 'http', frameworks: 'Express-style call registration (get/post/put/patch/delete/all, router.use, app.use)', status: 'verified', evidence: [T('build-js.test.js')], limits: 'Router mounts in another file and middleware factories are not followed (reported as router-mount-not-resolved); destructured and named imports are followed, re-exports and tsconfig path aliases are not.' },
17
17
  { language: 'python', kind: 'http', frameworks: 'decorator registration (Flask/FastAPI-style @app.route / @router.get), FastAPI Depends()/Security() guards', status: 'experimental', evidence: [T('build-python-haskell.test.js'), T('frameworks.test.js')], limits: 'Decorator guards are read from the decorator lines and Depends() guards from the signature (only dependencies named like an auth or user provider bind the principal); framework-level before_request hooks and Django URL conf are not modelled.' },
18
18
  { language: 'haskell', kind: 'http', frameworks: 'Scotty, WAI, Servant, Yesod (through the existing web model)', status: 'verified', evidence: [T('build-python-haskell.test.js'), T('frameworks.test.js')], limits: 'Static source analysis; the existing web model decides what a route is. Dynamic routes are reported unresolved.' },
19
- { language: 'java/kotlin/c#/go/php/ruby/rust', kind: 'http', frameworks: 'whatever the engine route scan recognises', status: 'unsupported', evidence: [], limits: 'No fixture proves this, so it is listed as unsupported even though some routes may resolve: Handlers are resolved only for decorator/annotation-style registration; no dedicated fixtures here.' },
19
+ { language: 'php', kind: 'http', frameworks: 'Laravel Route:: registration (the entry point only)', status: 'experimental', evidence: ['test/engineering-excellence/e4-01-dci-audit.test.js'], limits: 'Measured by the E4-01 audit on one fixture: the routes resolve, but no control or sensitive operation was extracted from the handlers.' },
20
+ { language: 'java/kotlin/c#/go/ruby/rust', kind: 'http', frameworks: 'whatever the engine route scan recognises', status: 'unsupported', evidence: [], limits: 'Measured by the E4-01 audit (docs/engineering-excellence/DCI_MATURITY.md) on one fixture per language (Spring, net/http, ASP.NET, Rails): no entry point was found, so no bundle is built.' },
20
21
  { language: 'any with a recognised surface', kind: 'webhook/queue/cron/upload/cli', frameworks: 'existing entry-point inventory', status: 'experimental', evidence: [T('build-js.test.js')], limits: 'Handler is the enclosing declaration of the surface; no framework wiring beyond that.' },
21
22
  { language: 'haskell', kind: 'compiler metadata import', frameworks: 'hie-export/1 JSON export of GHC declarations and references', status: 'experimental', evidence: [T('hie-adapter.test.js')], limits: 'Reads an export; never runs GHC or hiedb. The export is validated against the source snapshot. No export produced by a real GHC run is checked in.' },
22
23
  { language: 'any', kind: 'compiler metadata build', frameworks: 'automatic metadata generation', status: 'blocked', evidence: [], limits: 'Running a compiler on untrusted source needs a sandbox proof this build does not have (Template Haskell, custom Setup and plugins run code).' },
@@ -351,6 +351,8 @@ async function cmdReview(root, args, format) {
351
351
  maxCalls: num(flag(args, 'max-calls')) || config.review.maxCalls,
352
352
  maxWallSeconds: num(flag(args, 'max-wall-seconds')) || config.review.maxWallSeconds,
353
353
  maxTokensPerJob: config.review.maxTokensPerJob,
354
+ maxTokensPerRepo: config.review.maxTokensPerRepo,
355
+ anonymizePrompts: config.review.anonymizePrompts,
354
356
  maxRetries: config.review.maxRetries,
355
357
  jobTimeoutMs: (num(flag(args, 'job-timeout-seconds')) || 120) * 1000,
356
358
  maxCostUsd: num(flag(args, 'max-cost-usd')) ?? config.review.maxCostUsd,
@@ -22,7 +22,7 @@ export const DEFAULT_CONFIG = Object.freeze({
22
22
  maxFiles: 3000,
23
23
  semanticMetadata: { mode: 'off', haskellHieDir: null },
24
24
  context: { profile: 'standard', maxTokens: null, pruneLowValue: true, maxSymbols: 60, maxDepth: 12 },
25
- review: { enabled: false, allowRemote: false, questionPacks: ['authz-idor'], concurrency: 2, maxCalls: 100, maxWallSeconds: 900, maxCostUsd: null, maxTokensPerJob: 40000, maxRetries: 3 },
25
+ review: { enabled: false, allowRemote: false, questionPacks: ['authz-idor'], concurrency: 2, maxCalls: 100, maxWallSeconds: 900, maxCostUsd: null, maxTokensPerJob: 40000, maxRetries: 3, maxTokensPerRepo: null, anonymizePrompts: false },
26
26
  replay: { contentAddressed: true, retention: 'inherit' },
27
27
  });
28
28
 
@@ -71,6 +71,8 @@ export function normalizeConfig(raw) {
71
71
  maxCostUsd: Number.isFinite(rv.maxCostUsd) && rv.maxCostUsd >= 0 ? rv.maxCostUsd : null,
72
72
  maxTokensPerJob: clamp(rv.maxTokensPerJob, 1000, 400000, d.review.maxTokensPerJob),
73
73
  maxRetries: clamp(rv.maxRetries, 0, 3, d.review.maxRetries),
74
+ maxTokensPerRepo: Number.isFinite(rv.maxTokensPerRepo) && rv.maxTokensPerRepo >= 1000 ? Math.trunc(rv.maxTokensPerRepo) : null,
75
+ anonymizePrompts: rv.anonymizePrompts === true,
74
76
  },
75
77
  replay: { contentAddressed: rp.contentAddressed !== false, retention: typeof rp.retention === 'string' ? rp.retention : 'inherit' },
76
78
  };
@@ -139,6 +139,51 @@ function clip(s) { return s.trim().slice(0, 160); }
139
139
  * lines the FILE's lines (0-based array)
140
140
  * Returns [{ symbolId, line, category:'control'|'sensitive', kind, subkind, evidence, basis, rejectionSeen, text }]
141
141
  */
142
+ /**
143
+ * Blank the comments (and Python docstrings) of a source file, keeping every character position and newline, so line numbers do not move.
144
+ * The analysis looks for calls and comparisons in code; a comment that SAYS `ownerId: req.user.id` or `requireUser(req)` is prose, and prose is the
145
+ * easiest thing for a hostile or merely careless author to write. Strings are left alone (the principal and SQL rules already read around them).
146
+ */
147
+ export function blankComments(text, file = '') {
148
+ const src = String(text || '');
149
+ const hash = /\.(?:py|rb|sh|php|pl|r)$/i.test(file);
150
+ const dashes = /\.l?hs$/i.test(file);
151
+ const cLike = !dashes && !/\.(?:py|rb|sh|pl|r)$/i.test(file);
152
+ const out = src.split('');
153
+ const n = src.length;
154
+ let i = 0;
155
+ const blank = (a, b) => { for (let k = a; k < b && k < n; k++) if (out[k] !== '\n') out[k] = ' '; };
156
+ while (i < n) {
157
+ const c = src[i]; const d = src[i + 1];
158
+ if (c === '"' || c === "'" || c === '`') {
159
+ if (/\.py$/i.test(file) && src.startsWith(c.repeat(3), i)) {
160
+ const end = src.indexOf(c.repeat(3), i + 3); const stop = end < 0 ? n : end + 3;
161
+ blank(i, stop); i = stop; continue; // a docstring or triple-quoted block is prose
162
+ }
163
+ let j = i + 1;
164
+ while (j < n && src[j] !== c && !(src[j] === '\n' && c !== '`')) { if (src[j] === '\\') j++; j++; }
165
+ i = j + 1; continue;
166
+ }
167
+ if (cLike && c === '/' && d === '*') { const end = src.indexOf('*/', i + 2); const stop = end < 0 ? n : end + 2; blank(i, stop); i = stop; continue; }
168
+ if (cLike && c === '/' && d === '/' && (i === 0 || /[\s;,)}{\]]/.test(src[i - 1]))) { let j = src.indexOf('\n', i); if (j < 0) j = n; blank(i, j); i = j; continue; }
169
+ if (hash && c === '#' && !(file.endsWith('.php') && d === '[')) { let j = src.indexOf('\n', i); if (j < 0) j = n; blank(i, j); i = j; continue; }
170
+ if (dashes && c === '-' && d === '-' && !/[!#$%&*+./<=>?@\\^|~:]/.test(src[i + 2] || ' ')) { let j = src.indexOf('\n', i); if (j < 0) j = n; blank(i, j); i = j; continue; }
171
+ if (dashes && c === '{' && d === '-') { const end = src.indexOf('-}', i + 2); const stop = end < 0 ? n : end + 2; blank(i, stop); i = stop; continue; }
172
+ i++;
173
+ }
174
+ return out.join('');
175
+ }
176
+
177
+ function bodyAfterSignature(raw) {
178
+ const arrow = raw.indexOf('=>');
179
+ let rest = null;
180
+ if (arrow >= 0) rest = raw.slice(arrow + 2);
181
+ else { const m = /\)\s*\{(.*)$/.exec(raw); if (m) rest = m[1]; }
182
+ if (rest === null) return '';
183
+ const brace = /^\s*\{(.*)$/.exec(rest);
184
+ return brace ? brace[1] : rest;
185
+ }
186
+
142
187
  export function analyzeSymbolText(symbol, lines, { haskell = false } = {}) {
143
188
  const out = [];
144
189
  const seen = new Set();
@@ -171,7 +216,10 @@ export function analyzeSymbolText(symbol, lines, { haskell = false } = {}) {
171
216
  const calls = [];
172
217
  const re = /([A-Za-z_$][\w$]*(?:(?:\.|::)[A-Za-z_$][\w$]*)*)\s*\(/g;
173
218
  let m;
174
- if (!isDeclLine) { while ((m = re.exec(raw))) calls.push(m[1]); }
219
+ // A one-line handler (`app.get('/x', guard, async (req, res) => { res.json(await db.docs.findOne({ id })); })`) is its own declaration
220
+ // line, so skipping the whole line also skipped its body. Only the SIGNATURE is skipped: the calls after the arrow or the opening brace count.
221
+ const scanText = isDeclLine ? bodyAfterSignature(raw) : raw;
222
+ while ((m = re.exec(scanText))) calls.push(m[1]);
175
223
  if (haskell && !isDeclLine) {
176
224
  const hre = /\b([A-Z][\w.]*\.[a-z][\w']*|[a-z][\w']*)\b/g;
177
225
  while ((m = hre.exec(raw))) if (AUTH_NAME.test(m[1]) || HS_SENSITIVE.test(m[1])) calls.push(m[1]);
@@ -0,0 +1,200 @@
1
+ // Deterministic counterexample validation for a candidate invariant violation (E4-04).
2
+ //
3
+ // A candidate (for example a cross-route inconsistency from E4-03) says "this route looks weaker than its sibling". This module tries to settle it
4
+ // WITHOUT a model, in layers, and reports where it got to as one of four states that are never blended:
5
+ //
6
+ // refuted the claim is contradicted: the control IS on the path, the route is declared public by policy, there is no sensitive operation
7
+ // on the resource, or an executed attempt by the attacker was denied
8
+ // unresolved the analysis cannot say: an unresolved call or a traversal limit could hide the control, or the fixture could not run
9
+ // plausible every edge is resolved and the path reaches the resource's sensitive operation with no control of that kind before it, but nothing
10
+ // was executed. This is static evidence only
11
+ // proven an authorized LOCAL request fixture ran the real handler code and the attacker, who does not own the object, read or changed the
12
+ // victim's object. Only an execution can produce this state
13
+ //
14
+ // MODEL OUTPUT NEVER ENTERS. This file imports nothing from the review or model paths and reads no prose: facts come from the code analysis, which
15
+ // skips comments, docstrings and string contents, so a comment that claims a check exists, or tells a reviewer to ignore the finding, cannot move a
16
+ // state. The evidence trace is a list of steps each naming its kind (`static` or `executed`), so a reader can see which layer decided.
17
+ //
18
+ // THE FIXTURE RUNNER executes handler code, so it is confined: a child process under Node's permission model with NO file access (the fixture's sources are loaded from memory), no
19
+ // child processes and no workers, a driver that removes `fetch` and refuses every builtin and package, a scrubbed environment, a wall-clock
20
+ // limit and capped output. Network is not part of Node's permission model, so it is blocked by the driver, not by the runtime: lower assurance. Express-style
21
+ // apps are supported through a small in-process shim for `express`, and `db` is a recording in-memory store the fixture supplies. Code that needs
22
+ // anything else (a real database, another module system, a missing dependency) ends as `unresolved`, never as `proven`.
23
+ import { spawnSync } from 'node:child_process';
24
+ import * as path from 'node:path';
25
+
26
+ export const STATES = Object.freeze(['proven', 'plausible', 'refuted', 'unresolved']);
27
+ const FIXTURE_TIMEOUT_MS = 8000;
28
+ const MAX_OUTPUT = 200_000;
29
+ const MAX_FIXTURE_BYTES = 100_000;
30
+
31
+ // ---- the fixture runner -----------------------------------------------------------------------------------------------------
32
+
33
+ const DRIVER = String.raw`
34
+ 'use strict';
35
+ const path = require('node:path');
36
+ const spec = JSON.parse(process.env.FIXTURE_SPEC);
37
+ const ops = [];
38
+ const store = JSON.parse(JSON.stringify(spec.store || {}));
39
+ const match = (doc, q) => Object.entries(q || {}).every(([k, v]) => (v && typeof v === 'object' && !Array.isArray(v)) ? true : doc[k] === v);
40
+ const coll = (name) => ({
41
+ async findOne(q) { ops.push({ op: 'findOne', c: name, q }); return (store[name] || []).find((d) => match(d, q)) || null; },
42
+ async find(q) { ops.push({ op: 'find', c: name, q }); return (store[name] || []).filter((d) => match(d, q)); },
43
+ async updateOne(q, u) { ops.push({ op: 'updateOne', c: name, q }); const d = (store[name] || []).find((x) => match(x, q)); if (d) Object.assign(d, (u && u.$set) || u); return { matchedCount: d ? 1 : 0 }; },
44
+ async deleteOne(q) { ops.push({ op: 'deleteOne', c: name, q }); const i = (store[name] || []).findIndex((x) => match(x, q)); if (i >= 0) store[name].splice(i, 1); return { deletedCount: i >= 0 ? 1 : 0 }; },
45
+ async insertOne(d) { ops.push({ op: 'insertOne', c: name }); (store[name] ||= []).push(d); return { insertedId: d.id }; },
46
+ });
47
+ global.db = new Proxy({}, { get: (_, name) => coll(String(name)) });
48
+ const routes = []; const mw = [];
49
+ const app = {};
50
+ for (const m of ['get', 'post', 'put', 'patch', 'delete']) app[m] = (p, ...hs) => { routes.push({ method: m.toUpperCase(), path: p, handlers: hs.flat() }); return app; };
51
+ app.use = (...a) => { const fn = a.find((x) => typeof x === 'function'); if (fn) mw.push(fn); return app; };
52
+ app.listen = () => app; app.set = () => app; app.disable = () => app;
53
+ const express = () => app; express.json = () => (q, s, n) => n(); express.urlencoded = () => (q, s, n) => n(); express.Router = () => app;
54
+ // The fixture's files are loaded from memory: nothing is read from disk, so the process needs no file permission at all, and require can only
55
+ // reach the shim for express and the fixture's own relative modules. Everything else, builtins included, is refused.
56
+ delete globalThis.fetch; delete globalThis.WebSocket;
57
+ const vm = require('node:vm');
58
+ const cache = new Map();
59
+ const norm = (p) => path.posix.normalize(p).replace(/^\.\//, '');
60
+ const fileFor = (from, request) => {
61
+ const base = path.posix.join(path.posix.dirname(from), request);
62
+ for (const c of [base, base + '.js', base + '.cjs', base + '/index.js']) if (Object.hasOwn(spec.files, norm(c))) return norm(c);
63
+ return null;
64
+ };
65
+ const load = (file) => {
66
+ if (cache.has(file)) return cache.get(file).exports;
67
+ const mod = { exports: {} }; cache.set(file, mod);
68
+ const req = (request) => {
69
+ if (request === 'express') return express;
70
+ if (request.startsWith('.')) { const f = fileFor(file, request); if (f) return load(f); throw Object.assign(new Error('no such fixture module ' + request), { code: 'FIXTURE_UNSUPPORTED' }); }
71
+ throw Object.assign(new Error('fixture runner does not provide module ' + request), { code: 'FIXTURE_UNSUPPORTED' });
72
+ };
73
+ const wrapper = '(function (exports, require, module, __filename, __dirname) {' + spec.files[file] + '\n})';
74
+ vm.runInThisContext(wrapper, { filename: file })(mod.exports, req, mod, file, path.posix.dirname(file));
75
+ return mod.exports;
76
+ };
77
+ const matchRoute = (r, method, url) => {
78
+ if (r.method !== method) return null;
79
+ const a = r.path.split('/'); const b = url.split('/');
80
+ if (a.length !== b.length) return null;
81
+ const params = {};
82
+ for (let i = 0; i < a.length; i++) { if (a[i].startsWith(':')) params[a[i].slice(1)] = b[i]; else if (a[i] !== b[i]) return null; }
83
+ return params;
84
+ };
85
+ (async () => {
86
+ let result;
87
+ try {
88
+ load(norm(spec.entry));
89
+ const req0 = spec.request;
90
+ const hit = routes.map((r) => ({ r, params: matchRoute(r, req0.method, req0.path) })).find((x) => x.params);
91
+ if (!hit) { result = { error: 'no-route', detail: req0.method + ' ' + req0.path }; }
92
+ else {
93
+ const user = spec.user ? JSON.parse(JSON.stringify(spec.user)) : undefined;
94
+ const req = { method: req0.method, params: hit.params, query: req0.query || {}, body: req0.body || {}, headers: {}, user, get: () => undefined };
95
+ let done; const finished = new Promise((r) => { done = r; });
96
+ const res = { statusCode: 200, body: undefined, sent: false,
97
+ status(c) { this.statusCode = c; return this; }, json(b) { this.body = b; this.sent = true; done(); return this; }, send(b) { this.body = b; this.sent = true; done(); return this; },
98
+ sendStatus(c) { this.statusCode = c; this.sent = true; done(); return this; }, set() { return this; }, end() { this.sent = true; done(); return this; }, type() { return this; }, locals: {} };
99
+ const chain = [...mw, ...hit.r.handlers];
100
+ let i = 0;
101
+ const next = (err) => { if (err) { res.statusCode = 500; res.sent = true; done(); return; } const h = chain[i++]; if (!h) { done(); return; } try { const p = h(req, res, next); if (p && typeof p.then === 'function') p.catch((e) => { res.statusCode = 500; res.body = String(e && e.message); res.sent = true; done(); }); } catch (e) { res.statusCode = 500; res.body = String(e && e.message); res.sent = true; done(); } };
102
+ next();
103
+ await Promise.race([finished, new Promise((r) => setTimeout(r, 2000))]);
104
+ result = { status: res.statusCode, body: res.body, sent: res.sent, ops, store };
105
+ }
106
+ } catch (e) { result = { error: e && e.code === 'FIXTURE_UNSUPPORTED' ? 'unsupported' : 'load-failed', detail: String(e && e.message).slice(0, 300) }; }
107
+ process.stdout.write('@@RESULT@@' + JSON.stringify(result));
108
+ })();
109
+ `;
110
+
111
+ /**
112
+ * Run one request against the real handler code under confinement.
113
+ * @param {{files:Record<string,string>, entry:string, request:{method:string,path:string,body?:object,query?:object}, user?:object, store?:object}} f
114
+ * @returns {{ok:boolean, status?:number, body?:any, ops?:object[], store?:object, error?:string, detail?:string}}
115
+ */
116
+ export function runFixture(f) {
117
+ const total = Object.values(f.files || {}).reduce((n, t) => n + String(t).length, 0);
118
+ if (total > MAX_FIXTURE_BYTES) return { ok: false, error: 'too-large', detail: `${total} bytes of fixture source` };
119
+ for (const rel of Object.keys(f.files || {})) if (path.isAbsolute(rel) || rel.split('/').includes('..')) return { ok: false, error: 'bad-path', detail: rel };
120
+ // `--permission` with no allow flags: no file reads or writes, no child processes, no workers. The driver comes in through -e and the fixture's
121
+ // files through the environment, so nothing needs the disk. Network is not covered by the permission model; the driver removes `fetch` and
122
+ // refuses every builtin and package, which is the whole of its network reach.
123
+ const r = spawnSync(process.execPath, ['--permission', '-e', DRIVER], {
124
+ encoding: 'utf8', timeout: FIXTURE_TIMEOUT_MS, maxBuffer: MAX_OUTPUT,
125
+ env: { PATH: '/usr/bin:/bin', FIXTURE_SPEC: JSON.stringify({ files: f.files, entry: f.entry, request: f.request, user: f.user, store: f.store }) },
126
+ });
127
+ if (r.error) return { ok: false, error: r.error.code === 'ETIMEDOUT' ? 'timeout' : 'spawn-failed', detail: String(r.error.message).slice(0, 200) };
128
+ const out = String(r.stdout || ''); const i = out.indexOf('@@RESULT@@');
129
+ if (i < 0) return { ok: false, error: 'no-result', detail: String(r.stderr || '').slice(0, 300) };
130
+ let parsed; try { parsed = JSON.parse(out.slice(i + 10)); } catch { return { ok: false, error: 'bad-result' }; }
131
+ return parsed.error ? { ok: false, error: parsed.error, detail: parsed.detail } : { ok: true, ...parsed };
132
+ }
133
+
134
+ /**
135
+ * Make the attacker's request against the real handler code and say what happened to the victim's object. Used by assessCandidate and, after a patch,
136
+ * by the final verification of a fix (which must execute even when a static look already says the control is present).
137
+ * @returns {{state:'proven'|'refuted'|'unresolved', trace:object[], reasons:string[], reason?:string, status?:number}}
138
+ */
139
+ export function executeAttempt(candidate, fx) {
140
+ const trace = [];
141
+ const method = fx.method || (candidate.operations?.includes('delete') ? 'DELETE' : candidate.operations?.includes('update') ? 'PUT' : 'GET');
142
+ const attack = runFixture({ files: fx.files, entry: fx.entry, request: { method, path: fx.path, body: fx.body }, user: fx.attacker.user, store: fx.store });
143
+ if (!attack.ok) { trace.push(step('executed', 'attacker request', `${attack.error}: ${attack.detail || ''}`)); return { state: 'unresolved', trace, reasons: [`the fixture could not run (${attack.error}); the claim stays unproven`], reason: `the fixture could not run (${attack.error}); the claim stays unproven` }; }
144
+ trace.push(step('executed', 'attacker request', `${method} ${fx.path} as ${JSON.stringify(fx.attacker.user)} -> ${attack.status}`));
145
+ const marker = fx.victim.marker;
146
+ const leaked = marker ? JSON.stringify(attack.body ?? '').includes(marker) : attack.status >= 200 && attack.status < 300 && attack.body != null;
147
+ const changed = JSON.stringify(attack.store?.[fx.victim.collection] || []) !== JSON.stringify(fx.store[fx.victim.collection] || []);
148
+ if (leaked || changed) {
149
+ trace.push(step('executed', 'effect on the victim\'s object', leaked ? 'the attacker received the victim\'s data' : 'the victim\'s object was modified by the attacker'));
150
+ if (fx.siblingPath) {
151
+ const sib = runFixture({ files: fx.files, entry: fx.entry, request: { method: fx.siblingMethod || 'GET', path: fx.siblingPath }, user: fx.attacker.user, store: fx.store });
152
+ if (sib.ok) trace.push(step('executed', 'the enforcing sibling, same attacker', `${fx.siblingMethod || 'GET'} ${fx.siblingPath} -> ${sib.status}${marker && !JSON.stringify(sib.body ?? '').includes(marker) ? ' (victim data withheld)' : ''}`));
153
+ }
154
+ return { state: 'proven', trace, reasons: ['an executed local request let a principal who does not own the object ' + (leaked ? 'read' : 'change') + ' it'], status: attack.status };
155
+ }
156
+ trace.push(step('executed', 'effect on the victim\'s object', 'none: the attacker was denied or got nothing'));
157
+ return { state: 'refuted', trace, reasons: [`an executed attempt by the attacker was denied (status ${attack.status})`], status: attack.status };
158
+ }
159
+
160
+ // ---- the assessment ---------------------------------------------------------------------------------------------------------
161
+
162
+ const step = (kind, what, detail = null) => ({ kind, what, ...(detail ? { detail } : {}) });
163
+ const sameBundle = (b, route) => b.entrypoint && b.entrypoint.label === route;
164
+
165
+ /**
166
+ * @param {{route:string, resource:string, dimension:string, operations?:string[], enforcedAt?:object[], waivedBy?:string[]}} candidate e.g. a finding from findCrossRouteInconsistencies
167
+ * @param {{bundles:object[], fixture?:{files:Record<string,string>, entry:string, victim:{user:object, ownsId:string, collection:string, marker?:string}, attacker:{user:object}, store:object, path:string, method?:string, body?:object, siblingPath?:string, siblingMethod?:string}}} ctx
168
+ * @returns {{state:'proven'|'plausible'|'refuted'|'unresolved', trace:object[], reasons:string[]}}
169
+ */
170
+ export function assessCandidate(candidate, ctx) {
171
+ const trace = [];
172
+ const fail = (state, reason) => ({ state, trace, reasons: [reason] });
173
+ const bundle = (ctx.bundles || []).find((b) => sameBundle(b, candidate.route));
174
+ if (!bundle || !bundle.manifest) { trace.push(step('static', 'locate the route bundle', 'no bundle for this route')); return fail('unresolved', `no analysed bundle for ${candidate.route}`); }
175
+ trace.push(step('static', 'locate the route bundle', bundle.entrypoint.id));
176
+
177
+ if (candidate.waivedBy && candidate.waivedBy.length) { trace.push(step('static', 'check policy', `public-by-design: ${candidate.waivedBy.join(', ')}`)); return fail('refuted', `declared public by ${candidate.waivedBy.join(', ')}`); }
178
+
179
+ const facts = bundle.reach?.facts || [];
180
+ const sens = facts.filter((f) => f.category === 'sensitive');
181
+ if (!sens.length) { trace.push(step('static', 'find a sensitive operation', 'none on the path')); return fail('refuted', 'no sensitive operation is reachable from this route, so there is nothing to protect'); }
182
+ const first = Math.min(...sens.map((f) => f.effLine));
183
+ const kinds = candidate.dimension === 'ownership' ? ['ownership'] : [candidate.dimension];
184
+ const before = facts.filter((f) => f.category === 'control' && kinds.includes(f.kind) && (f.effLine < first || (f.basis === 'query-filter' && f.effLine <= first)));
185
+ if (before.length) { trace.push(step('static', `look for ${candidate.dimension} before the first sensitive operation`, `found at ${before[0].file}:${before[0].line}`)); return fail('refuted', `${candidate.dimension} is enforced at ${before[0].file}:${before[0].line} before the sensitive operation`); }
186
+ trace.push(step('static', `look for ${candidate.dimension} before the first sensitive operation`, 'none'));
187
+
188
+ const hidden = (bundle.manifest.unknowns || []).some((u) => u.material) || bundle.reach?.capped;
189
+ if (hidden) { trace.push(step('static', 'check for unresolved calls', 'a material unresolved call or a traversal limit')); return fail('unresolved', 'an unresolved call or a traversal limit could hide the control'); }
190
+ trace.push(step('static', 'check for unresolved calls', 'none'));
191
+
192
+ const fx = ctx.fixture;
193
+ if (!fx) return { state: 'plausible', trace, reasons: ['every edge on the path is resolved and no control precedes the sensitive operation; nothing was executed'] };
194
+
195
+ const ex = executeAttempt(candidate, fx);
196
+ trace.push(...ex.trace);
197
+ if (ex.state === 'unresolved') return fail('unresolved', ex.reason);
198
+ if (ex.state === 'proven') return { state: 'proven', trace, reasons: ex.reasons };
199
+ return { state: 'refuted', trace, reasons: ex.reasons };
200
+ }