@clear-capabilities/agentic-security-scanner 0.195.26 → 0.195.28
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 +27 -0
- package/bin/agentic-security.js +39 -7
- package/dist/396.index.js +936 -0
- package/dist/{60f58f89664e53fc2f96.json → 3eabd90d6d9c8c8dbbd9.json} +4 -3
- package/dist/5856.index.js +634 -0
- package/dist/7033.index.js +74 -14
- package/dist/7838.index.js +22 -0
- package/dist/9220.index.js +24 -1
- package/dist/agentic-security.mjs +9 -9
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/package.json +4 -3
- package/src/dataflow/catalog.js +42 -1
- package/src/engine.js +90 -10
- package/src/language/CLAUDE.md +6 -0
- package/src/language/assurance.js +53 -2
- package/src/language/haskell-budget-state.js +85 -0
- package/src/language/haskell-coverage.js +230 -0
- package/src/language/haskell-project-models.js +107 -0
- package/src/language/nix-eval-isolation.js +74 -14
- package/src/llm-validator/bounded-context.js +87 -0
- package/src/llm-validator/claim-groups.js +105 -0
- package/src/llm-validator/disposition.js +264 -0
- package/src/llm-validator/index.js +52 -26
- package/src/pipeline/evidence-record.js +112 -0
- package/src/pipeline/scan-health.js +12 -1
- package/src/posture/CLAUDE.md +10 -2
- package/src/posture/artifact-registry.js +2 -0
- package/src/posture/custom-rules.js +7 -2
- package/src/posture/drift.js +19 -1
- package/src/posture/provenance/coordinator.js +6 -2
- package/src/posture/provenance/dag-walk.js +7 -3
- package/src/posture/provenance/origin-resolver.js +16 -2
- package/src/posture/provenance/providers/github.js +6 -3
- package/src/posture/provenance/providers/gitlab.js +5 -3
- package/src/posture/reachability-filter.js +3 -3
- package/src/posture/rule-compiler/cli.js +76 -21
- package/src/posture/rule-compiler/negative-corpus.js +39 -0
- package/src/posture/rule-compiler/promotion.js +21 -0
- package/src/posture/rule-compiler/regression.js +39 -9
- package/src/posture/rule-compiler/store.js +72 -6
- package/src/posture/suppressions.js +21 -0
- package/src/posture/watch-mode.js +22 -1
- package/src/report/disposition-view.js +90 -0
- package/src/report/index.js +47 -0
- package/src/runScan.js +60 -6
- package/src/sast/oidc-trust.js +74 -0
- package/src/sast/pipeline.js +14 -1
- package/src/sast/workflow-flow.js +272 -0
- package/src/sca/basis.js +88 -0
- package/src/scope/flags.js +55 -0
- package/src/scope/inventory.js +241 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
d61dba15693817b199249d076741a3dd1e3dff5f70f8c37b6c39fb9b20e2744c agentic-security.mjs
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clear-capabilities/agentic-security-scanner",
|
|
3
|
-
"version": "0.195.
|
|
3
|
+
"version": "0.195.28",
|
|
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",
|
|
@@ -82,18 +82,19 @@
|
|
|
82
82
|
"test:loop": "node --test --test-concurrency=3 ../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
84
|
"bench:dag-incremental": "node ../bench/dag-incremental/run.mjs",
|
|
85
|
+
"bench:haskell-core-families": "node ../bench/haskell-core-families/runner.mjs",
|
|
85
86
|
"test:smoke": "node --test test/smoke.test.js test/demo-app.test.js",
|
|
86
87
|
"test:ollama-e2e": "AGENTIC_SECURITY_OLLAMA_E2E=1 node --test test/ollama-e2e.test.js",
|
|
87
88
|
"test:glob": "node --test test/glob-compat.test.js",
|
|
88
89
|
"test:sast": "node --test test/dag-precision.test.js test/cpp-hardcoded-secret.test.js test/sibling-guard.test.js test/comment-blindness.test.js test/todo-marker-words.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/vendor-java-parser-current.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",
|
|
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-transport.test.js test/local-preset-callers.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/api-contract-scope.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/accounting.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/proof-fabric/generate-haskell.test.js test/proof-fabric/generate-haskell-widened.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/gates.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:posture": "node --test test/contracts/finding-provenance.contract.test.js 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-transport.test.js test/local-preset-callers.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/scope/inventory.test.js test/scope/readtree-scope.test.js test/scope/cli-scope.test.js test/scope/watch-scope.test.js test/workflow-flow.test.js test/oidc-trust.test.js test/haskell-coverage/coverage.test.js test/validation-disposition.test.js test/claim-groups.test.js test/validation-bounded-context.test.js test/evidence-record.test.js test/report-disposition-view.test.js test/sca-basis.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/api-contract-scope.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/accounting.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/proof-fabric/generate-haskell.test.js test/proof-fabric/generate-haskell-widened.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/gates.test.js test/rule-compiler/ci-regression.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
91
|
"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 test/ir-cache.test.js test/canonicalize-parity.test.js test/dataflow-source-attribution.test.js",
|
|
91
92
|
"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",
|
|
92
93
|
"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/git-history-batch.test.js test/default-scan-drift.test.js test/bundle-optional-deps.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",
|
|
93
94
|
"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/seeding-across-calls.test.js test/lineage/boundary-join.test.js test/contracts/code-boundaries.contract.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 test/lineage/smt-z3-backend.test.js test/cli/dag-commands.test.js",
|
|
94
95
|
"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",
|
|
95
96
|
"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",
|
|
96
|
-
"test:haskell": "node --test test/haskell/haskell-reachability.test.js test/haskell/haskell-real-code-shapes.test.js test/haskell/haskell-unseen-v5-shapes.test.js test/haskell/haskell-unseen-v4-shapes.test.js test/haskell/haskell-alias-taint.test.js 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-remediation-0190.test.js test/haskell/haskell-remediation-kdf.test.js test/haskell/haskell-remediation-html-text.test.js test/haskell/haskell-remediation-scotty-body.test.js test/haskell/haskell-remediation-entropy.test.js test/haskell/haskell-remediation-text-command.test.js test/haskell/haskell-remediation-path-contain.test.js test/haskell/haskell-remediation-0195-16.test.js test/haskell/haskell-taint-shapes.test.js test/haskell/haskell-real-advisory-shapes.test.js test/haskell/haskell-discovery-shapes.test.js test/haskell/haskell-quasiquote-interp.test.js test/haskell/haskell-record-dot.test.js test/haskell/haskell-global-cell.test.js test/haskell/haskell-syntax-extensions.test.js test/haskell/haskell-rule-precision.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 test/haskell/haskell-generalization.test.js test/haskell/haskell-trust-boundary.test.js test/haskell/haskell-trust-fixed-file.test.js test/haskell/haskell-predictable-random-flow.test.js test/haskell/haskell-comment-invariance.test.js test/haskell/haskell-remediation-classes.test.js test/haskell/haskell-trust-boundary-frameworks.test.js test/haskell/haskell-generic-detectors.test.js",
|
|
97
|
+
"test:haskell": "node --test test/haskell/haskell-core-families-runner.test.js test/haskell/haskell-project-models.test.js test/haskell/haskell-reachability.test.js test/haskell/haskell-real-code-shapes.test.js test/haskell/haskell-unseen-v5-shapes.test.js test/haskell/haskell-unseen-v4-shapes.test.js test/haskell/haskell-alias-taint.test.js 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-remediation-0190.test.js test/haskell/haskell-remediation-kdf.test.js test/haskell/haskell-remediation-html-text.test.js test/haskell/haskell-remediation-scotty-body.test.js test/haskell/haskell-remediation-entropy.test.js test/haskell/haskell-remediation-text-command.test.js test/haskell/haskell-remediation-path-contain.test.js test/haskell/haskell-remediation-0195-16.test.js test/haskell/haskell-taint-shapes.test.js test/haskell/haskell-real-advisory-shapes.test.js test/haskell/haskell-discovery-shapes.test.js test/haskell/haskell-quasiquote-interp.test.js test/haskell/haskell-record-dot.test.js test/haskell/haskell-global-cell.test.js test/haskell/haskell-syntax-extensions.test.js test/haskell/haskell-rule-precision.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 test/haskell/haskell-generalization.test.js test/haskell/haskell-trust-boundary.test.js test/haskell/haskell-trust-fixed-file.test.js test/haskell/haskell-predictable-random-flow.test.js test/haskell/haskell-comment-invariance.test.js test/haskell/haskell-remediation-classes.test.js test/haskell/haskell-trust-boundary-frameworks.test.js test/haskell/haskell-generic-detectors.test.js",
|
|
97
98
|
"test:nix": "node --test test/nix/nix-option-types.test.js test/nix/nix-development-shapes.test.js 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",
|
|
98
99
|
"test:language": "node --test test/bench-haskell-precision.test.js test/bench-independent-haskell-panel.test.js 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/frozen-splits.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-parity-haskell.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",
|
|
99
100
|
"test:language-stress": "node --test --test-concurrency=1 test/language/language-stress-offline.test.js",
|
package/src/dataflow/catalog.js
CHANGED
|
@@ -2194,6 +2194,7 @@ export const CATALOG = [
|
|
|
2194
2194
|
// ~450 additional entries across JS / Python / Java / Ruby / PHP / Go.
|
|
2195
2195
|
// Lives in catalog-expanded.js to keep the diff reviewable. Merged into
|
|
2196
2196
|
// the main CATALOG below so the indexer treats them identically.
|
|
2197
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2197
2198
|
import { EXPANDED_SANITIZERS } from './catalog-expanded.js';
|
|
2198
2199
|
import { HASKELL_CATALOG } from './catalog-haskell.js';
|
|
2199
2200
|
import { cppExtRe } from '../ir/parser-cpp.js';
|
|
@@ -2490,7 +2491,12 @@ let _lastMode = null;
|
|
|
2490
2491
|
const _filterCache = new WeakMap();
|
|
2491
2492
|
function filterByProvenance(entries) {
|
|
2492
2493
|
const mode = isOfficialOnlyMode();
|
|
2493
|
-
if (!mode)
|
|
2494
|
+
if (!mode) {
|
|
2495
|
+
// Project-declared entries belong to the scan that registered them (see scanOwner); another scan in the same process never matches them.
|
|
2496
|
+
if (_PROJECT_ENTRIES.size === 0) return entries;
|
|
2497
|
+
const me = scanOwner.getStore();
|
|
2498
|
+
return entries.some((e) => e.source === 'project' && e.owner !== me) ? entries.filter((e) => e.source !== 'project' || e.owner === me) : entries;
|
|
2499
|
+
}
|
|
2494
2500
|
if (mode !== _lastMode) {
|
|
2495
2501
|
_modeGeneration++;
|
|
2496
2502
|
_lastMode = mode;
|
|
@@ -2759,3 +2765,38 @@ export function matchAnnotationParamSources(paramAnnotations, file) {
|
|
|
2759
2765
|
|
|
2760
2766
|
// For tests and reflection.
|
|
2761
2767
|
export function _catalogSize() { return CATALOG.length; }
|
|
2768
|
+
|
|
2769
|
+
// Project-declared models (PRD FR 03). Registered for the duration of one scan and removed afterwards, so a project's own wrapper
|
|
2770
|
+
// declarations never become part of the shipped catalog. Entries are tagged `source: 'project'`, which the official-only mode excludes.
|
|
2771
|
+
const _PROJECT_ENTRIES = new Map();
|
|
2772
|
+
export const scanOwner = new AsyncLocalStorage();
|
|
2773
|
+
export function registerProjectCatalogEntries(owner, entries) {
|
|
2774
|
+
unregisterProjectCatalogEntries(owner);
|
|
2775
|
+
const added = [];
|
|
2776
|
+
for (const e of entries || []) {
|
|
2777
|
+
if (!e || !e.match || e.match.type !== 'call' || !e.match.callee) continue;
|
|
2778
|
+
const entry = { ...e, source: 'project', owner };
|
|
2779
|
+
CATALOG.push(entry);
|
|
2780
|
+
const k = entry.match.callee;
|
|
2781
|
+
if (!CALLEE_INDEX.has(k)) CALLEE_INDEX.set(k, []);
|
|
2782
|
+
CALLEE_INDEX.get(k).push(entry);
|
|
2783
|
+
added.push(entry);
|
|
2784
|
+
}
|
|
2785
|
+
_PROJECT_ENTRIES.set(owner, added);
|
|
2786
|
+
return added.length;
|
|
2787
|
+
}
|
|
2788
|
+
export function unregisterProjectCatalogEntries(owner) {
|
|
2789
|
+
const added = _PROJECT_ENTRIES.get(owner);
|
|
2790
|
+
if (!added) return;
|
|
2791
|
+
for (const e of added) {
|
|
2792
|
+
const i = CATALOG.indexOf(e);
|
|
2793
|
+
if (i >= 0) CATALOG.splice(i, 1);
|
|
2794
|
+
const list = CALLEE_INDEX.get(e.match.callee);
|
|
2795
|
+
if (list) {
|
|
2796
|
+
const j = list.indexOf(e);
|
|
2797
|
+
if (j >= 0) list.splice(j, 1);
|
|
2798
|
+
if (!list.length) CALLEE_INDEX.delete(e.match.callee);
|
|
2799
|
+
}
|
|
2800
|
+
}
|
|
2801
|
+
_PROJECT_ENTRIES.delete(owner);
|
|
2802
|
+
}
|
package/src/engine.js
CHANGED
|
@@ -199,6 +199,13 @@ import { demoteUnreachable } from './posture/reachability-filter.js';
|
|
|
199
199
|
import { annotateExploitability, detectProjectContext } from './posture/exploitability.js';
|
|
200
200
|
import { applyFeedback as applyLearnedFeedback } from './posture/learning.js';
|
|
201
201
|
import { validateMany as llmValidateMany, applyValidatorVerdicts } from './llm-validator/index.js';
|
|
202
|
+
import { applyDispositions, assignDisposition } from './llm-validator/disposition.js';
|
|
203
|
+
import { groupEquivalentClaims, reconcileCounts } from './llm-validator/claim-groups.js';
|
|
204
|
+
import { annotateScaBasis, dedupeAdvisoryAliases } from './sca/basis.js';
|
|
205
|
+
import { applyOidcTrust, resolveOwnRepository } from './sast/oidc-trust.js';
|
|
206
|
+
import { readProjectModelFile, loadProjectModels, projectFileExists } from './language/haskell-project-models.js';
|
|
207
|
+
import { parseBudgetOverrides as parseHaskellBudgetOverrides } from './language/haskell-budget-state.js';
|
|
208
|
+
import { registerProjectCatalogEntries, unregisterProjectCatalogEntries, scanOwner } from './dataflow/catalog.js';
|
|
202
209
|
import { MODEL_STATUS, stageSummaryFromModelStatus } from './llm-validator/model-status.js';
|
|
203
210
|
import { resolveProvider as resolveLlmProvider, otherRemoteRoles as llmOtherRemoteRoles, NO_CLOUD_FALLBACK } from './llm-validator/providers.js';
|
|
204
211
|
import { scanCrossLangOpenAPI } from './posture/cross-lang-openapi.js';
|
|
@@ -784,6 +791,7 @@ function _isIaCFile(p){
|
|
|
784
791
|
// `isKubernetesManifest` below, because a path predicate cannot see content.
|
|
785
792
|
if (/(?:^|\/)k8s(?:\/|$)/.test(p) && /\.ya?ml$/i.test(base)) return true;
|
|
786
793
|
if (/(?:^|\/)\.github\/workflows\/.*\.ya?ml$/.test(p)) return true;
|
|
794
|
+
if (/(?:^|\/)\.github\/actions\/.*\.ya?ml$/.test(p)) return true; // composite actions kept in the repository
|
|
787
795
|
if (/(?:^|\/)\.gitlab-ci\.ya?ml$/.test(p)) return true;
|
|
788
796
|
if (/(?:^|\/)values\.ya?ml$/.test(p)) return true;
|
|
789
797
|
// MCP server config files (Claude Code agent host configuration)
|
|
@@ -846,7 +854,9 @@ export function isInstructionFile(relPath) {
|
|
|
846
854
|
return typeof relPath === 'string' && _INSTRUCTION_FILE_ADMIT_RE.test(relPath);
|
|
847
855
|
}
|
|
848
856
|
|
|
849
|
-
|
|
857
|
+
// `scoped` (PRD FR 01): the Git-aware inventory already decided eligibility, so a tracked file is not dropped merely because its
|
|
858
|
+
// folder is named test, bin or vendor, or because its name looks like a test. Minified bundles are still not source.
|
|
859
|
+
function shouldScan(p,scoped=false){if(/\.min\.[mc]?js$/i.test(p))return false;if(!scoped){if(/\.(test|spec|mock)\./i.test(p))return false;if(/_test\.go$/i.test(p))return false;if(/_spec\.rb$/i.test(p))return false;if(/Test\.(?:java|cs|kt|scala)$/i.test(p))return false;for(const x of p.split("/"))if(IGNORE_DIRS.has(x))return false;}else{for(const x of p.split("/"))if(x==="node_modules"||x===".git"||x===".agentic-security")return false;}
|
|
850
860
|
// Mobile + framework manifest files needed by the v4 detectors.
|
|
851
861
|
const base=p.split('/').pop();
|
|
852
862
|
if (/(?:^|[\\/])AndroidManifest\.xml$/i.test(p)) return true;
|
|
@@ -6308,17 +6318,27 @@ const _SECURITY_WORD_RE=/\b(?:auth|authn|authz|authenticat(?:e|ed|es|ion|or)|aut
|
|
|
6308
6318
|
function _splitIdentifierWords(text){
|
|
6309
6319
|
return text.replace(/([a-z0-9])([A-Z])/g,"$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g,"$1 $2").replace(/[_\-.]+/g," ");
|
|
6310
6320
|
}
|
|
6321
|
+
// PRD FR 07: a marker is a developer note only when it sits in comment text, either as the first word of the comment or written as a
|
|
6322
|
+
// label (`XXX:`, `FIXME(name)`). A Roman numeral or prose word that happens to read XXX, or a marker inside a string, is not a note.
|
|
6323
|
+
function _isMarkerComment(ln){
|
|
6324
|
+
const m=/(?:\/\/+|#+|--+|\/\*+|^\s*\*+|;+|%+|<!--)\s*(.*)$/.exec(ln);
|
|
6325
|
+
if(!m)return false;
|
|
6326
|
+
const text=m[1];
|
|
6327
|
+
return /^(?:TODO|FIXME|HACK|XXX|BUG|TEMP)\b/.test(text)||/\b(?:TODO|FIXME|HACK|XXX|BUG|TEMP)(?::|\()/.test(text);
|
|
6328
|
+
}
|
|
6311
6329
|
function scanTodosNearSecurity(fp,raw){
|
|
6312
6330
|
const lines=raw.split("\n");
|
|
6313
6331
|
const out=[];
|
|
6314
6332
|
for(let i=0;i<lines.length;i++){
|
|
6315
6333
|
const ln=lines[i];
|
|
6316
|
-
if(
|
|
6334
|
+
if(!_isMarkerComment(ln))continue;
|
|
6317
6335
|
const window=lines.slice(Math.max(0,i-3),Math.min(lines.length,i+4)).join(" ");
|
|
6318
6336
|
if(!_SECURITY_WORD_RE.test(_splitIdentifierWords(window)))continue;
|
|
6319
6337
|
out.push({
|
|
6320
6338
|
vuln:"Known-Broken Code Marker Near Security-Sensitive Logic",
|
|
6321
|
-
|
|
6339
|
+
// A developer note is a code-quality note, not a vulnerability, unless it is tied to a present weakness (PRD FR 07).
|
|
6340
|
+
kind:"hardening",hardeningAdvice:true,
|
|
6341
|
+
severity:"low",cwe:"CWE-1077",stride:"Tampering",
|
|
6322
6342
|
fix:"Review the TODO/FIXME. Known-broken comments next to auth/crypto code often indicate unfinished hardening.",
|
|
6323
6343
|
code:`// File: ${fp}:${i+1}\n// ${ln.trim()}`,
|
|
6324
6344
|
file:fp,line:i+1,snippet:ln.trim()
|
|
@@ -8562,6 +8582,9 @@ async function queryOSV(components,allFileContents){
|
|
|
8562
8582
|
fixedVersions: [...fixedVersions].sort(),
|
|
8563
8583
|
aliases: (d.aliases || []).filter(a => a.startsWith('CVE-')),
|
|
8564
8584
|
osvVulnFunctions: [...new Set(osvVulnFunctions)],
|
|
8585
|
+
// PRD FR 08: the advisory's own timestamps and affected ranges, so a finding can say what it matched and when that was published.
|
|
8586
|
+
advisoryModified: d.modified || null, advisoryPublished: d.published || null,
|
|
8587
|
+
affectedRanges: (d.affected || []).flatMap((aff) => (aff.ranges || []).map((r) => ({ type: r.type, events: (r.events || []).map((ev) => ({ ...ev })) }))),
|
|
8565
8588
|
severity, cvssVector, hasKnownAttackRef };
|
|
8566
8589
|
_osvCacheSet('vuln:' + vid, vuln);
|
|
8567
8590
|
return [vid, vuln];
|
|
@@ -8582,6 +8605,7 @@ async function queryOSV(components,allFileContents){
|
|
|
8582
8605
|
results.push({ type: 'vulnerable_dep', name: comp.name, version: comp.version, ecosystem: comp.ecosystem,
|
|
8583
8606
|
purl: comp.purl, osvId: vid, cveAliases: vuln.aliases, description: vuln.description,
|
|
8584
8607
|
fixedVersions: vuln.fixedVersions, severity: vuln.severity, cvssVector: vuln.cvssVector,
|
|
8608
|
+
advisoryModified: vuln.advisoryModified || null, advisoryPublished: vuln.advisoryPublished || null, affectedRanges: vuln.affectedRanges || null,
|
|
8585
8609
|
hasKnownAttackRef: vuln.hasKnownAttackRef, osvVulnFunctions: vuln.osvVulnFunctions || [], reachable: comp.reachable, scope: comp.scope,
|
|
8586
8610
|
file: comp.filePath,
|
|
8587
8611
|
// `isDirect` is backfilled onto every component just above the queryOSV
|
|
@@ -8971,7 +8995,7 @@ function _gcHint(minHeapMiB) {
|
|
|
8971
8995
|
_gcFn();
|
|
8972
8996
|
}
|
|
8973
8997
|
|
|
8974
|
-
async function
|
|
8998
|
+
async function _runFullScanBody({fileContents={}, depFileContents={}, scanRoot=null, resume=undefined, deep=undefined, deepInCi=undefined, provenance=true, completeScan=true, skipAnnotators=false, policyExcluded=[], sizeSkipped=[], haskellSourceMap=null, gitScope=false}, setProgress=()=>{}){
|
|
8975
8999
|
// E6-01: local, aggregate telemetry for this scan (see pipeline/telemetry.js). Nothing is sent anywhere; the snapshot is a field of the result.
|
|
8976
9000
|
const _tel = createTelemetry({ deterministic: isDeterministic() });
|
|
8977
9001
|
setDetectorTimingSink((name, ms) => _tel.detector(name, ms));
|
|
@@ -8979,6 +9003,14 @@ async function runFullScan({fileContents={}, depFileContents={}, scanRoot=null,
|
|
|
8979
9003
|
// The feed metadata is module state: reset it so one scan cannot inherit another's catalog freshness in the same process (0.195.22).
|
|
8980
9004
|
_kevCatalogMeta = { source: 'not-loaded', fetchedAt: null, ageDays: null, stale: null, entries: 0 };
|
|
8981
9005
|
_epssLiveMeta = { source: 'not-loaded', ageDays: null, stale: null, cvesChecked: 0 };
|
|
9006
|
+
// PRD FR 03: reviewed project models for Haskell wrappers. Registered for this scan only; a model without provenance or paired tests is rejected and reported.
|
|
9007
|
+
let _projectModels = { present: false, accepted: [], rejected: [], catalog: [] };
|
|
9008
|
+
try {
|
|
9009
|
+
if (scanRoot) {
|
|
9010
|
+
_projectModels = loadProjectModels(readProjectModelFile(scanRoot), projectFileExists(scanRoot));
|
|
9011
|
+
if (_projectModels.catalog.length) registerProjectCatalogEntries(scanRoot, _projectModels.catalog);
|
|
9012
|
+
}
|
|
9013
|
+
} catch (e) { _projectModels = { present: true, accepted: [], rejected: [{ id: '(file)', reason: String((e && e.message) || e) }], catalog: [] }; }
|
|
8982
9014
|
_resetSuppressions();_tel.time('index', () => _buildProjectIndex(fileContents));await _tel.timeAsync('custom-rules', () => _loadCustomRules(scanRoot));
|
|
8983
9015
|
// Pre-pass: build cross-file Java tainted-method index so per-file taint
|
|
8984
9016
|
// analysis can recognize calls to user-input-returning helper methods
|
|
@@ -9006,7 +9038,7 @@ function _deterministicFileTimings(timings) {
|
|
|
9006
9038
|
|
|
9007
9039
|
const _fileTimings = [];
|
|
9008
9040
|
let _filesSkipped = 0, _filesTimedOut = 0, _filesDenseSkipped = 0, _filesOversizeSkipped = 0;
|
|
9009
|
-
const files=Object.keys(fileContents).filter(f=>(shouldScan(f) || isKubernetesManifest(f, fileContents[f]) || isCloudFormationTemplate(f, fileContents[f]) || isInstructionFile(f)) && !_isPathIgnored(f));const fc={},pfr={};const aR=[],aF=[],aSrc=[],aSink=[],aSan=[],aLogic=[],aSupply=[],aSecrets=[],aCiphersRest=[],aCiphersTransit=[];const _detectorErrors=[];
|
|
9041
|
+
const files=Object.keys(fileContents).filter(f=>(shouldScan(f,gitScope) || isKubernetesManifest(f, fileContents[f]) || isCloudFormationTemplate(f, fileContents[f]) || isInstructionFile(f)) && !_isPathIgnored(f));const fc={},pfr={};const aR=[],aF=[],aSrc=[],aSink=[],aSan=[],aLogic=[],aSupply=[],aSecrets=[],aCiphersRest=[],aCiphersTransit=[];const _detectorErrors=[];
|
|
9010
9042
|
// ---- R8: opt-in per-file checkpointing (AGENTIC_SECURITY_RESUME=1, or
|
|
9011
9043
|
// runScan({resume:true})). Default OFF, so existing behaviour is untouched.
|
|
9012
9044
|
// Only this loop is checkpointed; every cross-file pass below re-runs, so
|
|
@@ -9405,7 +9437,6 @@ function _deterministicFileTimings(timings) {
|
|
|
9405
9437
|
} else {
|
|
9406
9438
|
sc.reachabilityTier = 'transitive-only';
|
|
9407
9439
|
}
|
|
9408
|
-
if (sc.reachabilityTier === 'transitive-only') { sc.unreachable = true; sc._reachabilityDemoted = true; }
|
|
9409
9440
|
// Mark as the strongest "vulnerable function actually invoked" signal so
|
|
9410
9441
|
// posture/reachability-filter can preserve full severity on this tier
|
|
9411
9442
|
// while demoting lower tiers.
|
|
@@ -9413,6 +9444,8 @@ function _deterministicFileTimings(timings) {
|
|
|
9413
9444
|
sc.routeReachableViaFunction = true;
|
|
9414
9445
|
}
|
|
9415
9446
|
}
|
|
9447
|
+
// PRD FR 08: record the basis of every dependency finding, kept apart from reachability.
|
|
9448
|
+
try { const _merged = dedupeAdvisoryAliases(supplyChain); supplyChain.length = 0; supplyChain.push(..._merged); annotateScaBasis(supplyChain); } catch (_) {}
|
|
9416
9449
|
// Early dedup: collapse duplicates BEFORE the annotation pipeline to reduce work.
|
|
9417
9450
|
try{const _earlyMap=new Map();for(const f of aF){const k=`${f.file||''}:${f.line||0}:${f.vuln||''}`;if(!_earlyMap.has(k))_earlyMap.set(k,f);}aF.length=0;aF.push(..._earlyMap.values());}catch(_){}
|
|
9418
9451
|
// Sort findings: critical first, then structural patterns last within same severity
|
|
@@ -9881,12 +9914,14 @@ function _deterministicFileTimings(timings) {
|
|
|
9881
9914
|
// An `unsafePerformIO` / `unsafeCoerce` / `unsafeInterleaveIO` boundary note says (in its own text) that it claims no vulnerability class: it marks where the
|
|
9882
9915
|
// type system is stepped around. In a scan it is information, not a finding that gates a release; the rules module keeps emitting it at `low` (its contract),
|
|
9883
9916
|
// and the severity is lowered here with the original kept.
|
|
9884
|
-
|
|
9885
|
-
|
|
9917
|
+
// FR 02: which Haskell rule families really executed (a thrown family is recorded as failed, never as clean).
|
|
9918
|
+
const _hsRuleRuns={};
|
|
9919
|
+
try{const _r=analyzeHaskellRules(fc,{reachability:_hsReachCtx()}).findings.map((f)=>f&&f.rule==='hs-unsafe-io-boundary'?{...f,originalSeverity:f.severity,severity:'info'}:f);aF.push(..._r);_hsRuleRuns['hs-security-rules']={ran:true,findings:_r.length};}catch(e){_hsRuleRuns['hs-security-rules']={ran:false,failed:String((e&&e.message)||e).slice(0,120)};}
|
|
9920
|
+
try{const _r=analyzeHaskellLlmRules(fc);aF.push(..._r);_hsRuleRuns['hs-llm']={ran:true,findings:_r.length};}catch(e){_hsRuleRuns['hs-llm']={ran:false,failed:String((e&&e.message)||e).slice(0,120)};}
|
|
9886
9921
|
try{const{analyzeLanguageFindings}=await import('./language/engine-pass.js');aF.push(...analyzeLanguageFindings(allFileContents).findings);}catch(_){}
|
|
9887
9922
|
let _languageBridges=null;try{if(Object.keys(allFileContents).some(f=>/\.(?:l?hs|nix)$/i.test(f))){const{analyzePolyglotBridges}=await import('./language/bridges.js');_languageBridges=analyzePolyglotBridges(allFileContents);}}catch(_){}
|
|
9888
9923
|
try{for(const[_p,_t]of Object.entries(allFileContents))if(typeof _t==='string')aF.push(...scanDependencyUrlCredentials(_p,_t));}catch(_){}
|
|
9889
|
-
try{const _hw=analyzeHaskellWeb(fc,{reachability:_hsReachCtx()});aF.push(..._hw.findings);aR.push(...toEngineRoutes(_hw));}catch(
|
|
9924
|
+
try{const _hw=analyzeHaskellWeb(fc,{reachability:_hsReachCtx()});aF.push(..._hw.findings);aR.push(...toEngineRoutes(_hw));_hsRuleRuns['hs-web']={ran:true,findings:_hw.findings.length};}catch(e){_hsRuleRuns['hs-web']={ran:false,failed:String((e&&e.message)||e).slice(0,120)};}
|
|
9890
9925
|
let finalFindings;try{finalFindings=dedupeFindingsWithEvidence(aF);}catch(_){finalFindings=dd(aF,f=>f.id);}
|
|
9891
9926
|
// Inline `agentic-security-ignore` pragmas, pass 1 of 2. This covers every
|
|
9892
9927
|
// finding that exists BY THIS POINT — the pattern detectors, the cross-file
|
|
@@ -10037,6 +10072,9 @@ function _deterministicFileTimings(timings) {
|
|
|
10037
10072
|
_licenseGraph = null, _attributions = null, _taxonomySummary = null;
|
|
10038
10073
|
let _scanMeta = null;
|
|
10039
10074
|
let _aiAssistance = null;
|
|
10075
|
+
let _dispositionCounts = null;
|
|
10076
|
+
let _groupedClaims = [];
|
|
10077
|
+
let _candidateReconciliation = null;
|
|
10040
10078
|
let _entrypointInventory = {};
|
|
10041
10079
|
let _rootCauseSweep = null;
|
|
10042
10080
|
let _proofCoverage = null;
|
|
@@ -10520,6 +10558,31 @@ function _deterministicFileTimings(timings) {
|
|
|
10520
10558
|
// upstream of it still need to run before validation, same as before).
|
|
10521
10559
|
try { annotateVerifierVerdicts(finalFindings, { fileContents: fc }); } catch (_) {}
|
|
10522
10560
|
} catch(_) {}
|
|
10561
|
+
// PRD FR 06: trust-policy evidence kept in the repository adjusts OIDC findings; absence there never closes one.
|
|
10562
|
+
try { const _own = finalFindings.some((x) => x && /^Pipeline: OIDC id-token: write/.test(String(x.vuln || ''))) ? resolveOwnRepository(scanRoot) : null; applyOidcTrust(finalFindings, depFileContents && Object.keys(depFileContents).length ? { ...allFileContents, ...depFileContents } : allFileContents, _own ? { ownRepository: _own.name, ownRepositoryBasis: _own.basis } : {}); } catch (e) { _annotatorErrors.push({ phase: 'applyOidcTrust', err: String((e && e.message) || e) }); }
|
|
10563
|
+
// PRD FR 05: final disposition. Runs whether or not a model was configured,
|
|
10564
|
+
// so every actionable finding says why it is confirmed, needs review,
|
|
10565
|
+
// hardening, refuted or unvalidated. Only an evidence-backed refutation or a
|
|
10566
|
+
// reviewed suppression leaves the list, and it is retained in the ledger.
|
|
10567
|
+
try {
|
|
10568
|
+
// Equivalent detector claims are grouped first (one weakness, one actionable result naming every detector); the grouped
|
|
10569
|
+
// claims are kept for the raw export, never deleted.
|
|
10570
|
+
const _suppressedBefore = _suppressionLog.length;
|
|
10571
|
+
const _raw = finalFindings.filter((x) => x && x.kind !== 'sca').length;
|
|
10572
|
+
const cg = groupEquivalentClaims(finalFindings);
|
|
10573
|
+
finalFindings = cg.kept;
|
|
10574
|
+
for (const g of cg.grouped) { try { assignDisposition(g, { fileContents: fc }); } catch (_) {} }
|
|
10575
|
+
_groupedClaims = cg.grouped;
|
|
10576
|
+
const dr = applyDispositions(finalFindings, { fileContents: fc });
|
|
10577
|
+
finalFindings = dr.kept;
|
|
10578
|
+
_dispositionCounts = dr.counts;
|
|
10579
|
+
_candidateReconciliation = reconcileCounts({ raw: _raw, grouped: cg.grouped.length, refuted: dr.refuted.length, dispositionCounts: dr.counts, suppressed: _suppressedBefore });
|
|
10580
|
+
for (const d of dr.refuted) _suppressionLog.push({
|
|
10581
|
+
vuln: d.vuln, file: d.file, line: d.line, snippet: d.snippet,
|
|
10582
|
+
reason: 'refuted:' + (d.dispositionDetail?.reason || '').slice(0, 80),
|
|
10583
|
+
disposition: d.disposition, dispositionDetail: d.dispositionDetail,
|
|
10584
|
+
});
|
|
10585
|
+
} catch (e) { _annotatorErrors.push({ phase: 'applyDispositions', err: String((e && e.message) || e) }); }
|
|
10523
10586
|
// Same ordering fix as annotateVerifierVerdicts above: annotateConfidence
|
|
10524
10587
|
// (~8111) computes f.confidence before f.unvalidated exists on any
|
|
10525
10588
|
// finding, so its 0.85x "LLM validator unavailable" penalty could never
|
|
@@ -11376,6 +11439,12 @@ function _deterministicFileTimings(timings) {
|
|
|
11376
11439
|
...(() => { const a = configuredAdvisoryDb(scanRoot); return { advisoryDb: a.db, advisoryReason: a.db ? null : a.reason }; })(),
|
|
11377
11440
|
policyExcluded,
|
|
11378
11441
|
sizeSkipped,
|
|
11442
|
+
deepEnabled: _deepEnabled,
|
|
11443
|
+
scanRoot,
|
|
11444
|
+
...(() => { const o = parseHaskellBudgetOverrides(env.AGENTIC_SECURITY_HASKELL_PARSE_BUDGETS); return { parseBudgets: o.budgets, parseBudgetRejected: o.rejected }; })(),
|
|
11445
|
+
projectModels: _projectModels,
|
|
11446
|
+
sourceMap: haskellSourceMap,
|
|
11447
|
+
ruleRuns: { ..._hsRuleRuns, 'ir-taint': { ran: _deepEnabled, findings: finalFindings.filter((f) => f && f.parser === 'IR-TAINT' && /\.l?hs$/i.test(f.file || '')).length }, 'hs-sca': { ran: true } },
|
|
11379
11448
|
supplyGaps: _languageSupplyGaps,
|
|
11380
11449
|
licenseUnavailable: ((_languageBom && _languageBom.components) || []).filter((c) => c && !c.license && !(Array.isArray(c.licenses) && c.licenses.length)).length,
|
|
11381
11450
|
optional: { 'nix-eval': { selected: env.AGENTIC_SECURITY_NIX_EVAL === '1', result: _nixEvalResult }, 'cabal-plan': { selected: false }, 'hackage-live': liveFeedOptionalState(env)},
|
|
@@ -11410,7 +11479,18 @@ function _deterministicFileTimings(timings) {
|
|
|
11410
11479
|
setDetectorTimingSink(null);
|
|
11411
11480
|
attributeErrors(_tel, { annotatorErrors: _annotatorErrors, detectorErrors: (typeof _detectorErrors !== 'undefined' ? _detectorErrors : []), deepFailure: _deepFailure, filesTimedOut: (_scanMeta && _scanMeta.filesTimedOut) || 0 });
|
|
11412
11481
|
_tel.set('files.scanned', (_scanMeta && _scanMeta.filesScanned) || 0); _tel.set('files.skipped', (_scanMeta && _scanMeta.filesSkipped) || 0);
|
|
11413
|
-
|
|
11482
|
+
try { unregisterProjectCatalogEntries(scanRoot); } catch (_) {}
|
|
11483
|
+
return{telemetry:_tel.snapshot(),entrypointInventory:_entrypointInventory,rootCauseSweep:_rootCauseSweep,proofCoverage:_proofCoverage,kevCatalog:kevCatalogMeta(),routes:dd(aR,r=>`${r.method}:${r.path}:${r.file}:${r.line}`),findings:finalFindings,sources:aSrc,sinks:aSink,sanitizers:aSan,filesScanned:files.length,linesScanned:Object.values(fc).reduce((_n,_c)=>_n+(typeof _c==='string'?_c.split("\n").length:0),0),crossFileCount:cf.length,logicVulns:aLogic,supplyChain,components:annotatedComponents,secrets:aSecrets,ciphers:{atRest:aCiphersRest,inTransit:aCiphersTransit},pfr,fc,depFileContents,suppressions:_getSuppressions(),...(_stageEvidenceOn()?{stageEvidence:{dedupe:[..._stageEvidence.dedupe],guard:[..._stageEvidence.guard]}}:{}),_v3,_scanMeta,_engineErrors:{cppDataflowParseErrors:_cppDataflowParseErrors.value},annotatorErrors:_annotatorErrors,detectorErrors:_detectorErrors,executionProof:_executionProofSummary,logicClaims:_logicClaims,vulnHistory:_vulnHistory,threatModel:_threatModel,privacyFramework:_privacyFramework,privacyIrBacked:_privacyIrBacked,privacyTaxonomyVersion:_privacyTaxonomyVersion,sbomDiff:_sbomDiff,complianceReport:_complianceReport,exploitBundles:_exploitBundles,pqcPlan:_pqcPlan,licenseGraph:_licenseGraph,attributions:_attributions,attackTaxonomy:_taxonomySummary,scanHealth:_scanHealth,coverageLedger:_coverageLedger,lineageGraph:_lineageGraph,lineageStatus:_lineageStatus,languageBridges:_languageBridges,languageBom:_languageBom,aiAssistance:_aiAssistance,dispositionCounts:_dispositionCounts,groupedClaims:_groupedClaims,candidateReconciliation:_candidateReconciliation};}
|
|
11484
|
+
|
|
11485
|
+
// A scan runs inside its own owner scope, so project-declared catalog entries registered for one root are matched only by the scan of that
|
|
11486
|
+
// root, even when scans overlap in one process, and are removed on every exit, including a thrown error.
|
|
11487
|
+
async function runFullScan(args = {}, setProgress) {
|
|
11488
|
+
const owner = args.scanRoot ?? null;
|
|
11489
|
+
return scanOwner.run(owner, async () => {
|
|
11490
|
+
try { return await _runFullScanBody(args, setProgress); }
|
|
11491
|
+
finally { try { unregisterProjectCatalogEntries(owner); } catch (_) {} }
|
|
11492
|
+
});
|
|
11493
|
+
}
|
|
11414
11494
|
|
|
11415
11495
|
// Post-aggregation classification: every source becomes "unsafe"|"safe"; every sink becomes "confirmed"|"safe".
|
|
11416
11496
|
// Orphans (no finding linkage) are bucketed by file-local heuristic so the UI shows binary states only.
|
package/src/language/CLAUDE.md
CHANGED
|
@@ -203,3 +203,9 @@ at the use site that shares one of the names disables the expansion (it stays th
|
|
|
203
203
|
the alias's call-graph edge is kept via `inlinedCalls`; arguments are lowered in the CALLER's module. Pinned both ways in
|
|
204
204
|
`test/haskell/haskell-alias-taint.test.js`. Haskell verdict-flip cases live in `bench/mutation/cases-haskell.mjs`; the 8
|
|
205
205
|
`bench/cve-replay/deep/hs-*-shape` entries are synthetic (self-authored, not from advisories).
|
|
206
|
+
|
|
207
|
+
## Project models for Haskell wrappers (PRD FR 03)
|
|
208
|
+
|
|
209
|
+
`haskell-project-models.js` loads `.agentic-security/haskell-models.json` (schema `haskell-project-models/1`). A model declares a source, sink or sanitizer by module and function name and is accepted only with provenance (reviewer, date, reason), an argument position for a sink, an explicit family list for a sanitizer (`*` is refused), and a paired positive and negative test file that exists inside the project. A rejected model is a scan-health condition and has no effect. Accepted models are registered into the taint catalog for one scan (`registerProjectCatalogEntries`, tagged `source: 'project'`) and removed when `runFullScan` returns or throws. Each scan runs in its own owner scope (`scanOwner`, an AsyncLocalStorage in `dataflow/catalog.js`), so overlapping scans of different roots in one process never match each other's project entries.
|
|
210
|
+
|
|
211
|
+
`haskell-budget-state.js` reads operator parse budgets from `AGENTIC_SECURITY_HASKELL_PARSE_BUDGETS` (`name=value,...`, parser budget names only; anything else is refused as a condition), and writes `.agentic-security/haskell-budget.json` with the effective budgets and every remaining file plus a content digest. The next scan reports `budget.sinceLast` (completed, still remaining on the same inputs, still remaining after a change, gone, newly remaining). It records work left; it does not resume, because the assurance pass parses every eligible file on every scan.
|
|
@@ -23,6 +23,10 @@ import { deriveCppContext } from './haskell-cpp.js';
|
|
|
23
23
|
import { createNixAdapter } from './nix-adapter.js';
|
|
24
24
|
import { analyzeHaskellManifests } from './haskell-manifests.js';
|
|
25
25
|
import { packageOfModule } from './haskell-models.js';
|
|
26
|
+
import { buildHaskellCoverage } from './haskell-coverage.js';
|
|
27
|
+
import { budgetRecord, loadBudgetState, saveBudgetState } from './haskell-budget-state.js';
|
|
28
|
+
import { DEFAULT_PARSE_BUDGETS } from './haskell-parser.js';
|
|
29
|
+
import { buildHaskellIR } from './haskell-ir.js';
|
|
26
30
|
|
|
27
31
|
export const ASSURANCE_VERSION = 'language-assurance/1';
|
|
28
32
|
|
|
@@ -75,7 +79,9 @@ export async function assessLanguageAssurance(input = {}) {
|
|
|
75
79
|
const DISCLOSED_KINDS = new Set(['cpp', 'ffi', 'th-safe-splice', 'quasiquote-inert']);
|
|
76
80
|
const disclosed = new Map(); // boundary kind -> {count, files:Set}
|
|
77
81
|
const projectModules = new Set(); const importedModules = new Map(); // module -> files
|
|
82
|
+
const parsesByFile = new Map();
|
|
78
83
|
const onParse = (file, parse) => {
|
|
84
|
+
parsesByFile.set(file, parse);
|
|
79
85
|
if (parse && parse.module && parse.module.name) projectModules.add(parse.module.name);
|
|
80
86
|
for (const i of (parse && parse.imports) || []) if (i && i.module) { const e = importedModules.get(i.module) || new Set(); e.add(file); importedModules.set(i.module, e); }
|
|
81
87
|
for (const b of (parse && parse.boundaries) || []) {
|
|
@@ -86,7 +92,7 @@ export async function assessLanguageAssurance(input = {}) {
|
|
|
86
92
|
disclosed.set(b.kind, e);
|
|
87
93
|
}
|
|
88
94
|
};
|
|
89
|
-
const adapters = input.adapters || [createHaskellAdapter({ onParse, cpp: deriveCppContext(files) }), createNixAdapter()];
|
|
95
|
+
const adapters = input.adapters || [createHaskellAdapter({ onParse, cpp: deriveCppContext(files), budgets: input.parseBudgets || undefined }), createNixAdapter()];
|
|
90
96
|
const run = await runLanguageAnalysis({ files, adapters, timeoutMs: input.timeoutMs || 0 });
|
|
91
97
|
const reconcile = reconcileLanguageLedger(run.ledger, files);
|
|
92
98
|
const base = languageHealth({ ledger: run.ledger, outcomes: run.outcomes });
|
|
@@ -136,6 +142,18 @@ export async function assessLanguageAssurance(input = {}) {
|
|
|
136
142
|
if (ociFiles.length) limitations.push({ kind: 'container-image-scan', files: ociFiles.sort(), note: 'Nix-built images and declared OCI services are analysed as configuration only: image layers and base-image vulnerabilities are NOT scanned' });
|
|
137
143
|
if (!reconcile.ok) conditions.push(`language ledger does not reconcile with the inputs: ${reconcile.errors[0]}`);
|
|
138
144
|
|
|
145
|
+
// Buck-built Haskell: its dependency graph is not resolved by this scanner, so version-based advisory matching has nothing to match.
|
|
146
|
+
// Stated as a coverage gap (PRD FR 08) rather than left looking like "no vulnerable dependencies".
|
|
147
|
+
const buckHaskell = Object.entries(files).filter(([f, t]) => /(?:^|\/)(?:BUCK|TARGETS)(?:\.v2)?$/.test(f) && typeof t === 'string' && /\bhaskell_(?:library|binary|test|ghci)\b|\bprebuilt_haskell_library\b/.test(t)).map(([f]) => f).sort();
|
|
148
|
+
if (present.has('haskell') && buckHaskell.length) conditions.push(`${buckHaskell.length} Buck target file(s) declare Haskell dependencies this scan does not resolve (${buckHaskell.slice(0, 3).join(', ')}): dependency advisories were not matched for them`);
|
|
149
|
+
|
|
150
|
+
// Declared project models (PRD FR 03): a rejected declaration means a wrapper the project meant to model is still opaque.
|
|
151
|
+
const pm = input.projectModels;
|
|
152
|
+
if (pm && pm.present) {
|
|
153
|
+
if (pm.rejected.length) conditions.push(`${pm.rejected.length} Haskell project model(s) were rejected and have no effect: ${pm.rejected.slice(0, 3).map((r) => `${r.id} (${r.reason})`).join('; ')}`);
|
|
154
|
+
if (pm.accepted.length) limitations.push({ kind: 'project-models', count: pm.accepted.length, ids: pm.accepted.map((m) => m.id).sort(), note: 'wrappers modelled by reviewed project declarations (.agentic-security/haskell-models.json); each carries provenance and a paired positive and negative test' });
|
|
155
|
+
}
|
|
156
|
+
|
|
139
157
|
// 2. manifests
|
|
140
158
|
if (manifests.length) {
|
|
141
159
|
let m = null;
|
|
@@ -188,6 +206,39 @@ export async function assessLanguageAssurance(input = {}) {
|
|
|
188
206
|
}
|
|
189
207
|
}
|
|
190
208
|
|
|
209
|
+
// 5b. Haskell coverage accounting (FR 02): per-file stages, rates against the eligible denominator, rule families executed.
|
|
210
|
+
let haskellCoverage = null;
|
|
211
|
+
if (present.has('haskell')) {
|
|
212
|
+
try {
|
|
213
|
+
let ir = null;
|
|
214
|
+
if (input.deepEnabled !== false) {
|
|
215
|
+
try { const hs = Object.fromEntries(Object.entries(files).filter(([f]) => /\.hs$/i.test(f))); if (Object.keys(hs).length) ir = buildHaskellIR(hs); } catch { ir = null; }
|
|
216
|
+
}
|
|
217
|
+
haskellCoverage = buildHaskellCoverage({
|
|
218
|
+
files, parses: parsesByFile, ir, deepEnabled: input.deepEnabled !== false && !disabled.has('haskell:taint'),
|
|
219
|
+
ruleRuns: input.ruleRuns || null, sizeSkipped: input.sizeSkipped, policyExcluded: input.policyExcluded,
|
|
220
|
+
excludedPaths: run.ledger.excludedFiles, sourceMap: input.sourceMap || null,
|
|
221
|
+
});
|
|
222
|
+
// Effective parse budgets, operator overrides that were refused, and the persisted record of work left (haskell-budget-state.js).
|
|
223
|
+
const b = haskellCoverage.budget;
|
|
224
|
+
b.budgets = { ...DEFAULT_PARSE_BUDGETS, ...(input.parseBudgets || {}) };
|
|
225
|
+
if (Array.isArray(input.parseBudgetRejected) && input.parseBudgetRejected.length) {
|
|
226
|
+
b.rejectedOverrides = input.parseBudgetRejected;
|
|
227
|
+
conditions.push(`Haskell parse budget override refused: ${input.parseBudgetRejected.map((r) => `${r.entry} (${r.reason})`).join('; ')}`);
|
|
228
|
+
}
|
|
229
|
+
const budgetOf = (file) => { const p = parsesByFile.get(file); return p && p.budget ? { budgetName: p.budget.name } : {}; };
|
|
230
|
+
const remainingAll = (b.remainingAll || []).map((r) => ({ ...r, ...budgetOf(r.file) }));
|
|
231
|
+
const previous = loadBudgetState(input.scanRoot);
|
|
232
|
+
const { record, sinceLast } = budgetRecord({ remaining: remainingAll, completedFiles: b.completedFiles, budgets: b.budgets, files, previous });
|
|
233
|
+
b.remaining = b.remaining.map((r) => ({ ...r, ...budgetOf(r.file) }));
|
|
234
|
+
b.sinceLast = sinceLast;
|
|
235
|
+
if (record.remainingFiles || previous) b.recorded = saveBudgetState(input.scanRoot, record);
|
|
236
|
+
// Only a measured shortfall is a condition. A parse-only form is a stated limitation, not a gap in what was asked.
|
|
237
|
+
for (const r of haskellCoverage.capability.reasons) if (!/deep analysis is disabled/.test(r)) conditions.push(`Haskell coverage: ${r}`);
|
|
238
|
+
for (const l of haskellCoverage.capability.limitations) limitations.push({ kind: 'haskell-parse-only', note: l });
|
|
239
|
+
} catch (e) { conditions.push(`Haskell coverage accounting failed: ${String((e && e.message) || e).slice(0, 160)}`); }
|
|
240
|
+
}
|
|
241
|
+
|
|
191
242
|
// 6. optional modes
|
|
192
243
|
const optionalModes = {};
|
|
193
244
|
for (const name of OPTIONAL_MODES) {
|
|
@@ -198,7 +249,7 @@ export async function assessLanguageAssurance(input = {}) {
|
|
|
198
249
|
|
|
199
250
|
return {
|
|
200
251
|
version: ASSURANCE_VERSION,
|
|
201
|
-
languageCoverage: { totals: base.totals, byKind, conditions, limitations, capabilities, optionalModes },
|
|
252
|
+
languageCoverage: { totals: base.totals, byKind, conditions, limitations, capabilities, optionalModes, ...(haskellCoverage ? { haskell: haskellCoverage } : {}) },
|
|
202
253
|
ledger: { reconciled: reconcile.ok, errors: reconcile.errors, byAnalyzer: run.ledger.byAnalyzer },
|
|
203
254
|
outcomes: run.outcomes,
|
|
204
255
|
retained: { findings: findings.length, findingsRef: findings },
|