@clear-capabilities/agentic-security-scanner 0.183.1 → 0.185.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.
- package/CHANGELOG.md +29 -0
- package/bin/agentic-security.js +88 -0
- package/dist/{2a8456e0800aeee871b6.json → 0b301d45b231f144a1b4.json} +27 -9
- package/dist/1128.index.js +908 -0
- package/dist/1336.index.js +261 -112
- package/dist/1665.index.js +828 -0
- package/dist/2923.index.js +17 -9
- package/dist/9382.index.js +23 -2
- package/dist/9579.index.js +11 -4
- package/dist/agentic-security.mjs +15 -15
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/dist/frontend/src/shell.js +12 -2
- package/package.json +27 -9
- package/src/context-intelligence/controls.js +15 -0
- package/src/context-intelligence/reachability.js +8 -2
- package/src/dataflow/CLAUDE.md +43 -1
- package/src/dataflow/backward.js +42 -7
- package/src/dataflow/cross-service-taint.js +83 -1
- package/src/dataflow/demand-query.js +929 -0
- package/src/dataflow/dep-fingerprint.js +718 -0
- package/src/dataflow/engine.js +48 -6
- package/src/dataflow/ifds-precise.js +22 -0
- package/src/dataflow/incremental-replay.js +118 -0
- package/src/dataflow/incremental-session.js +257 -0
- package/src/dataflow/incremental.js +237 -35
- package/src/dataflow/index.js +25 -94
- package/src/dataflow/summaries.js +72 -6
- package/src/dataflow/tabulation.js +80 -24
- package/src/discovery/hunter.js +6 -2
- package/src/discovery/index.js +5 -2
- package/src/engine.js +63 -3
- package/src/graph/CLAUDE.md +31 -0
- package/src/graph/adapters/artifact.js +81 -0
- package/src/graph/adapters/crossrepo.js +75 -0
- package/src/graph/adapters/dataflow.js +76 -0
- package/src/graph/adapters/provenance.js +92 -0
- package/src/graph/adapters/semantic.js +89 -0
- package/src/graph/crosswalk-builders.js +152 -0
- package/src/graph/crosswalk.js +146 -0
- package/src/graph/index.js +15 -0
- package/src/graph/observation.js +57 -0
- package/src/graph/refs.js +105 -0
- package/src/graph/registry.js +129 -0
- package/src/graph/relations.js +81 -0
- package/src/graph/scc.js +241 -0
- package/src/graph/view.js +254 -0
- package/src/language/haskell-disclosure.js +13 -1
- package/src/lineage/CLAUDE.md +71 -8
- package/src/lineage/DESIGN_GRAPH_BUILDER.md +1 -1
- package/src/lineage/DESIGN_PATH_PROVENANCE.md +6 -0
- package/src/lineage/boundary-contract.js +273 -0
- package/src/lineage/completion.js +205 -0
- package/src/lineage/continuation.js +140 -0
- package/src/lineage/control-credit.js +313 -0
- package/src/lineage/correlation.js +199 -0
- package/src/lineage/coverage.js +8 -1
- package/src/lineage/cross-repo-link.js +22 -0
- package/src/lineage/cut-planner.js +548 -0
- package/src/lineage/driver.js +219 -66
- package/src/lineage/engine.js +166 -21
- package/src/lineage/export-json.js +5 -0
- package/src/lineage/graph-builder.js +84 -7
- package/src/lineage/haskell-view.js +59 -0
- package/src/lineage/index.js +3 -0
- package/src/lineage/nix-view.js +35 -0
- package/src/lineage/observation-adapters.js +17 -9
- package/src/lineage/owned-build.js +77 -0
- package/src/lineage/owned-worker-entry.js +22 -0
- package/src/lineage/owned-worker.js +95 -0
- package/src/lineage/path-evidence.js +123 -0
- package/src/lineage/path-predicates.js +529 -0
- package/src/lineage/path-query.js +189 -20
- package/src/lineage/path-store.js +191 -17
- package/src/lineage/scc-solver.js +186 -0
- package/src/lineage/smt-orchestrator.js +138 -0
- package/src/lineage/source-seeding.js +36 -2
- package/src/lineage/summaries.js +66 -4
- package/src/lineage/value-versions.js +130 -0
- package/src/lineage/witness-selection.js +95 -0
- package/src/pipeline/scan-health.js +19 -0
- package/src/posture/CLAUDE.md +13 -0
- package/src/posture/evidence-bundle.js +1 -1
- package/src/posture/witness-bundle.js +573 -0
- package/src/posture/witness-runtime.js +276 -0
- package/src/report/index.js +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
9fca68c766f59a0b495833e06c29161ea87667d331bd80f5c2a8767e81e44f10 agentic-security.mjs
|
|
@@ -146,8 +146,18 @@ function buildHeader(graph) {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
function buildCoverageBanner(graph) {
|
|
149
|
-
|
|
150
|
-
|
|
149
|
+
// DAG-07 R07.2: an analysis that stopped early (iteration budget, cancel,
|
|
150
|
+
// construction or seeding limit) is stated outright, and stays visible when
|
|
151
|
+
// zero flows were projected, since an empty view is where it is easiest to
|
|
152
|
+
// misread the result as "nothing flows".
|
|
153
|
+
const ac = graph.coverage?.analysisCompletion ?? graph.scanHealth?.analysisCompletion ?? null;
|
|
154
|
+
const analysisStopped = !!ac && ac.status && ac.status !== 'complete';
|
|
155
|
+
const status = analysisStopped ? ac.status : (graph.coverage?.status ?? graph.scanHealth?.status);
|
|
156
|
+
const zeroFlows = Array.isArray(graph.flows) && graph.flows.length === 0;
|
|
157
|
+
const text = analysisStopped
|
|
158
|
+
? `Analysis ${ac.status}${zeroFlows ? ' (no flows shown)' : ''} — absence of a flow here is not evidence that none exists`
|
|
159
|
+
: `Coverage: ${status ?? 'unknown'} — not a complete assessment`;
|
|
160
|
+
const banner = el('div', { class: 'shell__coverage-banner' }, text);
|
|
151
161
|
if (status && status !== 'complete') banner.setAttribute('data-visible', 'true');
|
|
152
162
|
return banner;
|
|
153
163
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clear-capabilities/agentic-security-scanner",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.185.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",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"node": ">=24.0.0"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@babel/core": "^8.0.
|
|
43
|
+
"@babel/core": "^8.0.9",
|
|
44
44
|
"@babel/preset-react": "^8.0.1",
|
|
45
45
|
"@babel/preset-typescript": "^8.0.1",
|
|
46
46
|
"js-yaml": "^5.5.0",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"optionalDependencies": {
|
|
50
50
|
"tree-sitter-wasms": "0.1.13",
|
|
51
51
|
"web-tree-sitter": "0.20.8",
|
|
52
|
-
"z3-solver": "^5.3.
|
|
52
|
+
"z3-solver": "^5.3.2"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/node": "^26.6.5",
|
|
@@ -81,19 +81,20 @@
|
|
|
81
81
|
"test:loop-real-prd": "node --test ../scripts/loop-engineering/test/loop-real-prd.test.js",
|
|
82
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",
|
|
83
83
|
"test:python": "node ../scripts/run-python-tests.mjs",
|
|
84
|
+
"bench:dag-incremental": "node ../bench/dag-incremental/run.mjs",
|
|
84
85
|
"test:smoke": "node --test test/smoke.test.js test/demo-app.test.js",
|
|
85
86
|
"test:ollama-e2e": "AGENTIC_SECURITY_OLLAMA_E2E=1 node --test test/ollama-e2e.test.js",
|
|
86
87
|
"test:glob": "node --test test/glob-compat.test.js",
|
|
87
88
|
"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",
|
|
88
|
-
"test:posture": "node --test test/contracts/root-cause-sweep.contract.test.js test/contracts/blast-radius.contract.test.js test/contracts/federation.contract.test.js test/contracts/eval-lab-report.contract.test.js test/contracts/fleet.contract.test.js test/contracts/rule-compiler.contract.test.js test/contracts/release-assurance.contract.test.js test/contracts/dnr.contract.test.js test/contracts/strategic-metrics.contract.test.js test/contracts/exploit-proof.contract.test.js test/contracts/artifact-provenance.contract.test.js test/dnr/artifact-join.test.js test/rule-pack-signing.test.js 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/fleet/job-store.test.js test/fleet/enterprise-graph.test.js test/fleet/discover-edges.test.js test/fleet/code-boundaries.test.js test/fleet/job-runner.test.js test/fleet/fleet-org-cli.test.js test/eval-lab/dataset-neutralize.test.js test/eval-lab/arms-score-stats.test.js test/eval-lab/run-report.test.js test/eval-lab/router.test.js test/eval-lab/arm-ollama.test.js test/eval-lab/import-independent.test.js test/cli/eval-lab-cli.test.js test/dnr/ir-and-outputs.test.js test/dnr/logs-and-hunt.test.js test/dnr/window-store-view.test.js test/dnr/exploit-correlation.test.js test/cli/dnr-cli.test.js test/proof-fabric/core.test.js test/proof-fabric/container.test.js test/proof-fabric/generate.test.js test/proof-fabric/siblings.test.js test/proof-fabric/generate-python.test.js test/cli/proof-lifecycle-demo.test.js test/mcp-proof.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/rule-compiler/synthesis.test.js test/rule-compiler/structure.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/artifact/registry.test.js test/artifact/sources-cosign-evidence.test.js test/cli/artifact-sources-cli.test.js test/cli/artifact-provenance-cli.test.js",
|
|
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",
|
|
89
|
+
"test:posture": "node --test test/contracts/root-cause-sweep.contract.test.js test/contracts/model-validation.contract.test.js test/contracts/agentic-discovery.contract.test.js test/contracts/local-models.contract.test.js test/contracts/dependency-finding.contract.test.js test/contracts/taint-flow.contract.test.js test/contracts/runtime-corroboration.contract.test.js test/compliance-coverage.test.js test/contracts/blast-radius.contract.test.js test/contracts/federation.contract.test.js test/contracts/eval-lab-report.contract.test.js test/contracts/fleet.contract.test.js test/contracts/rule-compiler.contract.test.js test/contracts/release-assurance.contract.test.js test/contracts/dnr.contract.test.js test/contracts/strategic-metrics.contract.test.js test/contracts/exploit-proof.contract.test.js test/contracts/artifact-provenance.contract.test.js test/dnr/artifact-join.test.js test/rule-pack-signing.test.js 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/fleet/job-store.test.js test/fleet/enterprise-graph.test.js test/fleet/discover-edges.test.js test/fleet/code-boundaries.test.js test/fleet/job-runner.test.js test/fleet/fleet-org-cli.test.js test/eval-lab/dataset-neutralize.test.js test/eval-lab/arms-score-stats.test.js test/eval-lab/run-report.test.js test/eval-lab/router.test.js test/eval-lab/arm-ollama.test.js test/eval-lab/import-independent.test.js test/cli/eval-lab-cli.test.js test/dnr/ir-and-outputs.test.js test/dnr/logs-and-hunt.test.js test/dnr/window-store-view.test.js test/dnr/exploit-correlation.test.js test/cli/dnr-cli.test.js test/proof-fabric/core.test.js test/proof-fabric/container.test.js test/proof-fabric/generate.test.js test/proof-fabric/siblings.test.js test/proof-fabric/generate-python.test.js test/cli/proof-lifecycle-demo.test.js test/mcp-proof.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/rule-compiler/synthesis.test.js test/rule-compiler/structure.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/artifact/registry.test.js test/artifact/sources-cosign-evidence.test.js test/cli/artifact-sources-cli.test.js test/cli/artifact-provenance-cli.test.js test/witness-bundle.test.js",
|
|
90
|
+
"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 test/incremental-dependency.test.js test/incremental-integrity.test.js test/demand-query.test.js",
|
|
90
91
|
"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",
|
|
91
92
|
"test:report": "node --test test/report-scan-invariants.test.js test/junit.test.js test/ci.test.js test/poc-generator.test.js test/verifier.test.js test/verifier-target.test.js test/annotator-errors.test.js test/scan-health.test.js test/finding-schema.test.js test/pipeline/finding-schema-provenance.test.js test/evidence-provenance.test.js test/report/provenance-output.test.js test/report/provenance-format-parity.test.js test/legacy-compat.test.js test/annotator-runner.test.js test/detector-runner.test.js test/detector-errors.test.js test/analyzer-supervisor.test.js test/cascade-worker-pool.test.js test/cascade-pool-wiring.test.js test/coverage-ledger.test.js test/coverage-ledger-completeness.test.js test/assurance-mode.test.js test/artifact-registry.test.js test/artifact-registry-completeness.test.js test/retention-policy.test.js test/state-lifecycle-report.test.js test/legal-hold.test.js test/production-feedback.test.js test/calibration-feedback.test.js test/encryption-provider.test.js test/grader-calibration.test.js test/pr-delta-gate.test.js test/vex.test.js test/report-render.test.js test/oscal-conformance.test.js test/cli-fix-apply.test.js test/apply-fix-service.test.js test/high-impact-approval-gate.test.js test/approver-registry.test.js test/suppression-exceptions.test.js test/fix-history.test.js test/producer-registry.test.js test/producer-collector.test.js test/enrichment-completion.test.js",
|
|
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/lineage/runtime-edge-states.test.js test/lineage/runtime-explorer-view.test.js test/cli/runtime-explorer-cli.test.js test/cli/runtime-identity-cli.test.js test/cli/runtime-twin-cli.test.js",
|
|
93
|
+
"test:lineage": "node --test test/lineage/analysis-completion.test.js 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/lineage/runtime-edge-states.test.js test/lineage/runtime-explorer-view.test.js test/cli/runtime-explorer-cli.test.js test/cli/runtime-identity-cli.test.js test/cli/runtime-twin-cli.test.js test/lineage/cut-planner.test.js test/lineage/scc.test.js test/lineage/scc-solver.test.js test/graph/graph-views.test.js test/lineage/dag07-completion.test.js test/lineage/owned-build.test.js test/dataflow/boundary-propagation.test.js test/lineage/boundary-contract.test.js test/lineage/correlation-v2.test.js test/lineage/path-control-evidence.test.js",
|
|
93
94
|
"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",
|
|
94
95
|
"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",
|
|
95
|
-
"test:haskell": "node --test test/haskell/haskell-weak-hash-names.test.js 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-daemon.test.js 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",
|
|
96
|
+
"test:haskell": "node --test test/haskell/haskell-weak-hash-names.test.js 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 test/haskell/haskell-boundary-propagation.test.js",
|
|
97
|
+
"test:nix": "node --test test/nix/nixos-hardening-daemon.test.js 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 test/nix/nix-boundary-scope.test.js",
|
|
97
98
|
"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",
|
|
98
99
|
"test:language-stress": "node --test --test-concurrency=1 test/language/language-stress-offline.test.js",
|
|
99
100
|
"test:language-tools": "node --test test/haskell/haskell-web-auth.test.js test/haskell/haskell-support-gate.test.js",
|
|
@@ -181,7 +182,19 @@
|
|
|
181
182
|
"bench:self-scan": "node ../bench/self-scan/measure.mjs",
|
|
182
183
|
"bench:self-scan:check": "node ../bench/self-scan/check.mjs",
|
|
183
184
|
"bench:nist-800-171-labels:check": "node ../bench/nist-800-171-labels/check.mjs",
|
|
184
|
-
"bench:dci-real-app": "node ../bench/dci-real-app/runner.mjs",
|
|
185
|
+
"bench:dci-real-app": "node ../bench/dci-real-app/runner.mjs",
|
|
186
|
+
"bench:dci-real-app:check": "node ../bench/dci-real-app/runner.mjs --check",
|
|
187
|
+
"ee:perf-budget": "node ../scripts/engineering-excellence/perf-budget.mjs",
|
|
188
|
+
"ee:perf-budget:check": "node ../scripts/engineering-excellence/perf-budget.mjs --check",
|
|
189
|
+
"ee:e2e-demo": "node ../scripts/engineering-excellence/e2e-demo.mjs",
|
|
190
|
+
"ee:e2e-demo:check": "node ../scripts/engineering-excellence/e2e-demo.mjs --check",
|
|
191
|
+
"ee:doc-captures": "node ../scripts/engineering-excellence/doc-captures.mjs",
|
|
192
|
+
"ee:doc-captures:check": "node ../scripts/engineering-excellence/doc-captures.mjs --check",
|
|
193
|
+
"ee:regression-report": "node ../scripts/engineering-excellence/regression-report.mjs",
|
|
194
|
+
"ee:regression-report:check": "node ../scripts/engineering-excellence/regression-report.mjs --check",
|
|
195
|
+
"ee:final-report": "node ../scripts/engineering-excellence/final-report.mjs",
|
|
196
|
+
"ee:final-report:check": "node ../scripts/engineering-excellence/final-report.mjs --check",
|
|
197
|
+
"bench:mutation:check": "node ../bench/mutation/runner.mjs",
|
|
185
198
|
"baseline:capture": "node ../scripts/baseline-capture.mjs",
|
|
186
199
|
"bench:protection-verdict:check": "node ../bench/protection-verdict/runner.mjs",
|
|
187
200
|
"bench:independent:forensics": "node ../bench/independent/forensics.mjs",
|
|
@@ -230,6 +243,10 @@
|
|
|
230
243
|
"bench:layer-recall": "node ../bench/layer-recall/runner.mjs",
|
|
231
244
|
"bench:layer-recall:check": "node ../bench/layer-recall/runner.mjs --check",
|
|
232
245
|
"bench:layer-recall:update-baseline": "node ../bench/layer-recall/runner.mjs --update-baseline",
|
|
246
|
+
"bench:dag": "node ../bench/dag/run.mjs",
|
|
247
|
+
"bench:dag:quick": "node ../bench/dag/run.mjs --quick",
|
|
248
|
+
"bench:dag:check": "node ../bench/dag/run.mjs --check",
|
|
249
|
+
"bench:dag:update-baseline": "node ../bench/dag/run.mjs --update-baseline",
|
|
233
250
|
"bench:provenance-accuracy": "node ../bench/provenance-accuracy/runner.mjs",
|
|
234
251
|
"bench:provenance-accuracy:check": "node ../bench/provenance-accuracy/runner.mjs --check",
|
|
235
252
|
"bench:provenance-accuracy:update-baseline": "node ../bench/provenance-accuracy/runner.mjs --update-baseline",
|
|
@@ -274,6 +291,7 @@
|
|
|
274
291
|
"completion-status": "node ../scripts/write-completion-status.mjs",
|
|
275
292
|
"docs:check-positioning": "node ../scripts/check-positioning-docs.mjs",
|
|
276
293
|
"docs:positioning": "node ../scripts/check-positioning-docs.mjs --write",
|
|
294
|
+
"docs:compliance-coverage": "node ../scripts/compliance-coverage.mjs",
|
|
277
295
|
"docs:check-language": "node ../scripts/render-language-docs.mjs --check && node ../scripts/capture-language-examples.mjs --check",
|
|
278
296
|
"test:nixos-host": "node --test test/nix/nixos-host-runtime.test.js",
|
|
279
297
|
"test:language-gates": "node --test --test-concurrency=1 test/language/language-benchmark-gates.test.js",
|
|
@@ -94,6 +94,9 @@ const AUTH_NAME = /(?:^|[.:])(?:(?:require|ensure|check|assert|verify|validate|e
|
|
|
94
94
|
|
|
95
95
|
const SENSITIVE_NAME = /(?:^|[.:])(?:query|queryOne|queryRow|exec|execute|executeQuery|raw|rawQuery|prepare|find|findAll|findOne|findById|findByPk|findUnique|findFirst|findMany|get|getById|getBy|select|selectList|selectFirst|insert|insertOne|insertMany|insert_|update|updateOne|updateMany|upsert|delete|deleteOne|deleteMany|remove|destroy|save|create|createMany|aggregate|runDB|writeFile|writeFileSync|appendFile|unlink|rm|rmdir|spawn|spawnSync|execSync|execFile|system|popen|fetch|request|post|put|patch)$/i;
|
|
96
96
|
const DB_RECEIVER = /(?:^|\b)(?:db|database|conn|connection|pool|client|cursor|session|repo|repository|dao|model|models|collection|table|prisma|knex|sequelize|orm|store|objects|manager|em|entityManager|mongo|redis|cache|conn|stmt|statement|fs|child_process|cp|axios|http|https|requests|httpx|got|superagent|Database|Persist|Yesod|System)\b/;
|
|
97
|
+
// Flask-SQLAlchemy `Model.query...`, SQLAlchemy `session.query/add/delete/merge/execute/get`, and the query-builder methods that end a chain.
|
|
98
|
+
const PY_ORM = /(?:\b[A-Z]\w*\.query\b|\b(?:db\.)?session\.(?:query|add|add_all|delete|merge|execute|get|bulk_save_objects)\b|\.(?:filter_by|get_or_404|first_or_404|one_or_404)\()/;
|
|
99
|
+
const PY_ORM_WRITE = /\.(?:delete|update|bulk_update_mappings|bulk_insert_mappings)\(|\b(?:db\.)?session\.(?:add|add_all|delete|merge|bulk_save_objects)\b/;
|
|
97
100
|
const SQL_TEXT = /\b(?:select\s[\s\S]{1,120}\sfrom|insert\s+into|update\s+\w+\s+set|delete\s+from)\b/i;
|
|
98
101
|
const HS_SENSITIVE = /(?:^|\.)(?:runDB|selectList|selectFirst|getBy|getJust|insert_?|insertEntity|update|updateWhere|delete|deleteWhere|replace|upsert|query|query_|execute|execute_|readFile|writeFile|callProcess|readProcess)$|^(?:Database\.|System\.Process\.|System\.Directory\.)/;
|
|
99
102
|
|
|
@@ -253,6 +256,18 @@ export function analyzeSymbolText(symbol, lines, { haskell = false } = {}) {
|
|
|
253
256
|
}
|
|
254
257
|
}
|
|
255
258
|
}
|
|
259
|
+
// Python ORM calls. `Model.query.filter_by(...).delete()` and `db.session.add(x)` name no database receiver the call-name rule
|
|
260
|
+
// recognises, and the chained `.delete()` is not a call on one, so the data operation was invisible and a route that
|
|
261
|
+
// deletes a row read as touching nothing sensitive. A write is a chained mutation or a session write; anything else is a read.
|
|
262
|
+
if (!haskell && PY_ORM.test(raw)) {
|
|
263
|
+
const orm = PY_ORM_WRITE.test(raw) ? 'write' : 'read';
|
|
264
|
+
push({ line: ln, category: 'sensitive', kind: `data-${orm}`, subkind: orm, evidence: 'observed', basis: 'orm-call', rejectionSeen: null, text: clip(raw) });
|
|
265
|
+
const stmt = statementAt(lines, ln);
|
|
266
|
+
const pr = ownerBinding(stmt, extraPrincipal);
|
|
267
|
+
if (pr) {
|
|
268
|
+
push({ line: ln, category: 'control', kind: pr.tenant ? 'tenant-scope' : 'ownership', subkind: null, evidence: pr.level === 'qualified' ? 'observed' : 'inferred', basis: pr.level === 'qualified' ? 'query-filter' : 'query-filter-unqualified', rejectionSeen: null, text: clip(raw) });
|
|
269
|
+
}
|
|
270
|
+
}
|
|
256
271
|
if (SQL_TEXT.test(raw)) {
|
|
257
272
|
const verb = /\b(?:insert|update|delete)\b/i.test(raw) ? 'write' : 'read';
|
|
258
273
|
push({ line: ln, category: 'sensitive', kind: `data-${verb}`, subkind: verb, evidence: 'observed', basis: 'sql-text', rejectionSeen: null, text: clip(raw) });
|
|
@@ -166,8 +166,14 @@ export function evaluateProtection({ facts, unknowns, omittedWithControls = fals
|
|
|
166
166
|
const ctl = facts.filter(f => f.category === 'control' && kinds.includes(f.kind));
|
|
167
167
|
// A control whose answer is visibly thrown away (a predicate called as a bare statement) guards nothing.
|
|
168
168
|
const effective = (f) => f.rejectionSeen !== false;
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
// Ownership is the one dimension where reading before checking is the ordinary safe shape: load the record by id, refuse unless the
|
|
170
|
+
// principal owns it, and only then act on it. What an unchecked read can do is bounded by the check that follows before anything is
|
|
171
|
+
// written, so for ownership and tenant scope the line that must be preceded is the first WRITE. With no write in view the first
|
|
172
|
+
// sensitive operation of any kind still applies, so a read returned without a check is not excused.
|
|
173
|
+
const writes = sens.filter(f => f.subkind === 'write' || f.kind === 'filesystem' || f.kind === 'process');
|
|
174
|
+
const gate = dim === 'ownership' && writes.length ? Math.min(...writes.map(f => f.effLine)) : firstSens;
|
|
175
|
+
const before = ctl.filter(f => effective(f) && (gate === null || f.effLine < gate || (f.basis === 'query-filter' && f.effLine <= gate)));
|
|
176
|
+
const after = ctl.filter(f => gate !== null && f.effLine > gate);
|
|
171
177
|
let state; let why;
|
|
172
178
|
if (before.length) { state = 'present'; why = 'a control precedes the first sensitive operation'; }
|
|
173
179
|
else if (after.length) { state = 'evaluated_and_ineffective'; why = 'every control of this kind runs after the first sensitive operation'; }
|
package/src/dataflow/CLAUDE.md
CHANGED
|
@@ -103,6 +103,25 @@ argument 2) and `c.Redirect(code, url)` (argument 1) are sinks. Laravel `$reques
|
|
|
103
103
|
request-named variable). `cs-aspnet-implicit-action-param` and `java-spring-implicit-mapped-param` are annotation sources fed by `ir/implicit-handler-params.js`.
|
|
104
104
|
Tests: `test/evaluation/engine-mechanisms.test.js`.
|
|
105
105
|
|
|
106
|
+
## Boundary-contract consumer seeding (DAG-08)
|
|
107
|
+
|
|
108
|
+
`cross-service-taint.js` still only ANNOTATES findings for `consumes` declarations. The separate `runBoundaryTaint(perFileIR, callGraph, contracts)` seeds bound boundary contracts (see `../lineage/boundary-contract.js`): it sets `fn.boundarySeeds` (access paths such as `evt.customerId`, read by `_unionAnnotationTaint`) for one seed per engine run and always removes it afterwards. Findings new relative to an unseeded baseline carry `boundary` evidence (`modeledInput: true`, `observed: false`) and the consumer field that reached them. A contract that does not bind yields a coverage gap, no finding. Cost is one `runTaintEngine` pass per seed, capped by `maxRuns` (default 64, reported as a `budget` gap when hit).
|
|
109
|
+
## Demand-driven sink queries (DAG-02, `demand-query.js`)
|
|
110
|
+
|
|
111
|
+
Opt-in (`AGENTIC_SECURITY_DEMAND=1` plus an explicit query list or the `runDemandSinkQuery` API; the default scan never calls it). A query is keyed by exact sink site (file, line, optional node id, callee, sink id), argument index, field/access path inside that argument, context (only `whole-program` is supported; anything else is `unavailable`), rule family (CWE or family name) and the graph and configuration digests (`graphDigest`, `configDigest`, `sinkQueryKey`).
|
|
112
|
+
|
|
113
|
+
How it answers:
|
|
114
|
+
|
|
115
|
+
1. **Backward demand frontier** (`Frontier`): from the sink argument it follows definitions (field-aware, so `o.b` does not pull in the write to `o.a`), aliases, parameter to caller argument mappings, producer helper bodies (a callee whose return value feeds the sink), callee mutators, receiver paths, callbacks and their registrars, free variables (the defining functions in the same file), and the request-field writers the engine seeds across middleware. It uses the canonical caller index (`buildCallerQidIndex` in `tabulation.js`) extended with the embedded call sites `fn.calls` omits (`buildIncomingIndex`).
|
|
116
|
+
2. **Forward corroboration**: the EXISTING `runTaintEngine` runs over only the selected functions. The only witness is a finding that engine produced. The backward/forward overlap is reported as `candidateFilter`, labelled `candidate-filter-only`, and is never a witness.
|
|
117
|
+
3. **Conservative expansion (R02.4)**: an unsupported construct (instance fields and `this` receivers), a hit depth limit (`maxCallerDepth`, default 64) or a hit work limit (`maxWork`) expands to the FULL function set by default (`onLimit` / `onUnsupported` = `'full'`, recorded in `result.fallback`). With `'partial'` the result reports `partial` with `unexploredFrontierCount` instead. A function is never dropped because the selector did not reach it.
|
|
118
|
+
4. **No negative verdict from a limited walk**: `negativeClaimAllowed` comes from `lineage/completion.js` `makeCompletion` and is false for any limit, unsupported construct, unresolved callee, dynamic callee, engine `analysisIncomplete` reason or `unavailable` query. The verdict vocabulary is `flow-found`, `no-flow-in-modeled-scope` (scoped to the modeled graph) and `unknown`; there is no "safe".
|
|
119
|
+
5. **Field requests**: with `accessPath`, a finding is attributed only if the field-specific frontier reaches a non-clean terminal (source, parameter, producer or unresolved call, free variable). A sibling-only taint is suppressed and counted in `siblingFieldSuppressed`. The full-analysis reference (`runFullSinkQuery`) applies the same rule, so parity isolates the function selection.
|
|
120
|
+
|
|
121
|
+
Reconciliation (R02.5), nothing removed: `tabulation.js` keeps the coarse caller-only selector (`reachabilitySliceWithCompletion`; it cannot see producer helpers, which the parity corpus demonstrates), `backward.js` keeps the intraprocedural explanation trace (`reverseEdgesOf` now shares the CFG incoming-edge relation), `ifds-precise.js` keeps its predecessor chain and gains `backwardSliceWithCompletion`. `reconcileSelectors` reports the per-selector difference and roles using the shared completion vocabulary.
|
|
122
|
+
|
|
123
|
+
Known limits, stated honestly: instance-field and `this` flows always fall back to full analysis; the frontier is flow-insensitive and conservative, so it can select more than needed; an unresolved or dynamic callee is passed through (the engine does the same) but reported and blocks a negative claim; the optional `_cha` and `_pointsTo` opts are passed through unchanged, with method-name candidate expansion standing in for class-hierarchy resolution during selection. Tests: `test/demand-query.test.js` (21 fixture programs under `test/fixtures/demand/`, scored for parity against full analysis, plus the adversarial family and mutation checks). Benchmark: `bench/dag-demand/run.mjs`.
|
|
124
|
+
|
|
106
125
|
## Entry points
|
|
107
126
|
|
|
108
127
|
- `runTaintEngine(perFileIR, callGraph, opts)` — the public entry. Runs from `engine.js` when `AGENTIC_SECURITY_DEEP=1`. **R1 (PRD §5):** the CLI entry (`bin/agentic-security.js#cmdScan`) sets that env var by default for local/interactive scans (not in CI, and not when `--no-deep`/`AGENTIC_SECURITY_DEEP=0`), so the default `/scan --all` runs deep. In-process callers (tests, the cve-replay corpus) invoke `runScan()` directly without the CLI default and therefore stay deep-off unless they set the env var themselves (e.g. `test/deep-taint.test.js`).
|
|
@@ -123,12 +142,35 @@ Tests: `test/evaluation/engine-mechanisms.test.js`.
|
|
|
123
142
|
|
|
124
143
|
- **Path attribution.** If you're adding a sink to the catalog, set `argIndex` carefully. `'all'` means "any tainted arg fires"; a numeric index pinpoints THE arg whose taint matters. Wrong here → noisy findings with confused traces.
|
|
125
144
|
- **A member-WRITE sink (`x.prop = tainted`, `argIndex: 'rhs'`) MUST use `match.object: '_any_'`.** `matchMemberWriteSink` (catalog.js) indexes every write-sink entry under a fixed `_any_.<prop>` key and applies object-specificity AFTERWARD via the optional `match.receiver` regex (checked against the dotted-prefix segments before the final prop) — the same shape `react-dangerouslySetInnerHTML`/`js-koa-ctx-body` use. An entry written with a literal object name (`object: 'ctx'`) is indexed under a completely different key and is silently never found — confirmed by writing `js-koa-ctx-body` with `object: 'ctx'` first, which never fired, with no error anywhere. This is the write-sink analog of `match.type: 'call'` entries always keying off bare callee name.
|
|
126
|
-
- **Cache invalidation.** `SummaryCache` is in-memory per-scan. Cross-scan persistence
|
|
145
|
+
- **Cache invalidation.** `SummaryCache` is in-memory per-scan. Cross-scan persistence is `AGENTIC_SECURITY_INCREMENTAL=1` and is described in "Cross-scan incremental analysis" below. Don't conflate the two.
|
|
127
146
|
- **Recursion.** The cache returns a bottom summary (`_recursive: true`) when it hits a function already on the stack. The engine relies on fixed-point iteration to refine, and `runTaintEngine` does run a multi-pass loop (`MAX_FP_ITERS = 3`, `engine.js`) — this gotcha previously claimed a single pass, which contradicted the "Recursion via fixed point" bullet above and was stale. Cycles that have not converged within 3 iterations still under-approximate.
|
|
128
147
|
- **`AGENTIC_SECURITY_BLIND_BENCH=1` does NOT disable the deep engine.** It gates the bench-shape detectors; `_deepRequested` in `engine.js` keys on `AGENTIC_SECURITY_DEEP === '1'` alone, so deep mode runs regardless. (This bullet previously claimed the opposite — verified false while building `bench/layer-recall/`, where setting `BLIND_BENCH=1` left taint recall unchanged at 20/210.) To turn the taint engine off, set `AGENTIC_SECURITY_DEEP=0`.
|
|
129
148
|
- **The corpus barely exercises this engine.** `bench/cve-replay` enables deep mode only for its 6 `deep`-tier entries, and with the deep engine off entirely, corpus detection falls only 210 → 204. Taint quality is measured by `npm run bench:layer-recall` (which forces deep on for all 210), not by the corpus gate — see `docs/METRICS.md`.
|
|
130
149
|
- **Resolved: `stub-aware-filter.js` no longer mutates `severity`.** It used to (`f.severity = downgrade[f.severity]`, opt-in via `AGENTIC_SECURITY_TYPE_STUBS=1`), which violated the recall-preserving convention every other precision annotator in this directory follows. Flagged by documentation audit, then fixed on maintainer decision: it now demotes `confidence` (× 0.4, floor 0.01) + `confidenceTier` + `exploitabilityTier` by one step each, mirroring `proof-gate.js`'s own demotion shape exactly (`_confidenceBeforeStubFilter` records the pre-demotion value, a distinct field from `proof-gate.js`'s `_confidenceBeforeProofGate` so the two compose if both fire on the same finding). Severity is never touched.
|
|
131
150
|
|
|
151
|
+
## Cross-scan incremental analysis (DAG-05)
|
|
152
|
+
|
|
153
|
+
Opt-in (`AGENTIC_SECURITY_INCREMENTAL=1`; the CLI turns it on for `--pr` and `--changed-since`). A warm scan must give the same findings and completion as a cold scan of the same tree; the cache changes the cost, never the answer. Any doubt is a cold scan that states why.
|
|
154
|
+
|
|
155
|
+
| Module | Job |
|
|
156
|
+
|---|---|
|
|
157
|
+
| `dep-fingerprint.js` | The dependency model. Per function: an OWN fingerprint (canonical body with node ids renamed, because the IR numbers nodes from a process-global counter; the resolution of every name it calls or passes along; the file's shared facts; the class hierarchy), edges (calls, callbacks, same-class methods, class-field coupling, request-object seeding), SCCs (`graph/scc.js`) and a CLOSURE fingerprint per component. Plus the GLOBAL components, one content digest each: `options`, `build`, `graphSchema`, `catalog`, `sanitizers`, `analyzers`, `stubs`, `policies`, `boundary`. `planIncremental` compares a prior model with the current one. |
|
|
158
|
+
| `incremental-session.js` | `begin` (read state, fingerprint, decide warm or cold, restore typed contexts of clean functions) and `finish` (stamp `cacheProvenance` on findings, persist, build the stats). Unsupported options (`POINTS_TO`, `RHS`, `KCFA_CALLSTRING`, `BACKWARD_SLICE`, `SYMEXEC`) are cold with the option named. |
|
|
159
|
+
| `incremental-replay.js` | `ReplayHooks`, passed to `runTaintEngine` as `opts._replay`: records each function's findings (after the engine's own de-duplication key, duplicates included) and pre-pass exit state; replays them for a function proved clean. |
|
|
160
|
+
| `incremental.js` | Atomic persistence (below), `serializeContexts`/`restoreContexts` (typed, context-keyed), and the older primitives the tests still pin. |
|
|
161
|
+
|
|
162
|
+
Rules that are easy to get wrong:
|
|
163
|
+
|
|
164
|
+
- **Content, not counts.** A sanitizer whose behaviour changed keeps the catalog size; the `catalog` and `sanitizers` components digest the entries. The stored version record's `rules` field is `content:<digest>` for the same reason.
|
|
165
|
+
- **A removal is found through the PRIOR graph.** The persisted graph keeps each function's callees and each file's symbols, so a deleted or renamed callee dirties its callers even when the current IR has no trace of it. Reverse closure and whole SCCs are then recomputed; the closure fingerprint is a second, independent check.
|
|
166
|
+
- **Contexts keep their keys.** Every computed context is stored as `{entry list, stateHash, receiver hash, typed summary}` and restored only if the entry list reproduces its hash (`SummaryCache.restoreContext`). A tainted context is never stored in, or answered from, the empty-entry slot.
|
|
167
|
+
- **Atomic and verified.** Data files are written to uniquely named temp files and renamed; the manifest (the version file, which holds each data file's SHA-256) is renamed LAST. The reader rejects a missing, truncated, torn, hand-edited, legacy-format or schema-incompatible set as a whole. There is deliberately no fsync: the digest check, not durability, is what protects the cache.
|
|
168
|
+
- **Records are only valid for the loop they came from.** The main loop covers only the first `fnLimit` functions by qid, so a record carries `inMain` and replays only when that is unchanged. A prior run that hit the summary budget, a deadline or an analysis error, or whose fixed point did not converge, is not reused.
|
|
169
|
+
- **What it cannot do.** It never decides a result is unchanged because a callee's SUMMARY came out the same (no early cutoff): every transitive caller of an edited function is recomputed. A class's methods are one component. Resolution of names is replayed from the engine's own resolver; a project that re-exports under an alias disables the resolver pre-filter's shortcut for that name. Python, JavaScript and Haskell are exercised; other languages use the same path but are not measured here. Parsing to IR is not cached, so end-to-end speed-up is bounded by it (see `bench/dag-incremental/`).
|
|
170
|
+
- **Nix has no hook.** Its analysers keep no cross-scan state; `scanHealth.deepAnalysis.incremental` says `languagesWithoutIncrementalHook: ['nix']` and the scan is cold for it every time.
|
|
171
|
+
- **Where it is reported.** `findings[].cacheProvenance` (`reused` with the generation and closure fingerprint, or `recomputed`), `findings._incrementalStats` (non-enumerable), `scan.scanHealth.deepAnalysis.incremental`.
|
|
172
|
+
- **A call chain hundreds deep makes even a cold run non-deterministic** (the engine recurses on the JS stack and a `RangeError` is swallowed). Do not build parity fixtures that deep.
|
|
173
|
+
|
|
132
174
|
## Haskell catalog
|
|
133
175
|
|
|
134
176
|
`catalog-haskell.js` is **generated** from `language/haskell-models.js` (one registry of sources, sinks and sanitizers; entries
|
package/src/dataflow/backward.js
CHANGED
|
@@ -49,6 +49,15 @@ function _reverseEdges(cfg) {
|
|
|
49
49
|
return rev;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
/**
|
|
53
|
+
* CFG reverse-edge index (node id -> predecessor ids), exported so the demand
|
|
54
|
+
* selector (demand-query.js) and this slicer share one definition of the
|
|
55
|
+
* incoming-edge relation instead of each deriving its own.
|
|
56
|
+
*/
|
|
57
|
+
export function reverseEdgesOf(cfg) {
|
|
58
|
+
return _reverseEdges(cfg);
|
|
59
|
+
}
|
|
60
|
+
|
|
52
61
|
/**
|
|
53
62
|
* Build a backward slice from a finding's sink site to its source(s).
|
|
54
63
|
*
|
|
@@ -75,10 +84,28 @@ function _reverseEdges(cfg) {
|
|
|
75
84
|
* ]
|
|
76
85
|
*/
|
|
77
86
|
export function sliceBackward(fn, sinkNode, sinkArgPath) {
|
|
87
|
+
return sliceBackwardWithCompletion(fn, sinkNode, sinkArgPath).slice;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Same slice, plus a completion record (DAG-07 R07.1): { slice, completion }.
|
|
92
|
+
* A slice that stopped at SLICE_BUDGET_NODES is a prefix of the real
|
|
93
|
+
* backward closure; the record carries how many queued steps were left, so a
|
|
94
|
+
* consumer (the SMT infeasibility check among them) can tell "no source
|
|
95
|
+
* found" from "stopped looking". `sliceBackward` itself still returns the
|
|
96
|
+
* bare array for existing callers, with the same record attached as a
|
|
97
|
+
* non-enumerable `completion` property.
|
|
98
|
+
*/
|
|
99
|
+
export function sliceBackwardWithCompletion(fn, sinkNode, sinkArgPath) {
|
|
78
100
|
const out = [];
|
|
79
|
-
|
|
101
|
+
const completion = { status: 'complete', reasons: [], unexploredFrontierCount: 0, visited: 0, limits: { maxNodes: SLICE_BUDGET_NODES } };
|
|
102
|
+
const finish = () => {
|
|
103
|
+
Object.defineProperty(out, 'completion', { value: completion, enumerable: false, configurable: true });
|
|
104
|
+
return { slice: out, completion };
|
|
105
|
+
};
|
|
106
|
+
if (!fn || !sinkNode) { completion.status = 'unavailable'; completion.reasons = ['no-function-or-sink']; return finish(); }
|
|
80
107
|
const cfg = fn.cfg;
|
|
81
|
-
if (!cfg || !cfg.nodes) return
|
|
108
|
+
if (!cfg || !cfg.nodes) { completion.status = 'unavailable'; completion.reasons = ['no-cfg']; return finish(); }
|
|
82
109
|
const rev = _reverseEdges(cfg);
|
|
83
110
|
|
|
84
111
|
// Map node-id to itself lookup for nodes in this CFG.
|
|
@@ -90,7 +117,7 @@ export function sliceBackward(fn, sinkNode, sinkArgPath) {
|
|
|
90
117
|
for (const id of Object.keys(nodes)) {
|
|
91
118
|
if (nodes[id] === sinkNode) { sinkNid = id; break; }
|
|
92
119
|
}
|
|
93
|
-
if (!sinkNid) return
|
|
120
|
+
if (!sinkNid) { completion.status = 'unavailable'; completion.reasons = ['sink-not-in-cfg']; return finish(); }
|
|
94
121
|
|
|
95
122
|
out.push({
|
|
96
123
|
line: sinkNode.line || 0,
|
|
@@ -104,7 +131,12 @@ export function sliceBackward(fn, sinkNode, sinkArgPath) {
|
|
|
104
131
|
let visitedCount = 0;
|
|
105
132
|
|
|
106
133
|
while (work.length) {
|
|
107
|
-
if (++visitedCount > SLICE_BUDGET_NODES)
|
|
134
|
+
if (++visitedCount > SLICE_BUDGET_NODES) {
|
|
135
|
+
completion.status = 'partial';
|
|
136
|
+
completion.reasons = ['slice-node-budget'];
|
|
137
|
+
completion.unexploredFrontierCount = work.length;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
108
140
|
const { nid, queryPath } = work.shift();
|
|
109
141
|
const key = `${nid}::${queryPath}`;
|
|
110
142
|
if (visited.has(key)) continue;
|
|
@@ -206,8 +238,10 @@ export function sliceBackward(fn, sinkNode, sinkArgPath) {
|
|
|
206
238
|
}
|
|
207
239
|
}
|
|
208
240
|
|
|
241
|
+
completion.visited = Math.min(visitedCount, SLICE_BUDGET_NODES);
|
|
209
242
|
// Reverse so the trace reads source-first.
|
|
210
|
-
|
|
243
|
+
out.reverse();
|
|
244
|
+
return finish();
|
|
211
245
|
}
|
|
212
246
|
|
|
213
247
|
/**
|
|
@@ -233,7 +267,7 @@ export function annotateBackwardSlices(findings, perFileIR, callGraph) {
|
|
|
233
267
|
if (callGraph && callGraph.functions) {
|
|
234
268
|
for (const fn of callGraph.functions.values()) fnByQid.set(fn.qid, fn);
|
|
235
269
|
}
|
|
236
|
-
let annotated = 0, skipped = 0, exhausted = false;
|
|
270
|
+
let annotated = 0, skipped = 0, exhausted = false, partialSlices = 0;
|
|
237
271
|
for (const f of findings) {
|
|
238
272
|
if (Date.now() > deadline) { exhausted = true; skipped++; continue; }
|
|
239
273
|
if (!f || !f._funcQid) { skipped++; continue; }
|
|
@@ -278,6 +312,7 @@ export function annotateBackwardSlices(findings, perFileIR, callGraph) {
|
|
|
278
312
|
if (!slice) slice = candidateSlice;
|
|
279
313
|
}
|
|
280
314
|
}
|
|
315
|
+
if (slice && slice.completion && slice.completion.status !== 'complete') partialSlices++;
|
|
281
316
|
if (slice && slice.length) {
|
|
282
317
|
f.backwardSlice = slice;
|
|
283
318
|
f.pathSteps = (f.pathSteps || []).concat(slice.map(s => ({
|
|
@@ -291,7 +326,7 @@ export function annotateBackwardSlices(findings, perFileIR, callGraph) {
|
|
|
291
326
|
}
|
|
292
327
|
}
|
|
293
328
|
Object.defineProperty(findings, '_annotateBackwardSlicesStats', {
|
|
294
|
-
value: { annotated, skipped, exhausted, budgetMs },
|
|
329
|
+
value: { annotated, skipped, exhausted, budgetMs, partialSlices },
|
|
295
330
|
enumerable: false,
|
|
296
331
|
});
|
|
297
332
|
return findings;
|
|
@@ -63,6 +63,8 @@ import * as path from 'node:path';
|
|
|
63
63
|
import * as yaml from '../util/yaml.js';
|
|
64
64
|
|
|
65
65
|
import { statePath } from '../posture/state-dir.js';
|
|
66
|
+
import { runTaintEngine } from './engine.js';
|
|
67
|
+
import { bindBoundaryContracts, boundaryAttribution, BOUNDARY_CONTRACTS_FILENAME, validateBoundaryContract } from '../lineage/boundary-contract.js';
|
|
66
68
|
const SERVICES_FILE_NAMES = ['services.yml', 'services.yaml'];
|
|
67
69
|
|
|
68
70
|
export function loadServiceGraph(scanRoot) {
|
|
@@ -342,4 +344,84 @@ export function runCrossServiceTaint(scanRoot, findings) {
|
|
|
342
344
|
return annotateCrossServiceFindings(findings, graph, current);
|
|
343
345
|
}
|
|
344
346
|
|
|
345
|
-
|
|
347
|
+
// ─── DAG-08: boundary-contract consumer seeding ──────────────────────────────
|
|
348
|
+
//
|
|
349
|
+
// The SCOPE NOTE above stays true of the `consumes` annotation pass: it never invents a source. This section is the separate,
|
|
350
|
+
// explicit mechanism that does. A versioned boundary contract (lineage/boundary-contract.js) that BINDS to a parser-resolved
|
|
351
|
+
// consumer function and parameter seeds the declared, mapped fields of that parameter as a MODELED untrusted input. The seed is
|
|
352
|
+
// handed to the engine through `fn.boundarySeeds` (read by engine.js's `_unionAnnotationTaint`) for the duration of one run and
|
|
353
|
+
// always removed afterwards, so the shared call graph is never left seeded.
|
|
354
|
+
//
|
|
355
|
+
// A finding produced this way carries `boundary: {..., modeledInput: true, observed: false, exploited: false}`. A declaration
|
|
356
|
+
// establishes where taint is assumed to enter; it never establishes that a value was seen or that the sink is exploitable. A
|
|
357
|
+
// contract that does not bind produces a coverage gap and NO finding.
|
|
358
|
+
|
|
359
|
+
const DEFAULT_MAX_BOUNDARY_RUNS = 64;
|
|
360
|
+
|
|
361
|
+
function loadBoundaryContracts(scanRoot) {
|
|
362
|
+
if (!scanRoot) return { contracts: [], errors: [] };
|
|
363
|
+
const fp = statePath(scanRoot, BOUNDARY_CONTRACTS_FILENAME);
|
|
364
|
+
if (!fs.existsSync(fp)) return { contracts: [], errors: [] };
|
|
365
|
+
try {
|
|
366
|
+
const doc = JSON.parse(fs.readFileSync(fp, 'utf8'));
|
|
367
|
+
const list = Array.isArray(doc) ? doc : Array.isArray(doc && doc.contracts) ? doc.contracts : [];
|
|
368
|
+
return { contracts: list, errors: [] };
|
|
369
|
+
} catch (e) {
|
|
370
|
+
return { contracts: [], errors: [`Failed to parse ${fp}: ${e.message}`] };
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Run the taint engine with each bound contract's consumer fields seeded, one seed at a time so a finding is attributed to the
|
|
376
|
+
* exact consumer field that reached it (a sibling field the contract does not map is never seeded and so never attributed).
|
|
377
|
+
* When `contracts` is null/undefined they are read from `<scanRoot>/.agentic-security/boundary-contracts.json` (opts.scanRoot).
|
|
378
|
+
* @returns {{findings: object[], bindings: object[], gaps: object[], rejected: object[], coverage: object, loadErrors: string[]}}
|
|
379
|
+
*/
|
|
380
|
+
export function runBoundaryTaint(perFileIR, callGraph, contracts, opts = {}) {
|
|
381
|
+
let loadErrors = [];
|
|
382
|
+
if (contracts === null || contracts === undefined) { const l = loadBoundaryContracts(opts.scanRoot); contracts = l.contracts; loadErrors = l.errors; }
|
|
383
|
+
const maxRuns = Number.isFinite(opts.maxRuns) ? opts.maxRuns : DEFAULT_MAX_BOUNDARY_RUNS;
|
|
384
|
+
const { bindings, gaps, rejected } = bindBoundaryContracts(contracts, callGraph);
|
|
385
|
+
const fnByQid = new Map();
|
|
386
|
+
for (const f of callGraph.functions.values()) fnByQid.set(f.qid, f);
|
|
387
|
+
const baseline = new Set(runTaintEngine(perFileIR, callGraph, opts.engine || {}).map((f) => f.id));
|
|
388
|
+
const found = new Map();
|
|
389
|
+
let runs = 0; let truncated = false;
|
|
390
|
+
for (const b of bindings) {
|
|
391
|
+
const fn = fnByQid.get(b.qid);
|
|
392
|
+
for (const seed of b.seeds) {
|
|
393
|
+
if (runs >= maxRuns) { truncated = true; break; }
|
|
394
|
+
runs++;
|
|
395
|
+
const prior = fn.boundarySeeds;
|
|
396
|
+
fn.boundarySeeds = [seed];
|
|
397
|
+
let out = [];
|
|
398
|
+
try { out = runTaintEngine(perFileIR, callGraph, opts.engine || {}); } finally { if (prior === undefined) delete fn.boundarySeeds; else fn.boundarySeeds = prior; }
|
|
399
|
+
const mapping = b.mappedFields.find((m) => seed.endsWith(`.${m.to}`) || seed === m.to) || null;
|
|
400
|
+
for (const f of out) {
|
|
401
|
+
if (baseline.has(f.id)) continue;
|
|
402
|
+
let rec = found.get(f.id);
|
|
403
|
+
if (!rec) { rec = { finding: { ...f }, attributions: [] }; found.set(f.id, rec); }
|
|
404
|
+
rec.attributions.push({ binding: b, seed, mapping });
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
if (truncated) break;
|
|
408
|
+
}
|
|
409
|
+
const findings = [...found.values()].map(({ finding, attributions }) => {
|
|
410
|
+
const first = attributions[0];
|
|
411
|
+
finding.boundary = {
|
|
412
|
+
...boundaryAttribution(first.binding),
|
|
413
|
+
fields: attributions.map((a) => ({ seed: a.seed, producerField: a.mapping && a.mapping.from, consumerField: a.mapping && a.mapping.to })),
|
|
414
|
+
discoveredBy: 'boundary-contract-seed',
|
|
415
|
+
};
|
|
416
|
+
finding.boundarySeeded = true;
|
|
417
|
+
return finding;
|
|
418
|
+
}).sort((a, b) => (a.id < b.id ? -1 : 1));
|
|
419
|
+
const allGaps = [...gaps];
|
|
420
|
+
if (truncated) allGaps.push({ kind: 'budget', reason: 'engine-run-budget', detail: `stopped after ${maxRuns} seeded runs; remaining seeds were not analyzed` });
|
|
421
|
+
return {
|
|
422
|
+
findings, bindings, gaps: allGaps, rejected, loadErrors,
|
|
423
|
+
coverage: { contracts: (contracts || []).length, bound: bindings.length, unbound: gaps.filter((g) => g.side === 'consumer').length, rejected: rejected.length, engineRuns: runs, truncated },
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
export const _internals = { _normalizeGraph, SERVICES_FILE_NAMES, _pathTemplateMatches, _escapeRegex, validateBoundaryContract };
|