vaspera 2.13.0 → 2.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -0
- package/README.md +15 -2
- package/dist/__tests__/antagonist-integration.test.d.ts +6 -0
- package/dist/__tests__/antagonist-integration.test.d.ts.map +1 -0
- package/dist/__tests__/antagonist-integration.test.js +239 -0
- package/dist/__tests__/antagonist-integration.test.js.map +1 -0
- package/dist/__tests__/certification/agent-certificate-e2e.test.d.ts +2 -0
- package/dist/__tests__/certification/agent-certificate-e2e.test.d.ts.map +1 -0
- package/dist/__tests__/certification/agent-certificate-e2e.test.js +90 -0
- package/dist/__tests__/certification/agent-certificate-e2e.test.js.map +1 -0
- package/dist/__tests__/certification/agent-certificate-map.test.d.ts +2 -0
- package/dist/__tests__/certification/agent-certificate-map.test.d.ts.map +1 -0
- package/dist/__tests__/certification/agent-certificate-map.test.js +107 -0
- package/dist/__tests__/certification/agent-certificate-map.test.js.map +1 -0
- package/dist/__tests__/certification/agent-certificate.test.d.ts +2 -0
- package/dist/__tests__/certification/agent-certificate.test.d.ts.map +1 -0
- package/dist/__tests__/certification/agent-certificate.test.js +78 -0
- package/dist/__tests__/certification/agent-certificate.test.js.map +1 -0
- package/dist/__tests__/certification/verify-endpoint.test.d.ts +2 -0
- package/dist/__tests__/certification/verify-endpoint.test.d.ts.map +1 -0
- package/dist/__tests__/certification/verify-endpoint.test.js +81 -0
- package/dist/__tests__/certification/verify-endpoint.test.js.map +1 -0
- package/dist/__tests__/compliance/ai-frameworks.test.d.ts +2 -0
- package/dist/__tests__/compliance/ai-frameworks.test.d.ts.map +1 -0
- package/dist/__tests__/compliance/ai-frameworks.test.js +87 -0
- package/dist/__tests__/compliance/ai-frameworks.test.js.map +1 -0
- package/dist/__tests__/eval/llm-analyzer.test.d.ts +2 -0
- package/dist/__tests__/eval/llm-analyzer.test.d.ts.map +1 -0
- package/dist/__tests__/eval/llm-analyzer.test.js +93 -0
- package/dist/__tests__/eval/llm-analyzer.test.js.map +1 -0
- package/dist/__tests__/eval/redteam-harness.test.d.ts +2 -0
- package/dist/__tests__/eval/redteam-harness.test.d.ts.map +1 -0
- package/dist/__tests__/eval/redteam-harness.test.js +136 -0
- package/dist/__tests__/eval/redteam-harness.test.js.map +1 -0
- package/dist/__tests__/evidence/evidence.test.d.ts +2 -0
- package/dist/__tests__/evidence/evidence.test.d.ts.map +1 -0
- package/dist/__tests__/evidence/evidence.test.js +240 -0
- package/dist/__tests__/evidence/evidence.test.js.map +1 -0
- package/dist/__tests__/history/decisions.test.d.ts +2 -0
- package/dist/__tests__/history/decisions.test.d.ts.map +1 -0
- package/dist/__tests__/history/decisions.test.js +54 -0
- package/dist/__tests__/history/decisions.test.js.map +1 -0
- package/dist/__tests__/http-auth.test.d.ts +2 -0
- package/dist/__tests__/http-auth.test.d.ts.map +1 -0
- package/dist/__tests__/http-auth.test.js +55 -0
- package/dist/__tests__/http-auth.test.js.map +1 -0
- package/dist/__tests__/http-policy.test.d.ts +2 -0
- package/dist/__tests__/http-policy.test.d.ts.map +1 -0
- package/dist/__tests__/http-policy.test.js +69 -0
- package/dist/__tests__/http-policy.test.js.map +1 -0
- package/dist/__tests__/http-server-transport.test.d.ts +2 -0
- package/dist/__tests__/http-server-transport.test.d.ts.map +1 -0
- package/dist/__tests__/http-server-transport.test.js +132 -0
- package/dist/__tests__/http-server-transport.test.js.map +1 -0
- package/dist/__tests__/integration/destructive-guards.test.d.ts +2 -0
- package/dist/__tests__/integration/destructive-guards.test.d.ts.map +1 -0
- package/dist/__tests__/integration/destructive-guards.test.js +49 -0
- package/dist/__tests__/integration/destructive-guards.test.js.map +1 -0
- package/dist/__tests__/logger-redaction.test.d.ts +2 -0
- package/dist/__tests__/logger-redaction.test.d.ts.map +1 -0
- package/dist/__tests__/logger-redaction.test.js +74 -0
- package/dist/__tests__/logger-redaction.test.js.map +1 -0
- package/dist/__tests__/manifest-schema.test.d.ts +2 -0
- package/dist/__tests__/manifest-schema.test.d.ts.map +1 -0
- package/dist/__tests__/manifest-schema.test.js +43 -0
- package/dist/__tests__/manifest-schema.test.js.map +1 -0
- package/dist/__tests__/scanners/builtin-rules.test.d.ts +2 -0
- package/dist/__tests__/scanners/builtin-rules.test.d.ts.map +1 -0
- package/dist/__tests__/scanners/builtin-rules.test.js +51 -0
- package/dist/__tests__/scanners/builtin-rules.test.js.map +1 -0
- package/dist/__tests__/scanners/runtime/golden-path-runner.test.js +13 -1
- package/dist/__tests__/scanners/runtime/golden-path-runner.test.js.map +1 -1
- package/dist/__tests__/tool-guard.test.d.ts +2 -0
- package/dist/__tests__/tool-guard.test.d.ts.map +1 -0
- package/dist/__tests__/tool-guard.test.js +97 -0
- package/dist/__tests__/tool-guard.test.js.map +1 -0
- package/dist/__tests__/util/contained-file.test.d.ts +2 -0
- package/dist/__tests__/util/contained-file.test.d.ts.map +1 -0
- package/dist/__tests__/util/contained-file.test.js +78 -0
- package/dist/__tests__/util/contained-file.test.js.map +1 -0
- package/dist/__tests__/util/subprocess.test.d.ts +2 -0
- package/dist/__tests__/util/subprocess.test.d.ts.map +1 -0
- package/dist/__tests__/util/subprocess.test.js +48 -0
- package/dist/__tests__/util/subprocess.test.js.map +1 -0
- package/dist/action/diff-mode.d.ts.map +1 -1
- package/dist/action/diff-mode.js +31 -12
- package/dist/action/diff-mode.js.map +1 -1
- package/dist/agents/antagonist/challenger.d.ts +46 -0
- package/dist/agents/antagonist/challenger.d.ts.map +1 -0
- package/dist/agents/antagonist/challenger.js +257 -0
- package/dist/agents/antagonist/challenger.js.map +1 -0
- package/dist/agents/antagonist/index.d.ts +31 -0
- package/dist/agents/antagonist/index.d.ts.map +1 -0
- package/dist/agents/antagonist/index.js +175 -0
- package/dist/agents/antagonist/index.js.map +1 -0
- package/dist/agents/antagonist/prioritizer.d.ts +27 -0
- package/dist/agents/antagonist/prioritizer.d.ts.map +1 -0
- package/dist/agents/antagonist/prioritizer.js +181 -0
- package/dist/agents/antagonist/prioritizer.js.map +1 -0
- package/dist/agents/antagonist/prompts.d.ts +12 -0
- package/dist/agents/antagonist/prompts.d.ts.map +1 -0
- package/dist/agents/antagonist/prompts.js +155 -0
- package/dist/agents/antagonist/prompts.js.map +1 -0
- package/dist/agents/antagonist/synthesizer.d.ts +34 -0
- package/dist/agents/antagonist/synthesizer.d.ts.map +1 -0
- package/dist/agents/antagonist/synthesizer.js +451 -0
- package/dist/agents/antagonist/synthesizer.js.map +1 -0
- package/dist/agents/antagonist/types.d.ts +145 -0
- package/dist/agents/antagonist/types.d.ts.map +1 -0
- package/dist/agents/antagonist/types.js +63 -0
- package/dist/agents/antagonist/types.js.map +1 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +2 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/certification/agent-certificate-map.d.ts +51 -0
- package/dist/certification/agent-certificate-map.d.ts.map +1 -0
- package/dist/certification/agent-certificate-map.js +265 -0
- package/dist/certification/agent-certificate-map.js.map +1 -0
- package/dist/certification/agent-certificate-sample.d.ts +25 -0
- package/dist/certification/agent-certificate-sample.d.ts.map +1 -0
- package/dist/certification/agent-certificate-sample.js +207 -0
- package/dist/certification/agent-certificate-sample.js.map +1 -0
- package/dist/certification/agent-certificate.d.ts +1981 -0
- package/dist/certification/agent-certificate.d.ts.map +1 -0
- package/dist/certification/agent-certificate.js +309 -0
- package/dist/certification/agent-certificate.js.map +1 -0
- package/dist/certification/autofix.d.ts.map +1 -1
- package/dist/certification/autofix.js +5 -3
- package/dist/certification/autofix.js.map +1 -1
- package/dist/certification/consensus.test.js +2 -0
- package/dist/certification/consensus.test.js.map +1 -1
- package/dist/certification/store.d.ts.map +1 -1
- package/dist/certification/store.js +11 -3
- package/dist/certification/store.js.map +1 -1
- package/dist/certification/types.d.ts +1 -1
- package/dist/certification/types.d.ts.map +1 -1
- package/dist/certification/types.js +2 -0
- package/dist/certification/types.js.map +1 -1
- package/dist/certification/verify-endpoint.d.ts +48 -0
- package/dist/certification/verify-endpoint.d.ts.map +1 -0
- package/dist/certification/verify-endpoint.js +79 -0
- package/dist/certification/verify-endpoint.js.map +1 -0
- package/dist/compliance/index.d.ts +2 -0
- package/dist/compliance/index.d.ts.map +1 -1
- package/dist/compliance/index.js +4 -0
- package/dist/compliance/index.js.map +1 -1
- package/dist/compliance/iso42001.d.ts +21 -0
- package/dist/compliance/iso42001.d.ts.map +1 -0
- package/dist/compliance/iso42001.js +160 -0
- package/dist/compliance/iso42001.js.map +1 -0
- package/dist/compliance/mapper.d.ts.map +1 -1
- package/dist/compliance/mapper.js +12 -0
- package/dist/compliance/mapper.js.map +1 -1
- package/dist/compliance/nist-ai-rmf.d.ts +20 -0
- package/dist/compliance/nist-ai-rmf.d.ts.map +1 -0
- package/dist/compliance/nist-ai-rmf.js +140 -0
- package/dist/compliance/nist-ai-rmf.js.map +1 -0
- package/dist/config/flags.d.ts +4 -4
- package/dist/eval/fixtures.d.ts.map +1 -1
- package/dist/eval/fixtures.js +161 -119
- package/dist/eval/fixtures.js.map +1 -1
- package/dist/eval/fixtures.test.js +4 -2
- package/dist/eval/fixtures.test.js.map +1 -1
- package/dist/eval/llm-analyzer.d.ts +40 -0
- package/dist/eval/llm-analyzer.d.ts.map +1 -0
- package/dist/eval/llm-analyzer.js +154 -0
- package/dist/eval/llm-analyzer.js.map +1 -0
- package/dist/eval/redteam-harness.d.ts +95 -0
- package/dist/eval/redteam-harness.d.ts.map +1 -0
- package/dist/eval/redteam-harness.js +137 -0
- package/dist/eval/redteam-harness.js.map +1 -0
- package/dist/evidence/collector.d.ts.map +1 -1
- package/dist/evidence/collector.js +21 -1
- package/dist/evidence/collector.js.map +1 -1
- package/dist/evidence/store.d.ts.map +1 -1
- package/dist/evidence/store.js +29 -5
- package/dist/evidence/store.js.map +1 -1
- package/dist/evidence/types.d.ts +16 -9
- package/dist/evidence/types.d.ts.map +1 -1
- package/dist/history/decisions.d.ts +63 -0
- package/dist/history/decisions.d.ts.map +1 -0
- package/dist/history/decisions.js +60 -0
- package/dist/history/decisions.js.map +1 -0
- package/dist/history/index.d.ts +2 -0
- package/dist/history/index.d.ts.map +1 -1
- package/dist/history/index.js +2 -0
- package/dist/history/index.js.map +1 -1
- package/dist/history/types.d.ts +34 -5
- package/dist/history/types.d.ts.map +1 -1
- package/dist/history/types.js +2 -0
- package/dist/history/types.js.map +1 -1
- package/dist/http-auth.d.ts +22 -0
- package/dist/http-auth.d.ts.map +1 -0
- package/dist/http-auth.js +58 -0
- package/dist/http-auth.js.map +1 -0
- package/dist/http-policy.d.ts +30 -0
- package/dist/http-policy.d.ts.map +1 -0
- package/dist/http-policy.js +54 -0
- package/dist/http-policy.js.map +1 -0
- package/dist/http-server.js +195 -12
- package/dist/http-server.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +411 -15
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +56 -2
- package/dist/logger.js.map +1 -1
- package/dist/plugins/types.d.ts +2 -2
- package/dist/sbom/provenance.test.js +2 -2
- package/dist/sbom/provenance.test.js.map +1 -1
- package/dist/sbom/signing.d.ts.map +1 -1
- package/dist/sbom/signing.js +5 -3
- package/dist/sbom/signing.js.map +1 -1
- package/dist/scanners/agent/prompt-injection-fuzzer.d.ts.map +1 -1
- package/dist/scanners/agent/prompt-injection-fuzzer.js +26 -0
- package/dist/scanners/agent/prompt-injection-fuzzer.js.map +1 -1
- package/dist/scanners/agent/types.d.ts +10 -10
- package/dist/scanners/bandit.d.ts.map +1 -1
- package/dist/scanners/bandit.js +35 -29
- package/dist/scanners/bandit.js.map +1 -1
- package/dist/scanners/binary-analysis.d.ts.map +1 -1
- package/dist/scanners/binary-analysis.js +24 -49
- package/dist/scanners/binary-analysis.js.map +1 -1
- package/dist/scanners/brakeman.d.ts.map +1 -1
- package/dist/scanners/brakeman.js +19 -33
- package/dist/scanners/brakeman.js.map +1 -1
- package/dist/scanners/builtin-rules.d.ts +24 -0
- package/dist/scanners/builtin-rules.d.ts.map +1 -0
- package/dist/scanners/builtin-rules.js +175 -0
- package/dist/scanners/builtin-rules.js.map +1 -0
- package/dist/scanners/dast.d.ts.map +1 -1
- package/dist/scanners/dast.js +24 -34
- package/dist/scanners/dast.js.map +1 -1
- package/dist/scanners/deploy/types.d.ts +6 -6
- package/dist/scanners/eslint.d.ts.map +1 -1
- package/dist/scanners/eslint.js +15 -24
- package/dist/scanners/eslint.js.map +1 -1
- package/dist/scanners/gosec.d.ts.map +1 -1
- package/dist/scanners/gosec.js +14 -62
- package/dist/scanners/gosec.js.map +1 -1
- package/dist/scanners/index.d.ts.map +1 -1
- package/dist/scanners/index.js +38 -7
- package/dist/scanners/index.js.map +1 -1
- package/dist/scanners/memory-safety.d.ts.map +1 -1
- package/dist/scanners/memory-safety.js +27 -28
- package/dist/scanners/memory-safety.js.map +1 -1
- package/dist/scanners/openapi.d.ts.map +1 -1
- package/dist/scanners/openapi.js +14 -22
- package/dist/scanners/openapi.js.map +1 -1
- package/dist/scanners/race-condition.d.ts.map +1 -1
- package/dist/scanners/race-condition.js +17 -16
- package/dist/scanners/race-condition.js.map +1 -1
- package/dist/scanners/runtime/types.d.ts +4 -4
- package/dist/scanners/rust.d.ts.map +1 -1
- package/dist/scanners/rust.js +38 -37
- package/dist/scanners/rust.js.map +1 -1
- package/dist/scanners/scale/types.d.ts +16 -16
- package/dist/scanners/secrets.d.ts.map +1 -1
- package/dist/scanners/secrets.js +66 -78
- package/dist/scanners/secrets.js.map +1 -1
- package/dist/scanners/semgrep.d.ts +2 -0
- package/dist/scanners/semgrep.d.ts.map +1 -1
- package/dist/scanners/semgrep.js +12 -0
- package/dist/scanners/semgrep.js.map +1 -1
- package/dist/scanners/terraform.d.ts.map +1 -1
- package/dist/scanners/terraform.js +47 -40
- package/dist/scanners/terraform.js.map +1 -1
- package/dist/scanners/trivy.d.ts.map +1 -1
- package/dist/scanners/trivy.js +38 -30
- package/dist/scanners/trivy.js.map +1 -1
- package/dist/tool-guard.d.ts +40 -0
- package/dist/tool-guard.d.ts.map +1 -0
- package/dist/tool-guard.js +55 -0
- package/dist/tool-guard.js.map +1 -0
- package/dist/util/index.d.ts +2 -1
- package/dist/util/index.d.ts.map +1 -1
- package/dist/util/index.js +2 -1
- package/dist/util/index.js.map +1 -1
- package/dist/util/paths.d.ts +20 -3
- package/dist/util/paths.d.ts.map +1 -1
- package/dist/util/paths.js +84 -4
- package/dist/util/paths.js.map +1 -1
- package/dist/util/subprocess.d.ts +51 -0
- package/dist/util/subprocess.d.ts.map +1 -0
- package/dist/util/subprocess.js +77 -0
- package/dist/util/subprocess.js.map +1 -0
- package/package.json +12 -2
- package/dist/eval/fixtures/healthcare/audit-gaps.d.ts +0 -28
- package/dist/eval/fixtures/healthcare/audit-gaps.d.ts.map +0 -1
- package/dist/eval/fixtures/healthcare/audit-gaps.js +0 -90
- package/dist/eval/fixtures/healthcare/audit-gaps.js.map +0 -1
- package/dist/eval/fixtures/healthcare/consent-bypass.d.ts +0 -31
- package/dist/eval/fixtures/healthcare/consent-bypass.d.ts.map +0 -1
- package/dist/eval/fixtures/healthcare/consent-bypass.js +0 -61
- package/dist/eval/fixtures/healthcare/consent-bypass.js.map +0 -1
- package/dist/eval/fixtures/healthcare/phi-in-logs.d.ts +0 -24
- package/dist/eval/fixtures/healthcare/phi-in-logs.d.ts.map +0 -1
- package/dist/eval/fixtures/healthcare/phi-in-logs.js +0 -41
- package/dist/eval/fixtures/healthcare/phi-in-logs.js.map +0 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NIST AI Risk Management Framework (AI RMF 1.0) + Generative AI Profile
|
|
3
|
+
*
|
|
4
|
+
* The four functions — GOVERN, MAP, MEASURE, MANAGE — and their key
|
|
5
|
+
* subcategories, mapped to the platform's finding categories. US-friendly
|
|
6
|
+
* and becoming the de facto AI governance baseline.
|
|
7
|
+
*
|
|
8
|
+
* @module compliance/nist-ai-rmf
|
|
9
|
+
*/
|
|
10
|
+
import type { ComplianceControl } from "./types.js";
|
|
11
|
+
/**
|
|
12
|
+
* NIST AI RMF controls (representative subcategories relevant to
|
|
13
|
+
* certifying AI systems and AI-generated code).
|
|
14
|
+
*/
|
|
15
|
+
export declare const NIST_AI_RMF_CONTROLS: ComplianceControl[];
|
|
16
|
+
/** Get all NIST AI RMF controls. */
|
|
17
|
+
export declare function getNISTAIRMFControls(): ComplianceControl[];
|
|
18
|
+
/** Get NIST AI RMF controls for a given function (GOVERN/MAP/MEASURE/MANAGE). */
|
|
19
|
+
export declare function getNISTAIRMFControlsByFunction(fn: string): ComplianceControl[];
|
|
20
|
+
//# sourceMappingURL=nist-ai-rmf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nist-ai-rmf.d.ts","sourceRoot":"","sources":["../../src/compliance/nist-ai-rmf.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,iBAAiB,EAmInD,CAAC;AAEF,oCAAoC;AACpC,wBAAgB,oBAAoB,IAAI,iBAAiB,EAAE,CAE1D;AAED,iFAAiF;AACjF,wBAAgB,8BAA8B,CAAC,EAAE,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAE9E"}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NIST AI Risk Management Framework (AI RMF 1.0) + Generative AI Profile
|
|
3
|
+
*
|
|
4
|
+
* The four functions — GOVERN, MAP, MEASURE, MANAGE — and their key
|
|
5
|
+
* subcategories, mapped to the platform's finding categories. US-friendly
|
|
6
|
+
* and becoming the de facto AI governance baseline.
|
|
7
|
+
*
|
|
8
|
+
* @module compliance/nist-ai-rmf
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* NIST AI RMF controls (representative subcategories relevant to
|
|
12
|
+
* certifying AI systems and AI-generated code).
|
|
13
|
+
*/
|
|
14
|
+
export const NIST_AI_RMF_CONTROLS = [
|
|
15
|
+
// GOVERN — policies, accountability, culture
|
|
16
|
+
{
|
|
17
|
+
id: "GOVERN-1.1",
|
|
18
|
+
framework: "NIST-AI-RMF",
|
|
19
|
+
category: "GOVERN",
|
|
20
|
+
title: "Legal and policy requirements are understood and managed",
|
|
21
|
+
description: "Policies, processes, and practices for AI risk management are in place, transparent, and implemented.",
|
|
22
|
+
keywords: ["policy", "governance", "accountability", "compliance"],
|
|
23
|
+
findingCategories: ["security-misconfiguration"],
|
|
24
|
+
severityThreshold: "low",
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: "GOVERN-1.5",
|
|
28
|
+
framework: "NIST-AI-RMF",
|
|
29
|
+
category: "GOVERN",
|
|
30
|
+
title: "Ongoing monitoring and periodic review are planned",
|
|
31
|
+
description: "Mechanisms exist to monitor AI systems and detect drift in tools, models, and agent behavior over time.",
|
|
32
|
+
keywords: ["monitoring", "review", "drift", "ongoing"],
|
|
33
|
+
findingCategories: ["tool-drift", "manifest-drift"],
|
|
34
|
+
severityThreshold: "medium",
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: "GOVERN-6.1",
|
|
38
|
+
framework: "NIST-AI-RMF",
|
|
39
|
+
category: "GOVERN",
|
|
40
|
+
title: "Third-party risks are managed",
|
|
41
|
+
description: "Risks associated with third-party models, datasets, tools, and software (including MCP servers) are identified and managed.",
|
|
42
|
+
keywords: ["third party", "supply chain", "vendor", "external"],
|
|
43
|
+
findingCategories: ["supply-chain-vuln", "unsigned-change"],
|
|
44
|
+
severityThreshold: "medium",
|
|
45
|
+
},
|
|
46
|
+
// MAP — context and risk identification
|
|
47
|
+
{
|
|
48
|
+
id: "MAP-1.1",
|
|
49
|
+
framework: "NIST-AI-RMF",
|
|
50
|
+
category: "MAP",
|
|
51
|
+
title: "Intended purpose and context are established",
|
|
52
|
+
description: "The AI system's intended purpose, scope, and operating context — including the bounds of agent autonomy — are documented.",
|
|
53
|
+
keywords: ["intended use", "context", "scope", "autonomy"],
|
|
54
|
+
findingCategories: ["excessive-agency", "overreliance"],
|
|
55
|
+
severityThreshold: "medium",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
id: "MAP-5.1",
|
|
59
|
+
framework: "NIST-AI-RMF",
|
|
60
|
+
category: "MAP",
|
|
61
|
+
title: "Impacts to individuals and society are characterized",
|
|
62
|
+
description: "Likelihood and magnitude of impacts, including privacy and data-exposure harms, are identified.",
|
|
63
|
+
keywords: ["impact", "privacy", "harm", "exposure"],
|
|
64
|
+
findingCategories: ["pii-exposure", "sensitive-disclosure"],
|
|
65
|
+
severityThreshold: "medium",
|
|
66
|
+
},
|
|
67
|
+
// MEASURE — trustworthiness characteristics
|
|
68
|
+
{
|
|
69
|
+
id: "MEASURE-2.6",
|
|
70
|
+
framework: "NIST-AI-RMF",
|
|
71
|
+
category: "MEASURE",
|
|
72
|
+
title: "AI system is evaluated for safety and security/resilience",
|
|
73
|
+
description: "The AI system is tested for resistance to adversarial manipulation, including prompt injection and insecure output handling.",
|
|
74
|
+
keywords: ["security", "resilience", "adversarial", "prompt injection", "robustness"],
|
|
75
|
+
findingCategories: ["prompt-injection", "insecure-output", "model-denial-of-service"],
|
|
76
|
+
cweIds: ["CWE-77", "CWE-94"],
|
|
77
|
+
severityThreshold: "high",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: "MEASURE-2.7",
|
|
81
|
+
framework: "NIST-AI-RMF",
|
|
82
|
+
category: "MEASURE",
|
|
83
|
+
title: "AI system security and data exfiltration risks are assessed",
|
|
84
|
+
description: "Paths by which secrets or sensitive data could be exfiltrated through the AI system are assessed and mitigated.",
|
|
85
|
+
keywords: ["exfiltration", "data leak", "secret", "credential"],
|
|
86
|
+
findingCategories: ["exfil-path", "hardcoded-secret", "credential-overscoped"],
|
|
87
|
+
severityThreshold: "high",
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
id: "MEASURE-2.9",
|
|
91
|
+
framework: "NIST-AI-RMF",
|
|
92
|
+
category: "MEASURE",
|
|
93
|
+
title: "AI model is explainable and decisions are traceable",
|
|
94
|
+
description: "Mechanisms exist to trace and explain AI system decisions, supported by tamper-evident records.",
|
|
95
|
+
keywords: ["explainability", "traceability", "provenance", "audit"],
|
|
96
|
+
findingCategories: ["unsigned-change", "consensus-manipulation"],
|
|
97
|
+
severityThreshold: "medium",
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: "MEASURE-2.10",
|
|
101
|
+
framework: "NIST-AI-RMF",
|
|
102
|
+
category: "MEASURE",
|
|
103
|
+
title: "Privacy risk is assessed",
|
|
104
|
+
description: "Privacy risks, including exposure of personal data through model inputs or outputs, are measured.",
|
|
105
|
+
keywords: ["privacy", "pii", "personal data"],
|
|
106
|
+
findingCategories: ["pii-exposure"],
|
|
107
|
+
severityThreshold: "high",
|
|
108
|
+
},
|
|
109
|
+
// MANAGE — risk treatment and response
|
|
110
|
+
{
|
|
111
|
+
id: "MANAGE-2.2",
|
|
112
|
+
framework: "NIST-AI-RMF",
|
|
113
|
+
category: "MANAGE",
|
|
114
|
+
title: "Mechanisms to mitigate identified risks are applied",
|
|
115
|
+
description: "Controls (least privilege, sandboxing, scoping) are applied to mitigate risks from agent tools and permissions.",
|
|
116
|
+
keywords: ["mitigation", "least privilege", "sandbox", "scope", "permission"],
|
|
117
|
+
findingCategories: ["overscoped-permission", "missing-sandbox", "excessive-agency"],
|
|
118
|
+
cweIds: ["CWE-250", "CWE-269"],
|
|
119
|
+
severityThreshold: "high",
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: "MANAGE-4.1",
|
|
123
|
+
framework: "NIST-AI-RMF",
|
|
124
|
+
category: "MANAGE",
|
|
125
|
+
title: "Post-deployment monitoring and incident response are in place",
|
|
126
|
+
description: "AI systems are monitored after deployment for emergent risks, with response mechanisms for detected issues.",
|
|
127
|
+
keywords: ["post-deployment", "incident response", "monitoring", "emergent"],
|
|
128
|
+
findingCategories: ["insecure-plugin", "model-theft"],
|
|
129
|
+
severityThreshold: "medium",
|
|
130
|
+
},
|
|
131
|
+
];
|
|
132
|
+
/** Get all NIST AI RMF controls. */
|
|
133
|
+
export function getNISTAIRMFControls() {
|
|
134
|
+
return NIST_AI_RMF_CONTROLS;
|
|
135
|
+
}
|
|
136
|
+
/** Get NIST AI RMF controls for a given function (GOVERN/MAP/MEASURE/MANAGE). */
|
|
137
|
+
export function getNISTAIRMFControlsByFunction(fn) {
|
|
138
|
+
return NIST_AI_RMF_CONTROLS.filter((c) => c.category === fn);
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=nist-ai-rmf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nist-ai-rmf.js","sourceRoot":"","sources":["../../src/compliance/nist-ai-rmf.ts"],"names":[],"mappings":"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"}
|
package/dist/config/flags.d.ts
CHANGED
|
@@ -306,14 +306,14 @@ export declare const VasperaConfigSchema: z.ZodObject<{
|
|
|
306
306
|
configs: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
307
307
|
}, "strip", z.ZodTypeAny, {
|
|
308
308
|
configs: Record<string, Record<string, unknown>>;
|
|
309
|
+
sandbox: boolean;
|
|
309
310
|
loadLocal: boolean;
|
|
310
311
|
loadNpm: boolean;
|
|
311
|
-
sandbox: boolean;
|
|
312
312
|
}, {
|
|
313
313
|
configs?: Record<string, Record<string, unknown>> | undefined;
|
|
314
|
+
sandbox?: boolean | undefined;
|
|
314
315
|
loadLocal?: boolean | undefined;
|
|
315
316
|
loadNpm?: boolean | undefined;
|
|
316
|
-
sandbox?: boolean | undefined;
|
|
317
317
|
}>>;
|
|
318
318
|
}, "strip", z.ZodTypeAny, {
|
|
319
319
|
version: 1;
|
|
@@ -332,9 +332,9 @@ export declare const VasperaConfigSchema: z.ZodObject<{
|
|
|
332
332
|
}>;
|
|
333
333
|
plugins: {
|
|
334
334
|
configs: Record<string, Record<string, unknown>>;
|
|
335
|
+
sandbox: boolean;
|
|
335
336
|
loadLocal: boolean;
|
|
336
337
|
loadNpm: boolean;
|
|
337
|
-
sandbox: boolean;
|
|
338
338
|
};
|
|
339
339
|
cost: {
|
|
340
340
|
warningThreshold: number;
|
|
@@ -380,9 +380,9 @@ export declare const VasperaConfigSchema: z.ZodObject<{
|
|
|
380
380
|
}> | undefined;
|
|
381
381
|
plugins?: {
|
|
382
382
|
configs?: Record<string, Record<string, unknown>> | undefined;
|
|
383
|
+
sandbox?: boolean | undefined;
|
|
383
384
|
loadLocal?: boolean | undefined;
|
|
384
385
|
loadNpm?: boolean | undefined;
|
|
385
|
-
sandbox?: boolean | undefined;
|
|
386
386
|
} | undefined;
|
|
387
387
|
cost?: {
|
|
388
388
|
maxBudget?: number | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/eval/fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/eval/fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAAW,EAgG7C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,WAAW,EA+HpC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,WAAW,EAmGxC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,WAAW,EA+F3C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,WAAW,EA6CrC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAAW,EA4D9C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,EAAE,WAAW,EAmFjD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,WAAW,EA4FrC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,WAAW,EA6CpC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,+BAA+B,EAAE,WAAW,EA0FxD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,WAAW,EA4G1C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,WAAW,EAYrC,CAAC;AAEF;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE,CAErE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,EAAE,CAE3D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAElE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;CACvB,CAcA"}
|
package/dist/eval/fixtures.js
CHANGED
|
@@ -21,31 +21,33 @@ export const sqlInjectionFixtures = [
|
|
|
21
21
|
path: "db.ts",
|
|
22
22
|
language: "typescript",
|
|
23
23
|
content: `import { Pool } from 'pg';
|
|
24
|
+
import express from 'express';
|
|
24
25
|
|
|
25
26
|
const pool = new Pool();
|
|
27
|
+
const app = express();
|
|
26
28
|
|
|
27
|
-
// VULNERABLE:
|
|
28
|
-
|
|
29
|
+
// VULNERABLE: request input concatenated into a SQL query
|
|
30
|
+
app.get('/users', (req, res) => {
|
|
31
|
+
const name = req.query.name;
|
|
29
32
|
const query = "SELECT * FROM users WHERE name = '" + name + "'";
|
|
30
|
-
|
|
31
|
-
}
|
|
33
|
+
pool.query(query).then((r) => res.json(r.rows));
|
|
34
|
+
});
|
|
32
35
|
|
|
33
|
-
// SAFE:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
36
|
+
// SAFE: parameterized query
|
|
37
|
+
app.get('/user', (req, res) => {
|
|
38
|
+
pool.query("SELECT * FROM users WHERE id = $1", [req.query.id]);
|
|
39
|
+
});
|
|
38
40
|
`,
|
|
39
41
|
},
|
|
40
42
|
],
|
|
41
43
|
expectedFindings: [
|
|
42
44
|
{
|
|
43
45
|
file: "db.ts",
|
|
44
|
-
line:
|
|
46
|
+
line: 12,
|
|
45
47
|
severity: "critical",
|
|
46
48
|
category: "sql-injection",
|
|
47
49
|
cweId: "CWE-89",
|
|
48
|
-
description: "SQL injection via string concatenation",
|
|
50
|
+
description: "SQL injection via string concatenation of request input",
|
|
49
51
|
isVulnerable: true,
|
|
50
52
|
},
|
|
51
53
|
],
|
|
@@ -62,25 +64,29 @@ export async function getUserById(id: number) {
|
|
|
62
64
|
path: "search.ts",
|
|
63
65
|
language: "typescript",
|
|
64
66
|
content: `import { db } from './connection';
|
|
67
|
+
import express from 'express';
|
|
68
|
+
|
|
69
|
+
const app = express();
|
|
65
70
|
|
|
66
|
-
// VULNERABLE:
|
|
67
|
-
|
|
71
|
+
// VULNERABLE: template-literal injection from request input
|
|
72
|
+
app.get('/search', (req, res) => {
|
|
73
|
+
const term = req.query.term;
|
|
68
74
|
const sql = \`SELECT * FROM products WHERE name LIKE '%\${term}%'\`;
|
|
69
|
-
|
|
70
|
-
}
|
|
75
|
+
db.query(sql).then((r) => res.json(r));
|
|
76
|
+
});
|
|
71
77
|
|
|
72
|
-
// VULNERABLE:
|
|
73
|
-
|
|
74
|
-
const sql = \`SELECT * FROM users ORDER BY \${sortBy}\`;
|
|
75
|
-
|
|
76
|
-
}
|
|
78
|
+
// VULNERABLE: dynamic ORDER BY from request input
|
|
79
|
+
app.get('/list', (req, res) => {
|
|
80
|
+
const sql = \`SELECT * FROM users ORDER BY \${req.query.sortBy}\`;
|
|
81
|
+
db.query(sql);
|
|
82
|
+
});
|
|
77
83
|
`,
|
|
78
84
|
},
|
|
79
85
|
],
|
|
80
86
|
expectedFindings: [
|
|
81
87
|
{
|
|
82
88
|
file: "search.ts",
|
|
83
|
-
line:
|
|
89
|
+
line: 9,
|
|
84
90
|
severity: "critical",
|
|
85
91
|
category: "sql-injection",
|
|
86
92
|
cweId: "CWE-89",
|
|
@@ -89,7 +95,7 @@ export async function listUsers(sortBy: string) {
|
|
|
89
95
|
},
|
|
90
96
|
{
|
|
91
97
|
file: "search.ts",
|
|
92
|
-
line:
|
|
98
|
+
line: 15,
|
|
93
99
|
severity: "high",
|
|
94
100
|
category: "sql-injection",
|
|
95
101
|
cweId: "CWE-89",
|
|
@@ -165,46 +171,66 @@ export function SafeProfile({ bio }: Props) {
|
|
|
165
171
|
{
|
|
166
172
|
path: "comment.ts",
|
|
167
173
|
language: "typescript",
|
|
168
|
-
content:
|
|
169
|
-
export function renderComment(userComment: string) {
|
|
170
|
-
const container = document.getElementById('comments');
|
|
171
|
-
if (container) {
|
|
172
|
-
container.innerHTML = userComment;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
174
|
+
content: `import express from 'express';
|
|
175
175
|
|
|
176
|
-
|
|
177
|
-
export function writeMessage(message: string) {
|
|
178
|
-
document.write('<div>' + message + '</div>');
|
|
179
|
-
}
|
|
176
|
+
const app = express();
|
|
180
177
|
|
|
181
|
-
//
|
|
182
|
-
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
178
|
+
// VULNERABLE: Reflected XSS via res.send with unescaped req.query
|
|
179
|
+
app.get('/comment', (req, res) => {
|
|
180
|
+
const userComment = req.query.text;
|
|
181
|
+
res.send('<div>' + userComment + '</div>');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// VULNERABLE: Reflected XSS via res.write with unescaped req.query
|
|
185
|
+
app.get('/message', (req, res) => {
|
|
186
|
+
const message = req.query.msg;
|
|
187
|
+
res.write('<div>' + message + '</div>');
|
|
188
|
+
res.end();
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// SAFE: JSON response, not HTML
|
|
192
|
+
app.get('/safe-comment', (req, res) => {
|
|
193
|
+
const userComment = req.query.text;
|
|
194
|
+
res.json({ comment: userComment });
|
|
195
|
+
});
|
|
188
196
|
`,
|
|
189
197
|
},
|
|
190
198
|
],
|
|
191
199
|
expectedFindings: [
|
|
192
200
|
{
|
|
193
201
|
file: "comment.ts",
|
|
194
|
-
line:
|
|
202
|
+
line: 8,
|
|
195
203
|
severity: "high",
|
|
196
204
|
category: "xss",
|
|
197
205
|
cweId: "CWE-79",
|
|
198
|
-
description: "XSS via
|
|
206
|
+
description: "Reflected XSS via res.send with unescaped request input",
|
|
199
207
|
isVulnerable: true,
|
|
200
208
|
},
|
|
201
209
|
{
|
|
202
210
|
file: "comment.ts",
|
|
203
|
-
line:
|
|
211
|
+
line: 8,
|
|
212
|
+
severity: "high",
|
|
213
|
+
category: "xss",
|
|
214
|
+
cweId: "CWE-79",
|
|
215
|
+
description: "Reflected XSS: unsanitized request input written to HTTP response",
|
|
216
|
+
isVulnerable: true,
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
file: "comment.ts",
|
|
220
|
+
line: 14,
|
|
221
|
+
severity: "high",
|
|
222
|
+
category: "xss",
|
|
223
|
+
cweId: "CWE-79",
|
|
224
|
+
description: "Reflected XSS via res.write with unescaped request input",
|
|
225
|
+
isVulnerable: true,
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
file: "comment.ts",
|
|
229
|
+
line: 14,
|
|
204
230
|
severity: "high",
|
|
205
231
|
category: "xss",
|
|
206
232
|
cweId: "CWE-79",
|
|
207
|
-
description: "XSS
|
|
233
|
+
description: "Reflected XSS: unsanitized request input streamed to HTTP response",
|
|
208
234
|
isVulnerable: true,
|
|
209
235
|
},
|
|
210
236
|
],
|
|
@@ -477,46 +503,49 @@ export const pathTraversalFixtures = [
|
|
|
477
503
|
path: "files.ts",
|
|
478
504
|
language: "typescript",
|
|
479
505
|
content: `import { readFile } from 'fs/promises';
|
|
506
|
+
import { createReadStream } from 'fs';
|
|
480
507
|
import { join } from 'path';
|
|
508
|
+
import express from 'express';
|
|
509
|
+
|
|
510
|
+
const app = express();
|
|
481
511
|
|
|
482
512
|
// VULNERABLE: Direct user input in path
|
|
483
|
-
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
}
|
|
513
|
+
app.get('/file', (req, res) => {
|
|
514
|
+
const filename = req.query.name as string;
|
|
515
|
+
readFile(filename, 'utf-8').then((content) => res.send(content));
|
|
516
|
+
});
|
|
487
517
|
|
|
488
|
-
// VULNERABLE: Path traversal
|
|
489
|
-
|
|
490
|
-
const
|
|
491
|
-
|
|
492
|
-
|
|
518
|
+
// VULNERABLE: Path traversal via join with user input
|
|
519
|
+
app.get('/document', (req, res) => {
|
|
520
|
+
const docName = req.query.doc as string;
|
|
521
|
+
const filePath = join('./documents', docName);
|
|
522
|
+
createReadStream(filePath).pipe(res);
|
|
523
|
+
});
|
|
493
524
|
|
|
494
|
-
// SAFE:
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
525
|
+
// SAFE: Fixed allowlist of known files, no user input in path
|
|
526
|
+
const ALLOWED_FILES: Record<string, string> = {
|
|
527
|
+
readme: './uploads/readme.txt',
|
|
528
|
+
license: './uploads/license.txt',
|
|
529
|
+
};
|
|
530
|
+
app.get('/upload', (req, res) => {
|
|
531
|
+
const key = req.query.name as string;
|
|
532
|
+
const safePath = ALLOWED_FILES[key];
|
|
533
|
+
if (!safePath) {
|
|
534
|
+
return res.status(404).send('Not found');
|
|
535
|
+
}
|
|
536
|
+
readFile(safePath, 'utf-8').then((content) => res.send(content));
|
|
537
|
+
});
|
|
500
538
|
`,
|
|
501
539
|
},
|
|
502
540
|
],
|
|
503
541
|
expectedFindings: [
|
|
504
542
|
{
|
|
505
543
|
file: "files.ts",
|
|
506
|
-
line:
|
|
507
|
-
severity: "high",
|
|
508
|
-
category: "path-traversal",
|
|
509
|
-
cweId: "CWE-22",
|
|
510
|
-
description: "Path traversal via direct user input",
|
|
511
|
-
isVulnerable: true,
|
|
512
|
-
},
|
|
513
|
-
{
|
|
514
|
-
file: "files.ts",
|
|
515
|
-
line: 12,
|
|
544
|
+
line: 17,
|
|
516
545
|
severity: "high",
|
|
517
546
|
category: "path-traversal",
|
|
518
547
|
cweId: "CWE-22",
|
|
519
|
-
description: "Path traversal via
|
|
548
|
+
description: "Path traversal via path.join with unvalidated request input",
|
|
520
549
|
isVulnerable: true,
|
|
521
550
|
},
|
|
522
551
|
],
|
|
@@ -537,25 +566,28 @@ export const commandInjectionFixtures = [
|
|
|
537
566
|
{
|
|
538
567
|
path: "utils/git.ts",
|
|
539
568
|
language: "typescript",
|
|
540
|
-
content: `import { exec } from 'child_process';
|
|
569
|
+
content: `import { exec, spawn } from 'child_process';
|
|
570
|
+
import express from 'express';
|
|
541
571
|
|
|
542
|
-
|
|
543
|
-
export function cloneRepo(repoUrl: string) {
|
|
544
|
-
exec(\`git clone \${repoUrl}\`);
|
|
545
|
-
}
|
|
572
|
+
const app = express();
|
|
546
573
|
|
|
547
|
-
//
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
}
|
|
574
|
+
// VULNERABLE: request input concatenated into a shell command
|
|
575
|
+
app.get('/clone', (req, res) => {
|
|
576
|
+
const repoUrl = req.query.repo;
|
|
577
|
+
exec(\`git clone \${repoUrl}\`, (err) => res.sendStatus(err ? 500 : 200));
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
// SAFE: array-based spawn, no shell interpolation
|
|
581
|
+
app.get('/clone-safe', (req, res) => {
|
|
582
|
+
spawn('git', ['clone', String(req.query.repo)]);
|
|
583
|
+
});
|
|
552
584
|
`,
|
|
553
585
|
},
|
|
554
586
|
],
|
|
555
587
|
expectedFindings: [
|
|
556
588
|
{
|
|
557
589
|
file: "utils/git.ts",
|
|
558
|
-
line:
|
|
590
|
+
line: 8,
|
|
559
591
|
severity: "critical",
|
|
560
592
|
category: "command-injection",
|
|
561
593
|
cweId: "CWE-78",
|
|
@@ -567,36 +599,40 @@ export function cloneRepoSafe(repoUrl: string) {
|
|
|
567
599
|
},
|
|
568
600
|
{
|
|
569
601
|
id: "cmd-002",
|
|
570
|
-
name: "
|
|
571
|
-
description: "Command injection via
|
|
602
|
+
name: "exec with request input",
|
|
603
|
+
description: "Command injection via child_process.exec with request input",
|
|
572
604
|
category: "command-injection",
|
|
573
605
|
source: "custom",
|
|
574
606
|
files: [
|
|
575
607
|
{
|
|
576
608
|
path: "services/deploy.ts",
|
|
577
609
|
language: "typescript",
|
|
578
|
-
content: `import {
|
|
610
|
+
content: `import { exec } from 'child_process';
|
|
611
|
+
import express from 'express';
|
|
579
612
|
|
|
580
|
-
|
|
581
|
-
export function runScript(scriptName: string) {
|
|
582
|
-
spawn(\`./scripts/\${scriptName}.sh\`, { shell: true });
|
|
583
|
-
}
|
|
613
|
+
const app = express();
|
|
584
614
|
|
|
585
|
-
//
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
615
|
+
// VULNERABLE: request input flows into exec
|
|
616
|
+
app.post('/run', (req, res) => {
|
|
617
|
+
const scriptName = req.body.script;
|
|
618
|
+
exec('./scripts/' + scriptName + '.sh', (err) => res.sendStatus(err ? 500 : 200));
|
|
619
|
+
});
|
|
620
|
+
|
|
621
|
+
// SAFE: fixed command
|
|
622
|
+
app.post('/run-safe', (_req, res) => {
|
|
623
|
+
exec('./scripts/run.sh', () => res.sendStatus(200));
|
|
624
|
+
});
|
|
589
625
|
`,
|
|
590
626
|
},
|
|
591
627
|
],
|
|
592
628
|
expectedFindings: [
|
|
593
629
|
{
|
|
594
630
|
file: "services/deploy.ts",
|
|
595
|
-
line:
|
|
631
|
+
line: 9,
|
|
596
632
|
severity: "critical",
|
|
597
633
|
category: "command-injection",
|
|
598
634
|
cweId: "CWE-78",
|
|
599
|
-
description: "
|
|
635
|
+
description: "Command injection via request input in exec",
|
|
600
636
|
isVulnerable: true,
|
|
601
637
|
},
|
|
602
638
|
],
|
|
@@ -617,28 +653,32 @@ export const ssrfFixtures = [
|
|
|
617
653
|
{
|
|
618
654
|
path: "api/proxy.ts",
|
|
619
655
|
language: "typescript",
|
|
620
|
-
content:
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
656
|
+
content: `import express from 'express';
|
|
657
|
+
|
|
658
|
+
const app = express();
|
|
659
|
+
|
|
660
|
+
// VULNERABLE: request-controlled URL passed straight to fetch
|
|
661
|
+
app.get('/proxy', async (req, res) => {
|
|
662
|
+
const response = await fetch(req.query.url);
|
|
663
|
+
res.json(await response.json());
|
|
664
|
+
});
|
|
625
665
|
|
|
626
666
|
// SAFE: URL allowlist
|
|
627
667
|
const ALLOWED_HOSTS = ['api.example.com', 'cdn.example.com'];
|
|
628
|
-
|
|
629
|
-
const parsed = new URL(url);
|
|
668
|
+
app.get('/proxy-safe', async (req, res) => {
|
|
669
|
+
const parsed = new URL(String(req.query.url));
|
|
630
670
|
if (!ALLOWED_HOSTS.includes(parsed.host)) {
|
|
631
|
-
|
|
671
|
+
return res.status(400).end();
|
|
632
672
|
}
|
|
633
|
-
|
|
634
|
-
}
|
|
673
|
+
res.json(await (await fetch('https://api.example.com')).json());
|
|
674
|
+
});
|
|
635
675
|
`,
|
|
636
676
|
},
|
|
637
677
|
],
|
|
638
678
|
expectedFindings: [
|
|
639
679
|
{
|
|
640
680
|
file: "api/proxy.ts",
|
|
641
|
-
line:
|
|
681
|
+
line: 7,
|
|
642
682
|
severity: "high",
|
|
643
683
|
category: "ssrf",
|
|
644
684
|
cweId: "CWE-918",
|
|
@@ -659,30 +699,32 @@ export async function proxyRequestSafe(url: string) {
|
|
|
659
699
|
path: "services/webhook.ts",
|
|
660
700
|
language: "typescript",
|
|
661
701
|
content: `import axios from 'axios';
|
|
702
|
+
import express from 'express';
|
|
662
703
|
|
|
663
|
-
|
|
664
|
-
export async function callWebhook(webhookUrl: string, payload: object) {
|
|
665
|
-
const response = await axios.post(webhookUrl, payload, {
|
|
666
|
-
maxRedirects: 5, // Can redirect to internal networks
|
|
667
|
-
});
|
|
668
|
-
return response.data;
|
|
669
|
-
}
|
|
704
|
+
const app = express();
|
|
670
705
|
|
|
671
|
-
//
|
|
672
|
-
|
|
673
|
-
const
|
|
706
|
+
// VULNERABLE: request-controlled webhook URL
|
|
707
|
+
app.post('/webhook', async (req, res) => {
|
|
708
|
+
const webhookUrl = req.body.url;
|
|
709
|
+
const response = await axios.post(webhookUrl, req.body.payload);
|
|
710
|
+
res.json(response.data);
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
// SAFE: validate URL against internal ranges first
|
|
714
|
+
app.post('/webhook-safe', async (req, res) => {
|
|
715
|
+
const url = new URL(String(req.body.url));
|
|
674
716
|
if (url.hostname === 'localhost' || url.hostname.startsWith('192.168.')) {
|
|
675
|
-
|
|
717
|
+
return res.status(400).end();
|
|
676
718
|
}
|
|
677
|
-
|
|
678
|
-
}
|
|
719
|
+
res.json((await axios.post('https://hooks.example.com', req.body.payload)).data);
|
|
720
|
+
});
|
|
679
721
|
`,
|
|
680
722
|
},
|
|
681
723
|
],
|
|
682
724
|
expectedFindings: [
|
|
683
725
|
{
|
|
684
726
|
file: "services/webhook.ts",
|
|
685
|
-
line:
|
|
727
|
+
line: 9,
|
|
686
728
|
severity: "high",
|
|
687
729
|
category: "ssrf",
|
|
688
730
|
cweId: "CWE-918",
|