@clear-capabilities/agentic-security-scanner 0.186.1 → 0.186.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -1
- package/bin/agentic-security.js +42 -17
- package/dist/1602.index.js +1063 -0
- package/dist/{ca62ee93079be4c24eee.json → 4d06c8944ae121d7085c.json} +3 -3
- package/dist/9560.index.js +1 -1
- package/dist/agentic-security.mjs +2 -2
- package/dist/agentic-security.mjs.sha256 +1 -1
- package/package.json +3 -3
- package/src/posture/proof-fabric/cli.js +1 -1
- package/src/posture/proof-fabric/container.js +2 -2
- package/src/posture/proof-fabric/generate-haskell.js +205 -0
- package/src/posture/proof-fabric/generate.js +6 -3
- package/src/posture/proof-fabric/reproducer.js +4 -2
- package/src/posture/proof-fabric/runner.js +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
38adcd8324aa7552b7bf61f5ac662fe383ed41f0bcf7f6eb2cad89de080a88c5 agentic-security.mjs
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clear-capabilities/agentic-security-scanner",
|
|
3
|
-
"version": "0.186.
|
|
3
|
+
"version": "0.186.2",
|
|
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",
|
|
@@ -86,10 +86,10 @@
|
|
|
86
86
|
"test:ollama-e2e": "AGENTIC_SECURITY_OLLAMA_E2E=1 node --test test/ollama-e2e.test.js",
|
|
87
87
|
"test:glob": "node --test test/glob-compat.test.js",
|
|
88
88
|
"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/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",
|
|
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",
|
|
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/proof-fabric/generate-haskell.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
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 test/ir-cache.test.js test/canonicalize-parity.test.js",
|
|
91
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",
|
|
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/git-history-batch.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: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
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 test/lineage/smt-z3-backend.test.js test/cli/dag-commands.test.js",
|
|
94
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",
|
|
95
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",
|
|
@@ -132,7 +132,7 @@ export async function cmdProof(args, root) {
|
|
|
132
132
|
function doctor(args) {
|
|
133
133
|
const tools = hostTools();
|
|
134
134
|
const rows = LANGUAGES.map((l) => ({ lang: l, ...languageSupport(l, tools) }));
|
|
135
|
-
const envs = ['javascript', 'python'].map((l) => ({ lang: l, ...selectEnvironment({ lang: l }) }));
|
|
135
|
+
const envs = ['javascript', 'python', 'haskell'].map((l) => ({ lang: l, ...selectEnvironment({ lang: l }) }));
|
|
136
136
|
if (args.flags.json) { console.log(JSON.stringify({ tools, languages: rows, environments: envs }, null, 2)); return 0; }
|
|
137
137
|
console.log('Proof fabric doctor');
|
|
138
138
|
for (const r of rows) console.log(` ${r.lang.padEnd(11)} ${r.supported ? 'supported' : `unsupported (${r.reason})`}`);
|
|
@@ -20,9 +20,9 @@ import { scrubEnv } from '../../sandbox/trust-domains.js';
|
|
|
20
20
|
export const CONTAINER_ROOT = '/work';
|
|
21
21
|
// the image's own toolchain directories matter: the Temurin image puts the JDK at /opt/java/openjdk/bin and sets it through ENV, which a
|
|
22
22
|
// bare PATH override throws away (found by the first run against a real engine: `javac: not found`)
|
|
23
|
-
const CONTAINER_PATH = '/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin';
|
|
23
|
+
const CONTAINER_PATH = '/opt/java/openjdk/bin:/opt/ghc/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin';
|
|
24
24
|
// the interpreter names inside the image; the host paths the runner uses locally mean nothing in there
|
|
25
|
-
export const CONTAINER_TOOLS = Object.freeze({ node: 'node', python: 'python3', java: 'java', javac: 'javac', cc: 'gcc', dotnet: 'dotnet' });
|
|
25
|
+
export const CONTAINER_TOOLS = Object.freeze({ node: 'node', python: 'python3', java: 'java', javac: 'javac', cc: 'gcc', dotnet: 'dotnet', ghc: 'ghc', runghc: 'runghc' });
|
|
26
26
|
|
|
27
27
|
export function containerArgs({ image, name, hostRoot, argv, env = {}, limits, user = null }) {
|
|
28
28
|
if (!image || !name || !hostRoot || !Array.isArray(argv) || !argv.length) throw new Error('container run needs image, name, root and argv');
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
// Reproducer generation for Haskell (PRD 1), the third language of `generate.js`. Same contract as JavaScript and Python: a
|
|
2
|
+
// DETERMINISTIC proposal built from the flagged file alone, then run through the ordinary runner, oracle, 3-of-3 repetition and
|
|
3
|
+
// independent replay. A generated reproducer is a proposal that execution either confirms or does not.
|
|
4
|
+
//
|
|
5
|
+
// The program is run by GHC's interpreter (`ghc -e`), not compiled. Why: it needs no C compiler and no linker (so no dependence on
|
|
6
|
+
// the platform's developer tools), it leaves no object files or binaries to account for, it starts in about half a second where a
|
|
7
|
+
// compile-then-run takes a second or more, and there is one process tree to confine instead of a build stage followed by a run
|
|
8
|
+
// stage. Interpreted bytecode calls the same installed libraries a compiled program would, so a shell string reaches the same
|
|
9
|
+
// `System.Process` either way. The tradeoff is stated, not hidden: a program whose behaviour depends on compiled code (FFI, an
|
|
10
|
+
// optimisation-sensitive race) is refused, and `-O` is never in play. A hand-written reproducer may still use `build`/`run` with
|
|
11
|
+
// `{{GHC}}` to compile; both paths run under the same sandbox, timeout and output cap.
|
|
12
|
+
//
|
|
13
|
+
// Two shapes, as in the other languages:
|
|
14
|
+
// script the file reads `getArgs`: it is run as `:main "<payload>"`, so the payload arrives as the first argument;
|
|
15
|
+
// function a top-level function around the flagged line that has a type signature of `String`/`FilePath` parameters and an `IO`
|
|
16
|
+
// result: `ghc -e 'fn "<payload>" ...'` loads the module with every top-level name in scope (the module need not export
|
|
17
|
+
// it) and calls it with the payload in every parameter.
|
|
18
|
+
//
|
|
19
|
+
// Only what the proof environment can load is accepted: the file's imports must be modules of the packages that ship with GHC (the
|
|
20
|
+
// global package database, read from the installed GHC) or other `.hs` files in the repository. A web framework, a database binding
|
|
21
|
+
// or any Hackage package is refused with the package named where it is known. Template Haskell, quasi-quotes, CPP, the foreign
|
|
22
|
+
// function interface and compiler-plugin options are refused too: they run code at load time, before the payload is involved.
|
|
23
|
+
//
|
|
24
|
+
// Classes: command injection (CWE-78) and path traversal by a write (CWE-22). SSRF (CWE-918) is refused for Haskell on purpose: no
|
|
25
|
+
// HTTP client ships with GHC, so a request-making program necessarily imports a package the stdlib-only rule already refuses, and
|
|
26
|
+
// nothing could be proven honestly. Nothing is executed on a refusal.
|
|
27
|
+
import fs from 'node:fs';
|
|
28
|
+
import path from 'node:path';
|
|
29
|
+
import { spawnSync } from 'node:child_process';
|
|
30
|
+
import { parseHaskell } from '../../language/haskell-parser.js';
|
|
31
|
+
import { validateReproducer } from './reproducer.js';
|
|
32
|
+
import { hostTools } from './runner.js';
|
|
33
|
+
|
|
34
|
+
const MAX_SOURCE = 256 * 1024;
|
|
35
|
+
const MAX_FILES = 8;
|
|
36
|
+
const fail = (reason, extra = {}) => ({ ok: false, reason, ...extra });
|
|
37
|
+
|
|
38
|
+
// Well-known packages that are NOT part of a GHC install, by module prefix, so a refusal can name the package to install.
|
|
39
|
+
const THIRD_PARTY = [
|
|
40
|
+
['Web.Scotty', 'scotty'], ['Network.Wai', 'wai'], ['Network.HTTP.Types', 'http-types'], ['Network.HTTP.Client', 'http-client'],
|
|
41
|
+
['Network.HTTP.Simple', 'http-conduit'], ['Network.HTTP.Conduit', 'http-conduit'], ['Network.Wreq', 'wreq'], ['Network.Socket', 'network'],
|
|
42
|
+
['Servant', 'servant'], ['Yesod', 'yesod'], ['Snap', 'snap'], ['Happstack', 'happstack-server'], ['Data.Aeson', 'aeson'],
|
|
43
|
+
['Database.SQLite.Simple', 'sqlite-simple'], ['Database.PostgreSQL.Simple', 'postgresql-simple'], ['Database.Persist', 'persistent'],
|
|
44
|
+
['Database.MySQL', 'mysql-simple'], ['System.Random', 'random'], ['Data.Vector', 'vector'], ['Data.Hashable', 'hashable'],
|
|
45
|
+
['Data.HashMap', 'unordered-containers'], ['Control.Lens', 'lens'], ['Test.', 'a test framework'], ['Turtle', 'turtle'],
|
|
46
|
+
['Shelly', 'shelly'], ['System.Process.Typed', 'typed-process'], ['Conduit', 'conduit'], ['Control.Monad.Logger', 'monad-logger'],
|
|
47
|
+
['Options.Applicative', 'optparse-applicative'], ['Data.Text.Lazy.Builder', null],
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
const libCache = new Map();
|
|
51
|
+
/** The modules the installed GHC exposes from its global package database (what a program can import with no extra packages). */
|
|
52
|
+
export function bootModuleSet(ghc) {
|
|
53
|
+
if (libCache.has(ghc)) return libCache.get(ghc);
|
|
54
|
+
let set = null;
|
|
55
|
+
try {
|
|
56
|
+
const r = spawnSync(ghc, ['--print-libdir'], { encoding: 'utf8', timeout: 10_000 });
|
|
57
|
+
const dir = r.status === 0 ? path.join(r.stdout.trim(), 'package.conf.d') : null;
|
|
58
|
+
if (dir && fs.existsSync(dir)) {
|
|
59
|
+
set = new Set();
|
|
60
|
+
for (const f of fs.readdirSync(dir)) {
|
|
61
|
+
if (!f.endsWith('.conf')) continue;
|
|
62
|
+
const text = fs.readFileSync(path.join(dir, f), 'utf8');
|
|
63
|
+
if (/^exposed:\s*False/m.test(text)) continue;
|
|
64
|
+
const m = /^exposed-modules:\s*\n?([\s\S]*?)(?=^\S)/m.exec(text);
|
|
65
|
+
if (!m) continue;
|
|
66
|
+
for (const tok of m[1].split(/[\s,]+/)) if (/^[A-Z][\w']*(?:\.[A-Z][\w']*)*$/.test(tok)) set.add(tok);
|
|
67
|
+
}
|
|
68
|
+
if (!set.has('Prelude')) set = null; // a database that does not even list Prelude was not read correctly
|
|
69
|
+
}
|
|
70
|
+
} catch { set = null; }
|
|
71
|
+
libCache.set(ghc, set);
|
|
72
|
+
return set;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function readInside(root, rel) {
|
|
76
|
+
let real; try { real = fs.realpathSync(path.resolve(root, rel)); } catch { return null; }
|
|
77
|
+
const base = fs.realpathSync(root);
|
|
78
|
+
if (!(real === base || real.startsWith(base + path.sep))) return null;
|
|
79
|
+
const st = fs.statSync(real);
|
|
80
|
+
return st.isFile() && st.size <= MAX_SOURCE ? { real, text: fs.readFileSync(real, 'utf8') } : null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Split a type on its top-level arrows (arrows inside parentheses or brackets belong to a function-typed argument). */
|
|
84
|
+
function splitArrows(type) {
|
|
85
|
+
const parts = []; let depth = 0; let cur = '';
|
|
86
|
+
for (let i = 0; i < type.length; i++) {
|
|
87
|
+
const c = type[i];
|
|
88
|
+
if ('([{'.includes(c)) depth++; else if (')]}'.includes(c)) depth--;
|
|
89
|
+
if (depth === 0 && c === '-' && type[i + 1] === '>') { parts.push(cur.trim()); cur = ''; i++; continue; }
|
|
90
|
+
cur += c;
|
|
91
|
+
}
|
|
92
|
+
parts.push(cur.trim());
|
|
93
|
+
return parts;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Compile-time code execution and options that change what runs before the payload is involved.
|
|
97
|
+
function loadTimeHazard(text) {
|
|
98
|
+
if (/\{-#\s*LANGUAGE[^#]*\b(?:TemplateHaskell|TemplateHaskellQuotes|QuasiQuotes|CPP|ForeignFunctionInterface|CApiFFI)\b/i.test(text)) return 'it enables Template Haskell, quasi-quotes, CPP or the foreign function interface, which run or require code at load time';
|
|
99
|
+
if (/\{-#\s*OPTIONS(?:_GHC)?\b[^#]*(?:-fplugin|-pgm|-opt[a-zA-Z]|-F\b|-cpp|-fobject-code)/i.test(text)) return 'its OPTIONS_GHC pragma names a plugin, a preprocessor or an external program';
|
|
100
|
+
if (/^\s*foreign\s+(?:import|export)\b/m.test(text)) return 'it uses the foreign function interface';
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function classify(mod, pkg, boot) {
|
|
105
|
+
if (pkg) return { ok: false, name: String(pkg).replace(/^"|"$/g, '') };
|
|
106
|
+
if (boot.has(mod)) return { ok: true };
|
|
107
|
+
for (const [prefix, name] of THIRD_PARTY) if (mod === prefix || mod.startsWith(prefix.endsWith('.') ? prefix : `${prefix}.`)) return { ok: false, name: name ?? mod };
|
|
108
|
+
return { ok: false, name: mod };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** @param {{finding: object, root: string, cls: {name: string, payload: string, oracle: object, network?: string, watch?: object, needsHs?: RegExp}, bootModules?: Set<string>}} o */
|
|
112
|
+
export function generateHaskellReproducer({ finding, root, cls, bootModules }) {
|
|
113
|
+
const rel = String(finding.file);
|
|
114
|
+
if (cls.name === 'ssrf') return fail('ssrf: no HTTP client ships with GHC, so any program that makes a request imports a package outside the proof environment; this class is not proven for Haskell');
|
|
115
|
+
const src = readInside(root, rel);
|
|
116
|
+
if (!src) return fail('the flagged file is missing, outside the repository, or too large');
|
|
117
|
+
const hazard = loadTimeHazard(src.text);
|
|
118
|
+
if (hazard) return fail(`the flagged file is refused: ${hazard}`);
|
|
119
|
+
const info = parseHaskell(src.text);
|
|
120
|
+
if (!info || info.status !== 'parsed') return fail('the flagged file could not be parsed as Haskell');
|
|
121
|
+
const lines = src.text.split('\n');
|
|
122
|
+
const sinkLine = lines[finding.line - 1] ?? '';
|
|
123
|
+
const around = lines.slice(Math.max(0, finding.line - 3), finding.line + 2).join('\n');
|
|
124
|
+
if (cls.needsHs && !cls.needsHs.test(sinkLine) && !cls.needsHs.test(around)) return fail(`${cls.name}: the flagged code is not a write, and this class is only proven for write sinks`);
|
|
125
|
+
|
|
126
|
+
const tools = hostTools();
|
|
127
|
+
const boot = bootModules ?? (tools.ghc ? bootModuleSet(tools.ghc) : null);
|
|
128
|
+
if (!boot) return fail('no working GHC was found to list the modules the proof environment can import (install ghc, or run `agentic-security proof doctor`)');
|
|
129
|
+
|
|
130
|
+
// the entry module is placed at its module path so that other modules can import it; Main goes to Main.hs
|
|
131
|
+
const modName = info.module?.name ?? 'Main';
|
|
132
|
+
const entry = `${modName.replaceAll('.', '/')}.hs`;
|
|
133
|
+
const rootReal = fs.realpathSync(root);
|
|
134
|
+
const entryDir = path.dirname(src.real);
|
|
135
|
+
const modRel = modName.replaceAll('.', path.sep);
|
|
136
|
+
const srcRoot = src.real.endsWith(`${modRel}.hs`) ? src.real.slice(0, src.real.length - modRel.length - 3) : `${entryDir}${path.sep}`;
|
|
137
|
+
const searchRoots = [...new Set([srcRoot.replace(/[\\/]$/, ''), ...['src', 'app', 'lib', ''].map((d) => path.join(rootReal, d))])];
|
|
138
|
+
const sources = {}; const external = []; const seen = new Set([modName]);
|
|
139
|
+
let count = 0;
|
|
140
|
+
const visit = (imports) => {
|
|
141
|
+
for (const imp of imports) {
|
|
142
|
+
const mod = imp.module;
|
|
143
|
+
if (seen.has(mod)) continue;
|
|
144
|
+
seen.add(mod);
|
|
145
|
+
let local = null;
|
|
146
|
+
for (const base of searchRoots) { const cand = path.join(base, `${mod.replaceAll('.', '/')}.hs`); const r = readInside(root, path.relative(rootReal, cand)); if (r) { local = r; break; } }
|
|
147
|
+
if (local && !imp.package) {
|
|
148
|
+
if (++count > MAX_FILES) return fail(`the file pulls in more than ${MAX_FILES} repository modules`);
|
|
149
|
+
const dep = parseHaskell(local.text);
|
|
150
|
+
if (!dep || dep.status !== 'parsed') return fail(`the module ${mod} could not be parsed as Haskell`);
|
|
151
|
+
const h = loadTimeHazard(local.text); if (h) return fail(`the module ${mod} is refused: ${h}`);
|
|
152
|
+
sources[`${mod.replaceAll('.', '/')}.hs`] = path.relative(rootReal, local.real);
|
|
153
|
+
const r = visit(dep.imports ?? []); if (r) return r;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const c = classify(mod, imp.package, boot);
|
|
157
|
+
if (!c.ok) external.push(c.name);
|
|
158
|
+
}
|
|
159
|
+
return null;
|
|
160
|
+
};
|
|
161
|
+
const bad = visit(info.imports ?? []);
|
|
162
|
+
if (bad) return bad;
|
|
163
|
+
if (external.length) return fail(`the flagged code needs ${[...new Set(external)].slice(0, 4).join(', ')}, which is not available in the proof environment; only the packages that ship with GHC and files in the repository can be loaded`, { missing: [...new Set(external)] });
|
|
164
|
+
sources[entry] = rel;
|
|
165
|
+
|
|
166
|
+
const assumptions = [];
|
|
167
|
+
const base = { schema: 'agentic-security/reproducer', version: 1, findingId: String(finding.stableId ?? finding.id ?? 'generated'), lang: 'haskell', oracle: cls.oracle, network: cls.network ?? 'none', ...(cls.watch ? { watch: cls.watch } : {}) };
|
|
168
|
+
if (cls.watch) assumptions.push('the write target is assumed to be one directory below the working directory (the payload is ../escaped.txt); if the code uses another base, the proof will not confirm it');
|
|
169
|
+
const ghcRun = (expr) => ['{{GHC}}', '-ignore-dot-ghci', '-e', expr, entry];
|
|
170
|
+
const literal = (s) => JSON.stringify(s); // payloads are fixed strings with no quote or backslash; this is a plain Haskell string literal
|
|
171
|
+
|
|
172
|
+
// shape 1: a program that reads its payload from the command line
|
|
173
|
+
const hasMain = (info.functions ?? []).some((f) => f.scope === 'top' && f.name === 'main');
|
|
174
|
+
if (/\bgetArgs\b/.test(src.text) && hasMain) {
|
|
175
|
+
assumptions.push('the payload is passed as the first and only command-line argument; a program that expects other arguments will not reach the flagged line');
|
|
176
|
+
const reproducer = { ...base, sources, run: ghcRun(`:main ${literal(cls.payload)}`) };
|
|
177
|
+
const errs = validateReproducer(reproducer);
|
|
178
|
+
return errs.length ? fail(`the generated reproducer is invalid: ${errs[0]}`) : { ok: true, reproducer, basis: { shape: 'script', class: cls.name, entry: rel, line: finding.line, assumptions } };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// shape 2: a top-level function around the flagged line
|
|
182
|
+
const fn = (info.functions ?? []).filter((f) => f.scope === 'top' && f.name !== 'main' && /^[a-z_][\w']*$/.test(f.name)).find((f) => {
|
|
183
|
+
const end = Math.max(f.span.endLine, ...(f.clauses ?? []).map((c) => c.span?.endLine ?? 0));
|
|
184
|
+
return f.span.startLine <= finding.line && end >= finding.line;
|
|
185
|
+
});
|
|
186
|
+
if (!fn) return fail('the flagged line is not inside a top-level function, and the file does not read getArgs in a main');
|
|
187
|
+
const sig = (info.signatures ?? []).find((s) => s.scope === 'top' && s.names.includes(fn.name));
|
|
188
|
+
if (!sig) return fail(`${fn.name} has no type signature, so the proof cannot tell what to pass it`);
|
|
189
|
+
const sigText = lines.slice(sig.span.startLine - 1, sig.span.endLine).join(' ');
|
|
190
|
+
const m = new RegExp(`${fn.name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}[^:]*::\\s*([\\s\\S]*)$`).exec(sigText);
|
|
191
|
+
if (!m) return fail(`the type signature of ${fn.name} could not be read`);
|
|
192
|
+
const type = m[1].replace(/--.*$/, '').trim();
|
|
193
|
+
if (type.includes('=>') || /\bforall\b/.test(type)) return fail(`${fn.name} is polymorphic or constrained (${type.slice(0, 60)}), so the proof cannot choose its arguments`);
|
|
194
|
+
const parts = splitArrows(type);
|
|
195
|
+
const result = parts[parts.length - 1]; const params = parts.slice(0, -1);
|
|
196
|
+
if (!/^IO\b/.test(result)) return fail(`${fn.name} returns ${result.slice(0, 40)}, not IO, so calling it would not perform the flagged operation`);
|
|
197
|
+
if (!params.length) return fail(`${fn.name} takes no parameters, so the payload has no way in`);
|
|
198
|
+
const bad2 = params.find((p) => !/^(?:String|FilePath|\[Char\])$/.test(p));
|
|
199
|
+
if (bad2) return fail(`${fn.name} takes a parameter of type ${bad2.slice(0, 40)}; only String and FilePath can be filled with a payload`);
|
|
200
|
+
assumptions.push('the payload is passed in every parameter (a String has no request-like stand-in), which is an approximation of how the function is really called');
|
|
201
|
+
const call = `${fn.name} ${params.map(() => literal(cls.payload)).join(' ')} >>= \\_ -> return ()`;
|
|
202
|
+
const reproducer = { ...base, sources, run: ghcRun(call) };
|
|
203
|
+
const errs = validateReproducer(reproducer);
|
|
204
|
+
return errs.length ? fail(`the generated reproducer is invalid: ${errs[0]}`) : { ok: true, reproducer, basis: { shape: 'function', class: cls.name, entry: rel, line: finding.line, function: `${fn.name}(${params.length} String)`, assumptions } };
|
|
205
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// independent replay as any other. A generated reproducer is not a verdict; it is a proposal that is either confirmed by execution
|
|
7
7
|
// or not.
|
|
8
8
|
//
|
|
9
|
-
// What this is not: a general exploit generator. It handles JavaScript (here)
|
|
9
|
+
// What this is not: a general exploit generator. It handles JavaScript (here), Python (`generate-python.js`) and Haskell (`generate-haskell.js`), and only code the proof environment can actually load:
|
|
10
10
|
// the file's imports must be Node built-ins or relative files inside the repository (a package from node_modules is not there in
|
|
11
11
|
// the sandbox, so a handler that needs `express` is refused, with the package named). Anything outside that returns `{ ok: false }`
|
|
12
12
|
// with the reason, and nothing is executed.
|
|
@@ -27,10 +27,11 @@ import { builtinModules } from 'node:module';
|
|
|
27
27
|
import { parse } from '@babel/parser';
|
|
28
28
|
import { validateReproducer } from './reproducer.js';
|
|
29
29
|
import { generatePythonReproducer } from './generate-python.js';
|
|
30
|
+
import { generateHaskellReproducer } from './generate-haskell.js';
|
|
30
31
|
|
|
31
32
|
const CLASSES = {
|
|
32
33
|
'CWE-78': { name: 'command-injection', payload: 'x; touch {{CANARY:command}}', oracle: { type: 'command_execution', params: { canary: 'command' } } },
|
|
33
|
-
'CWE-22': { needsPy: /\bopen\s*\([^)]*['"][wax]b?\+?['"]|\.write_(?:text|bytes)\s*\(|\bshutil\.(?:copy|move)/, name: 'path-traversal', payload: '../escaped.txt', oracle: { type: 'filesystem_mutation', params: { canary: 'fs' } }, watch: { fs: 'escaped.txt' }, needs: /\b(?:writeFile|writeFileSync|appendFile|appendFileSync|createWriteStream)\b/ },
|
|
34
|
+
'CWE-22': { needsPy: /\bopen\s*\([^)]*['"][wax]b?\+?['"]|\.write_(?:text|bytes)\s*\(|\bshutil\.(?:copy|move)/, name: 'path-traversal', payload: '../escaped.txt', oracle: { type: 'filesystem_mutation', params: { canary: 'fs' } }, watch: { fs: 'escaped.txt' }, needsHs: /\b(?:writeFile|appendFile|copyFile|copyFileWithMetadata|renameFile|openBinaryFile)\b|\b(?:openFile|withFile|withBinaryFile)\b[^\n]*\b(?:WriteMode|AppendMode|ReadWriteMode)\b/, needs: /\b(?:writeFile|writeFileSync|appendFile|appendFileSync|createWriteStream)\b/ },
|
|
34
35
|
'CWE-918': { name: 'ssrf', payload: '{{CALLBACK_URL}}', oracle: { type: 'outbound_callback' }, network: 'callback' },
|
|
35
36
|
};
|
|
36
37
|
const MAX_SOURCE = 256 * 1024;
|
|
@@ -138,9 +139,11 @@ export function generateReproducer({ finding, root }) {
|
|
|
138
139
|
if (!cls) return fail(`no payload and oracle exist for ${cwe ?? 'this finding'}; supported: ${Object.keys(CLASSES).join(', ')} (others need a database, a deserializer or a native harness)`);
|
|
139
140
|
const rel = String(finding?.file ?? '');
|
|
140
141
|
const isPy = /\.py$/i.test(rel);
|
|
141
|
-
|
|
142
|
+
const isHs = /\.hs$/i.test(rel);
|
|
143
|
+
if (!isPy && !isHs && !/\.(?:js|mjs|cjs)$/i.test(rel)) return fail(`no harness builder for ${path.extname(rel) || 'this file type'}; JavaScript, Python and Haskell only`);
|
|
142
144
|
if (!Number.isInteger(finding?.line)) return fail('the finding has no line number');
|
|
143
145
|
if (isPy) return generatePythonReproducer({ finding, root, cls });
|
|
146
|
+
if (isHs) return generateHaskellReproducer({ finding, root, cls });
|
|
144
147
|
const src = readSource(root, rel);
|
|
145
148
|
if (!src) return fail('the flagged file is missing, outside the repository, or too large');
|
|
146
149
|
const ast = parseSource(src.text);
|
|
@@ -8,12 +8,12 @@ import { validateAttackFacts } from '../dnr/attack-facts.js';
|
|
|
8
8
|
|
|
9
9
|
const REPRODUCER_SCHEMA = 'agentic-security/reproducer';
|
|
10
10
|
const REPRODUCER_VERSION = 1;
|
|
11
|
-
export const LANGUAGES = Object.freeze(['javascript', 'typescript', 'python', 'java', 'c', 'cpp', 'csharp']);
|
|
11
|
+
export const LANGUAGES = Object.freeze(['javascript', 'typescript', 'python', 'java', 'c', 'cpp', 'csharp', 'haskell']);
|
|
12
12
|
export const MAX_FILES = 64;
|
|
13
13
|
export const MAX_FILE_BYTES = 256 * 1024;
|
|
14
14
|
const MAX_TOTAL_BYTES = 1024 * 1024;
|
|
15
15
|
const PLACEHOLDER_RE = /\{\{([A-Z_]+)(?::([a-z0-9_-]{1,32}))?\}\}/g;
|
|
16
|
-
const ALLOWED_PLACEHOLDERS = new Set(['NONCE', 'SECRET', 'CANARY', 'CALLBACK_URL', 'CALLBACK_PORT', 'ROOT', 'NODE', 'PYTHON', 'JAVA', 'JAVAC', 'CC']);
|
|
16
|
+
const ALLOWED_PLACEHOLDERS = new Set(['NONCE', 'SECRET', 'CANARY', 'CALLBACK_URL', 'CALLBACK_PORT', 'ROOT', 'NODE', 'PYTHON', 'JAVA', 'JAVAC', 'CC', 'GHC', 'RUNGHC']);
|
|
17
17
|
|
|
18
18
|
export function isSafeRelPath(rel) {
|
|
19
19
|
if (typeof rel !== 'string' || !rel || rel.length > 200) return false;
|
|
@@ -105,6 +105,8 @@ export function substitute(text, ctx) {
|
|
|
105
105
|
case 'JAVA': return ctx.tools.java ?? whole;
|
|
106
106
|
case 'JAVAC': return ctx.tools.javac ?? whole;
|
|
107
107
|
case 'CC': return ctx.tools.cc ?? whole;
|
|
108
|
+
case 'GHC': return ctx.tools.ghc ?? whole;
|
|
109
|
+
case 'RUNGHC': return ctx.tools.runghc ?? whole;
|
|
108
110
|
default: return whole;
|
|
109
111
|
}
|
|
110
112
|
});
|
|
@@ -24,13 +24,13 @@ export const DEFAULT_LIMITS = Object.freeze({
|
|
|
24
24
|
|
|
25
25
|
const CONTAINER_IMAGES = Object.freeze({
|
|
26
26
|
javascript: 'node:24-slim', typescript: 'node:24-slim', python: 'python:3-slim', java: 'eclipse-temurin:21',
|
|
27
|
-
c: 'gcc:latest', cpp: 'gcc:latest', csharp: 'mcr.microsoft.com/dotnet/sdk:8.0',
|
|
27
|
+
c: 'gcc:latest', cpp: 'gcc:latest', csharp: 'mcr.microsoft.com/dotnet/sdk:8.0', haskell: 'haskell:9',
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
const SIGNALS = { 134: 'SIGABRT', 135: 'SIGBUS', 136: 'SIGFPE', 132: 'SIGILL', 139: 'SIGSEGV' };
|
|
31
31
|
|
|
32
32
|
// only language toolchains are probed; the container engine has its own, richer health check (`container.js`)
|
|
33
|
-
const PROBED_TOOLS = new Set(['java', 'javac', 'python3', 'cc', 'gcc', 'dotnet']);
|
|
33
|
+
const PROBED_TOOLS = new Set(['java', 'javac', 'python3', 'cc', 'gcc', 'dotnet', 'ghc', 'runghc']);
|
|
34
34
|
const probeCache = new Map();
|
|
35
35
|
/** A launcher that exists is not a toolchain that works: macOS ships /usr/bin/java and /usr/bin/python3 as stubs that only prompt for an
|
|
36
36
|
* install. A tool counts only if it answers its version flag, within a short timeout, with exit 0. */
|
|
@@ -61,12 +61,12 @@ function findTool(name, pathEnv = process.env.PATH || '') {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
export function hostTools() {
|
|
64
|
-
return { node: process.execPath, python: findTool('python3'), java: findTool('java'), javac: findTool('javac'), cc: findTool('cc') || findTool('gcc'), dotnet: findTool('dotnet') };
|
|
64
|
+
return { node: process.execPath, python: findTool('python3'), java: findTool('java'), javac: findTool('javac'), cc: findTool('cc') || findTool('gcc'), dotnet: findTool('dotnet'), ghc: findTool('ghc'), runghc: findTool('runghc') };
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
/** Language -> tools it needs. Missing tools make the language `unsupported` with a typed reason, never a pass. */
|
|
68
68
|
export function languageSupport(lang, tools = hostTools()) {
|
|
69
|
-
const need = { javascript: ['node'], typescript: ['node'], python: ['python'], java: ['java', 'javac'], c: ['cc'], cpp: ['cc'], csharp: ['dotnet'] }[lang];
|
|
69
|
+
const need = { javascript: ['node'], typescript: ['node'], python: ['python'], java: ['java', 'javac'], c: ['cc'], cpp: ['cc'], csharp: ['dotnet'], haskell: ['ghc', 'runghc'] }[lang];
|
|
70
70
|
if (!need) return { supported: false, reason: `unsupported language: ${lang}` };
|
|
71
71
|
const missing = need.filter((t) => !tools[t]);
|
|
72
72
|
return missing.length ? { supported: false, reason: `missing toolchain: ${missing.join(', ')}` } : { supported: true, reason: null };
|