@oculum/scanner 1.0.9 → 1.0.11
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/dist/baseline/diff.d.ts +32 -0
- package/dist/baseline/diff.d.ts.map +1 -0
- package/dist/baseline/diff.js +119 -0
- package/dist/baseline/diff.js.map +1 -0
- package/dist/baseline/index.d.ts +9 -0
- package/dist/baseline/index.d.ts.map +1 -0
- package/dist/baseline/index.js +19 -0
- package/dist/baseline/index.js.map +1 -0
- package/dist/baseline/manager.d.ts +67 -0
- package/dist/baseline/manager.d.ts.map +1 -0
- package/dist/baseline/manager.js +180 -0
- package/dist/baseline/manager.js.map +1 -0
- package/dist/baseline/types.d.ts +91 -0
- package/dist/baseline/types.d.ts.map +1 -0
- package/dist/baseline/types.js +12 -0
- package/dist/baseline/types.js.map +1 -0
- package/dist/formatters/cli-terminal.d.ts +38 -0
- package/dist/formatters/cli-terminal.d.ts.map +1 -1
- package/dist/formatters/cli-terminal.js +365 -42
- package/dist/formatters/cli-terminal.js.map +1 -1
- package/dist/formatters/github-comment.d.ts +1 -1
- package/dist/formatters/github-comment.d.ts.map +1 -1
- package/dist/formatters/github-comment.js +75 -11
- package/dist/formatters/github-comment.js.map +1 -1
- package/dist/formatters/index.d.ts +1 -1
- package/dist/formatters/index.d.ts.map +1 -1
- package/dist/formatters/index.js +4 -1
- package/dist/formatters/index.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +155 -16
- package/dist/index.js.map +1 -1
- package/dist/layer1/config-audit.d.ts.map +1 -1
- package/dist/layer1/config-audit.js +20 -3
- package/dist/layer1/config-audit.js.map +1 -1
- package/dist/layer1/config-mcp-audit.d.ts +20 -0
- package/dist/layer1/config-mcp-audit.d.ts.map +1 -0
- package/dist/layer1/config-mcp-audit.js +239 -0
- package/dist/layer1/config-mcp-audit.js.map +1 -0
- package/dist/layer1/index.d.ts +1 -0
- package/dist/layer1/index.d.ts.map +1 -1
- package/dist/layer1/index.js +9 -1
- package/dist/layer1/index.js.map +1 -1
- package/dist/layer2/ai-agent-tools.d.ts.map +1 -1
- package/dist/layer2/ai-agent-tools.js +303 -0
- package/dist/layer2/ai-agent-tools.js.map +1 -1
- package/dist/layer2/ai-endpoint-protection.d.ts.map +1 -1
- package/dist/layer2/ai-endpoint-protection.js +17 -3
- package/dist/layer2/ai-endpoint-protection.js.map +1 -1
- package/dist/layer2/ai-execution-sinks.d.ts.map +1 -1
- package/dist/layer2/ai-execution-sinks.js +462 -12
- package/dist/layer2/ai-execution-sinks.js.map +1 -1
- package/dist/layer2/ai-fingerprinting.d.ts.map +1 -1
- package/dist/layer2/ai-fingerprinting.js +3 -0
- package/dist/layer2/ai-fingerprinting.js.map +1 -1
- package/dist/layer2/ai-mcp-security.d.ts +17 -0
- package/dist/layer2/ai-mcp-security.d.ts.map +1 -0
- package/dist/layer2/ai-mcp-security.js +679 -0
- package/dist/layer2/ai-mcp-security.js.map +1 -0
- package/dist/layer2/ai-package-hallucination.d.ts +19 -0
- package/dist/layer2/ai-package-hallucination.d.ts.map +1 -0
- package/dist/layer2/ai-package-hallucination.js +696 -0
- package/dist/layer2/ai-package-hallucination.js.map +1 -0
- package/dist/layer2/ai-prompt-hygiene.d.ts.map +1 -1
- package/dist/layer2/ai-prompt-hygiene.js +495 -9
- package/dist/layer2/ai-prompt-hygiene.js.map +1 -1
- package/dist/layer2/ai-rag-safety.d.ts.map +1 -1
- package/dist/layer2/ai-rag-safety.js +372 -1
- package/dist/layer2/ai-rag-safety.js.map +1 -1
- package/dist/layer2/auth-antipatterns.d.ts.map +1 -1
- package/dist/layer2/auth-antipatterns.js +4 -0
- package/dist/layer2/auth-antipatterns.js.map +1 -1
- package/dist/layer2/byok-patterns.d.ts.map +1 -1
- package/dist/layer2/byok-patterns.js +3 -0
- package/dist/layer2/byok-patterns.js.map +1 -1
- package/dist/layer2/dangerous-functions/child-process.d.ts +16 -0
- package/dist/layer2/dangerous-functions/child-process.d.ts.map +1 -0
- package/dist/layer2/dangerous-functions/child-process.js +74 -0
- package/dist/layer2/dangerous-functions/child-process.js.map +1 -0
- package/dist/layer2/dangerous-functions/dom-xss.d.ts +29 -0
- package/dist/layer2/dangerous-functions/dom-xss.d.ts.map +1 -0
- package/dist/layer2/dangerous-functions/dom-xss.js +179 -0
- package/dist/layer2/dangerous-functions/dom-xss.js.map +1 -0
- package/dist/layer2/dangerous-functions/index.d.ts +13 -0
- package/dist/layer2/dangerous-functions/index.d.ts.map +1 -0
- package/dist/layer2/dangerous-functions/index.js +621 -0
- package/dist/layer2/dangerous-functions/index.js.map +1 -0
- package/dist/layer2/dangerous-functions/json-parse.d.ts +31 -0
- package/dist/layer2/dangerous-functions/json-parse.d.ts.map +1 -0
- package/dist/layer2/dangerous-functions/json-parse.js +319 -0
- package/dist/layer2/dangerous-functions/json-parse.js.map +1 -0
- package/dist/layer2/dangerous-functions/math-random.d.ts +61 -0
- package/dist/layer2/dangerous-functions/math-random.d.ts.map +1 -0
- package/dist/layer2/dangerous-functions/math-random.js +459 -0
- package/dist/layer2/dangerous-functions/math-random.js.map +1 -0
- package/dist/layer2/dangerous-functions/patterns.d.ts +21 -0
- package/dist/layer2/dangerous-functions/patterns.d.ts.map +1 -0
- package/dist/layer2/dangerous-functions/patterns.js +161 -0
- package/dist/layer2/dangerous-functions/patterns.js.map +1 -0
- package/dist/layer2/dangerous-functions/request-validation.d.ts +13 -0
- package/dist/layer2/dangerous-functions/request-validation.d.ts.map +1 -0
- package/dist/layer2/dangerous-functions/request-validation.js +119 -0
- package/dist/layer2/dangerous-functions/request-validation.js.map +1 -0
- package/dist/layer2/dangerous-functions/utils/control-flow.d.ts +23 -0
- package/dist/layer2/dangerous-functions/utils/control-flow.d.ts.map +1 -0
- package/dist/layer2/dangerous-functions/utils/control-flow.js +149 -0
- package/dist/layer2/dangerous-functions/utils/control-flow.js.map +1 -0
- package/dist/layer2/dangerous-functions/utils/helpers.d.ts +31 -0
- package/dist/layer2/dangerous-functions/utils/helpers.d.ts.map +1 -0
- package/dist/layer2/dangerous-functions/utils/helpers.js +124 -0
- package/dist/layer2/dangerous-functions/utils/helpers.js.map +1 -0
- package/dist/layer2/dangerous-functions/utils/index.d.ts +9 -0
- package/dist/layer2/dangerous-functions/utils/index.d.ts.map +1 -0
- package/dist/layer2/dangerous-functions/utils/index.js +23 -0
- package/dist/layer2/dangerous-functions/utils/index.js.map +1 -0
- package/dist/layer2/dangerous-functions/utils/schema-validation.d.ts +22 -0
- package/dist/layer2/dangerous-functions/utils/schema-validation.d.ts.map +1 -0
- package/dist/layer2/dangerous-functions/utils/schema-validation.js +89 -0
- package/dist/layer2/dangerous-functions/utils/schema-validation.js.map +1 -0
- package/dist/layer2/data-exposure.d.ts.map +1 -1
- package/dist/layer2/data-exposure.js +3 -0
- package/dist/layer2/data-exposure.js.map +1 -1
- package/dist/layer2/framework-checks.d.ts.map +1 -1
- package/dist/layer2/framework-checks.js +3 -0
- package/dist/layer2/framework-checks.js.map +1 -1
- package/dist/layer2/index.d.ts +3 -0
- package/dist/layer2/index.d.ts.map +1 -1
- package/dist/layer2/index.js +61 -2
- package/dist/layer2/index.js.map +1 -1
- package/dist/layer2/logic-gates.d.ts.map +1 -1
- package/dist/layer2/logic-gates.js +4 -0
- package/dist/layer2/logic-gates.js.map +1 -1
- package/dist/layer2/model-supply-chain.d.ts +20 -0
- package/dist/layer2/model-supply-chain.d.ts.map +1 -0
- package/dist/layer2/model-supply-chain.js +376 -0
- package/dist/layer2/model-supply-chain.js.map +1 -0
- package/dist/layer2/risky-imports.d.ts.map +1 -1
- package/dist/layer2/risky-imports.js +4 -0
- package/dist/layer2/risky-imports.js.map +1 -1
- package/dist/layer2/variables.d.ts.map +1 -1
- package/dist/layer2/variables.js +4 -0
- package/dist/layer2/variables.js.map +1 -1
- package/dist/layer3/anthropic/auto-dismiss.d.ts +24 -0
- package/dist/layer3/anthropic/auto-dismiss.d.ts.map +1 -0
- package/dist/layer3/anthropic/auto-dismiss.js +188 -0
- package/dist/layer3/anthropic/auto-dismiss.js.map +1 -0
- package/dist/layer3/anthropic/clients.d.ts +44 -0
- package/dist/layer3/anthropic/clients.d.ts.map +1 -0
- package/dist/layer3/anthropic/clients.js +81 -0
- package/dist/layer3/anthropic/clients.js.map +1 -0
- package/dist/layer3/anthropic/index.d.ts +41 -0
- package/dist/layer3/anthropic/index.d.ts.map +1 -0
- package/dist/layer3/anthropic/index.js +141 -0
- package/dist/layer3/anthropic/index.js.map +1 -0
- package/dist/layer3/anthropic/prompts/index.d.ts +8 -0
- package/dist/layer3/anthropic/prompts/index.d.ts.map +1 -0
- package/dist/layer3/anthropic/prompts/index.js +14 -0
- package/dist/layer3/anthropic/prompts/index.js.map +1 -0
- package/dist/layer3/anthropic/prompts/semantic-analysis.d.ts +15 -0
- package/dist/layer3/anthropic/prompts/semantic-analysis.d.ts.map +1 -0
- package/dist/layer3/anthropic/prompts/semantic-analysis.js +169 -0
- package/dist/layer3/anthropic/prompts/semantic-analysis.js.map +1 -0
- package/dist/layer3/anthropic/prompts/validation.d.ts +12 -0
- package/dist/layer3/anthropic/prompts/validation.d.ts.map +1 -0
- package/dist/layer3/anthropic/prompts/validation.js +421 -0
- package/dist/layer3/anthropic/prompts/validation.js.map +1 -0
- package/dist/layer3/anthropic/providers/anthropic.d.ts +21 -0
- package/dist/layer3/anthropic/providers/anthropic.d.ts.map +1 -0
- package/dist/layer3/anthropic/providers/anthropic.js +266 -0
- package/dist/layer3/anthropic/providers/anthropic.js.map +1 -0
- package/dist/layer3/anthropic/providers/index.d.ts +8 -0
- package/dist/layer3/anthropic/providers/index.d.ts.map +1 -0
- package/dist/layer3/anthropic/providers/index.js +15 -0
- package/dist/layer3/anthropic/providers/index.js.map +1 -0
- package/dist/layer3/anthropic/providers/openai.d.ts +18 -0
- package/dist/layer3/anthropic/providers/openai.d.ts.map +1 -0
- package/dist/layer3/anthropic/providers/openai.js +340 -0
- package/dist/layer3/anthropic/providers/openai.js.map +1 -0
- package/dist/layer3/anthropic/request-builder.d.ts +20 -0
- package/dist/layer3/anthropic/request-builder.d.ts.map +1 -0
- package/dist/layer3/anthropic/request-builder.js +134 -0
- package/dist/layer3/anthropic/request-builder.js.map +1 -0
- package/dist/layer3/anthropic/types.d.ts +88 -0
- package/dist/layer3/anthropic/types.d.ts.map +1 -0
- package/dist/layer3/anthropic/types.js +38 -0
- package/dist/layer3/anthropic/types.js.map +1 -0
- package/dist/layer3/anthropic/utils/index.d.ts +9 -0
- package/dist/layer3/anthropic/utils/index.d.ts.map +1 -0
- package/dist/layer3/anthropic/utils/index.js +24 -0
- package/dist/layer3/anthropic/utils/index.js.map +1 -0
- package/dist/layer3/anthropic/utils/path-helpers.d.ts +21 -0
- package/dist/layer3/anthropic/utils/path-helpers.d.ts.map +1 -0
- package/dist/layer3/anthropic/utils/path-helpers.js +69 -0
- package/dist/layer3/anthropic/utils/path-helpers.js.map +1 -0
- package/dist/layer3/anthropic/utils/response-parser.d.ts +40 -0
- package/dist/layer3/anthropic/utils/response-parser.d.ts.map +1 -0
- package/dist/layer3/anthropic/utils/response-parser.js +285 -0
- package/dist/layer3/anthropic/utils/response-parser.js.map +1 -0
- package/dist/layer3/anthropic/utils/retry.d.ts +15 -0
- package/dist/layer3/anthropic/utils/retry.d.ts.map +1 -0
- package/dist/layer3/anthropic/utils/retry.js +62 -0
- package/dist/layer3/anthropic/utils/retry.js.map +1 -0
- package/dist/layer3/index.d.ts +1 -0
- package/dist/layer3/index.d.ts.map +1 -1
- package/dist/layer3/index.js +16 -6
- package/dist/layer3/index.js.map +1 -1
- package/dist/layer3/osv-check.d.ts +75 -0
- package/dist/layer3/osv-check.d.ts.map +1 -0
- package/dist/layer3/osv-check.js +308 -0
- package/dist/layer3/osv-check.js.map +1 -0
- package/dist/rules/framework-fixes.d.ts +48 -0
- package/dist/rules/framework-fixes.d.ts.map +1 -0
- package/dist/rules/framework-fixes.js +439 -0
- package/dist/rules/framework-fixes.js.map +1 -0
- package/dist/rules/index.d.ts +8 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +18 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/metadata.d.ts +43 -0
- package/dist/rules/metadata.d.ts.map +1 -0
- package/dist/rules/metadata.js +734 -0
- package/dist/rules/metadata.js.map +1 -0
- package/dist/suppression/config-loader.d.ts +74 -0
- package/dist/suppression/config-loader.d.ts.map +1 -0
- package/dist/suppression/config-loader.js +424 -0
- package/dist/suppression/config-loader.js.map +1 -0
- package/dist/suppression/hash.d.ts +48 -0
- package/dist/suppression/hash.d.ts.map +1 -0
- package/dist/suppression/hash.js +88 -0
- package/dist/suppression/hash.js.map +1 -0
- package/dist/suppression/index.d.ts +11 -0
- package/dist/suppression/index.d.ts.map +1 -0
- package/dist/suppression/index.js +39 -0
- package/dist/suppression/index.js.map +1 -0
- package/dist/suppression/inline-parser.d.ts +39 -0
- package/dist/suppression/inline-parser.d.ts.map +1 -0
- package/dist/suppression/inline-parser.js +218 -0
- package/dist/suppression/inline-parser.js.map +1 -0
- package/dist/suppression/manager.d.ts +94 -0
- package/dist/suppression/manager.d.ts.map +1 -0
- package/dist/suppression/manager.js +292 -0
- package/dist/suppression/manager.js.map +1 -0
- package/dist/suppression/types.d.ts +151 -0
- package/dist/suppression/types.d.ts.map +1 -0
- package/dist/suppression/types.js +28 -0
- package/dist/suppression/types.js.map +1 -0
- package/dist/tiers.d.ts +1 -1
- package/dist/tiers.d.ts.map +1 -1
- package/dist/tiers.js +27 -0
- package/dist/tiers.js.map +1 -1
- package/dist/types.d.ts +62 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/context-helpers.d.ts +4 -0
- package/dist/utils/context-helpers.d.ts.map +1 -1
- package/dist/utils/context-helpers.js +13 -9
- package/dist/utils/context-helpers.js.map +1 -1
- package/package.json +4 -2
- package/src/__tests__/benchmark/fixtures/layer1/mcp-config-audit.json +31 -0
- package/src/__tests__/benchmark/fixtures/layer2/ai-execution-sinks.ts +1489 -82
- package/src/__tests__/benchmark/fixtures/layer2/ai-mcp-security.ts +495 -0
- package/src/__tests__/benchmark/fixtures/layer2/ai-package-hallucination.ts +255 -0
- package/src/__tests__/benchmark/fixtures/layer2/ai-prompt-hygiene.ts +300 -1
- package/src/__tests__/benchmark/fixtures/layer2/ai-rag-safety.ts +139 -0
- package/src/__tests__/benchmark/fixtures/layer2/byok-patterns.ts +7 -0
- package/src/__tests__/benchmark/fixtures/layer2/data-exposure.ts +63 -0
- package/src/__tests__/benchmark/fixtures/layer2/excessive-agency.ts +221 -0
- package/src/__tests__/benchmark/fixtures/layer2/index.ts +18 -0
- package/src/__tests__/benchmark/fixtures/layer2/model-supply-chain.ts +204 -0
- package/src/__tests__/benchmark/fixtures/layer2/phase1-enhancements.ts +157 -0
- package/src/__tests__/snapshots/__snapshots__/anthropic-validation-refactor.test.ts.snap +758 -0
- package/src/__tests__/snapshots/__snapshots__/dangerous-functions-refactor.test.ts.snap +503 -0
- package/src/__tests__/snapshots/anthropic-validation-refactor.test.ts +321 -0
- package/src/__tests__/snapshots/dangerous-functions-refactor.test.ts +439 -0
- package/src/baseline/__tests__/diff.test.ts +261 -0
- package/src/baseline/__tests__/manager.test.ts +225 -0
- package/src/baseline/diff.ts +135 -0
- package/src/baseline/index.ts +29 -0
- package/src/baseline/manager.ts +230 -0
- package/src/baseline/types.ts +97 -0
- package/src/formatters/cli-terminal.ts +444 -41
- package/src/formatters/github-comment.ts +79 -11
- package/src/formatters/index.ts +4 -0
- package/src/index.ts +197 -14
- package/src/layer1/config-audit.ts +24 -3
- package/src/layer1/config-mcp-audit.ts +276 -0
- package/src/layer1/index.ts +16 -6
- package/src/layer2/ai-agent-tools.ts +336 -0
- package/src/layer2/ai-endpoint-protection.ts +16 -3
- package/src/layer2/ai-execution-sinks.ts +516 -12
- package/src/layer2/ai-fingerprinting.ts +5 -1
- package/src/layer2/ai-mcp-security.ts +730 -0
- package/src/layer2/ai-package-hallucination.ts +791 -0
- package/src/layer2/ai-prompt-hygiene.ts +547 -9
- package/src/layer2/ai-rag-safety.ts +382 -3
- package/src/layer2/auth-antipatterns.ts +5 -0
- package/src/layer2/byok-patterns.ts +5 -1
- package/src/layer2/dangerous-functions/child-process.ts +98 -0
- package/src/layer2/dangerous-functions/dom-xss.ts +220 -0
- package/src/layer2/dangerous-functions/index.ts +949 -0
- package/src/layer2/dangerous-functions/json-parse.ts +385 -0
- package/src/layer2/dangerous-functions/math-random.ts +537 -0
- package/src/layer2/dangerous-functions/patterns.ts +174 -0
- package/src/layer2/dangerous-functions/request-validation.ts +145 -0
- package/src/layer2/dangerous-functions/utils/control-flow.ts +162 -0
- package/src/layer2/dangerous-functions/utils/helpers.ts +170 -0
- package/src/layer2/dangerous-functions/utils/index.ts +25 -0
- package/src/layer2/dangerous-functions/utils/schema-validation.ts +91 -0
- package/src/layer2/data-exposure.ts +5 -1
- package/src/layer2/framework-checks.ts +5 -0
- package/src/layer2/index.ts +63 -1
- package/src/layer2/logic-gates.ts +5 -0
- package/src/layer2/model-supply-chain.ts +456 -0
- package/src/layer2/risky-imports.ts +5 -0
- package/src/layer2/variables.ts +5 -0
- package/src/layer3/__tests__/osv-check.test.ts +384 -0
- package/src/layer3/anthropic/auto-dismiss.ts +212 -0
- package/src/layer3/anthropic/clients.ts +84 -0
- package/src/layer3/anthropic/index.ts +170 -0
- package/src/layer3/anthropic/prompts/index.ts +14 -0
- package/src/layer3/anthropic/prompts/semantic-analysis.ts +173 -0
- package/src/layer3/anthropic/prompts/validation.ts +419 -0
- package/src/layer3/anthropic/providers/anthropic.ts +310 -0
- package/src/layer3/anthropic/providers/index.ts +8 -0
- package/src/layer3/anthropic/providers/openai.ts +384 -0
- package/src/layer3/anthropic/request-builder.ts +150 -0
- package/src/layer3/anthropic/types.ts +148 -0
- package/src/layer3/anthropic/utils/index.ts +26 -0
- package/src/layer3/anthropic/utils/path-helpers.ts +68 -0
- package/src/layer3/anthropic/utils/response-parser.ts +322 -0
- package/src/layer3/anthropic/utils/retry.ts +75 -0
- package/src/layer3/index.ts +18 -5
- package/src/layer3/osv-check.ts +420 -0
- package/src/rules/__tests__/framework-fixes.test.ts +689 -0
- package/src/rules/__tests__/metadata.test.ts +218 -0
- package/src/rules/framework-fixes.ts +470 -0
- package/src/rules/index.ts +21 -0
- package/src/rules/metadata.ts +831 -0
- package/src/suppression/__tests__/config-loader.test.ts +382 -0
- package/src/suppression/__tests__/hash.test.ts +166 -0
- package/src/suppression/__tests__/inline-parser.test.ts +212 -0
- package/src/suppression/__tests__/manager.test.ts +415 -0
- package/src/suppression/config-loader.ts +462 -0
- package/src/suppression/hash.ts +95 -0
- package/src/suppression/index.ts +51 -0
- package/src/suppression/inline-parser.ts +273 -0
- package/src/suppression/manager.ts +379 -0
- package/src/suppression/types.ts +174 -0
- package/src/tiers.ts +36 -0
- package/src/types.ts +90 -0
- package/src/utils/context-helpers.ts +13 -9
- package/dist/layer2/dangerous-functions.d.ts +0 -7
- package/dist/layer2/dangerous-functions.d.ts.map +0 -1
- package/dist/layer2/dangerous-functions.js +0 -1701
- package/dist/layer2/dangerous-functions.js.map +0 -1
- package/dist/layer3/anthropic.d.ts +0 -87
- package/dist/layer3/anthropic.d.ts.map +0 -1
- package/dist/layer3/anthropic.js +0 -1948
- package/dist/layer3/anthropic.js.map +0 -1
- package/dist/layer3/openai.d.ts +0 -25
- package/dist/layer3/openai.d.ts.map +0 -1
- package/dist/layer3/openai.js +0 -238
- package/dist/layer3/openai.js.map +0 -1
- package/src/layer2/dangerous-functions.ts +0 -1940
- package/src/layer3/anthropic.ts +0 -2257
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 1: MCP Configuration Audit
|
|
3
|
+
* Detects security issues in MCP configuration files
|
|
4
|
+
*
|
|
5
|
+
* Scans:
|
|
6
|
+
* - mcp.json, *.mcp.json
|
|
7
|
+
* - .mcp/config.json
|
|
8
|
+
* - mcpServers in package.json
|
|
9
|
+
*
|
|
10
|
+
* Detects:
|
|
11
|
+
* - Secrets in MCP config (API keys, tokens in args)
|
|
12
|
+
* - Overpermissive settings (disabled approval, infinite timeouts)
|
|
13
|
+
* - Insecure transport (http:// instead of https://)
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { Vulnerability, VulnerabilitySeverity, VulnerabilityCategory } from '../types'
|
|
17
|
+
import {
|
|
18
|
+
isComment,
|
|
19
|
+
isTestOrMockFile,
|
|
20
|
+
isDocumentationFile,
|
|
21
|
+
isScannerOrFixtureFile,
|
|
22
|
+
isExampleDirectory,
|
|
23
|
+
} from '../utils/context-helpers'
|
|
24
|
+
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// Configuration File Detection
|
|
27
|
+
// ============================================================================
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Check if file is an MCP configuration file
|
|
31
|
+
*/
|
|
32
|
+
function isMCPConfigFile(filePath: string): boolean {
|
|
33
|
+
const mcpConfigPatterns = [
|
|
34
|
+
/mcp\.json$/i,
|
|
35
|
+
/\.mcp\.json$/i,
|
|
36
|
+
/\.mcp\/config\.json$/i,
|
|
37
|
+
/mcp[-_]?config\.json$/i,
|
|
38
|
+
/claude[-_]?desktop[-_]?config\.json$/i,
|
|
39
|
+
]
|
|
40
|
+
return mcpConfigPatterns.some(p => p.test(filePath))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Check if file might contain mcpServers configuration (package.json, etc.)
|
|
45
|
+
*/
|
|
46
|
+
function mightContainMCPConfig(filePath: string, content: string): boolean {
|
|
47
|
+
if (filePath.endsWith('package.json')) {
|
|
48
|
+
return content.includes('mcpServers') || content.includes('mcp')
|
|
49
|
+
}
|
|
50
|
+
if (filePath.endsWith('.json')) {
|
|
51
|
+
return content.includes('mcpServers') || content.includes('"command"') ||
|
|
52
|
+
content.includes('"args"') || content.includes('"url"')
|
|
53
|
+
}
|
|
54
|
+
return false
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ============================================================================
|
|
58
|
+
// Pattern Definitions
|
|
59
|
+
// ============================================================================
|
|
60
|
+
|
|
61
|
+
interface MCPConfigPattern {
|
|
62
|
+
name: string
|
|
63
|
+
pattern: RegExp
|
|
64
|
+
category: VulnerabilityCategory
|
|
65
|
+
baseSeverity: VulnerabilitySeverity
|
|
66
|
+
description: string
|
|
67
|
+
suggestedFix: string
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* MCP Configuration Security Patterns
|
|
72
|
+
*/
|
|
73
|
+
const MCP_CONFIG_PATTERNS: MCPConfigPattern[] = [
|
|
74
|
+
// Secrets in args array
|
|
75
|
+
{
|
|
76
|
+
name: 'API key in MCP server args',
|
|
77
|
+
pattern: /"args"\s*:\s*\[[^\]]*(?:api[_-]?key|API[_-]?KEY|apiKey)[=:]["'][^"']+["'][^\]]*\]/gi,
|
|
78
|
+
category: 'ai_mcp_config_secrets',
|
|
79
|
+
baseSeverity: 'critical',
|
|
80
|
+
description: 'API key found in MCP server arguments. Secrets should not be stored in configuration files.',
|
|
81
|
+
suggestedFix: 'Use environment variables for secrets: ["--api-key", "${ANTHROPIC_API_KEY}"] or use a secrets manager.',
|
|
82
|
+
},
|
|
83
|
+
// Secret/token in args
|
|
84
|
+
{
|
|
85
|
+
name: 'Secret token in MCP server args',
|
|
86
|
+
pattern: /"args"\s*:\s*\[[^\]]*(?:secret|token|password|credential|auth)[=:]["'][^"']+["'][^\]]*\]/gi,
|
|
87
|
+
category: 'ai_mcp_config_secrets',
|
|
88
|
+
baseSeverity: 'critical',
|
|
89
|
+
description: 'Secret or token found in MCP server arguments. This could be exposed in logs or version control.',
|
|
90
|
+
suggestedFix: 'Move secrets to environment variables or a secrets manager.',
|
|
91
|
+
},
|
|
92
|
+
// Hardcoded bearer token
|
|
93
|
+
{
|
|
94
|
+
name: 'Bearer token in MCP config',
|
|
95
|
+
pattern: /"(?:auth|authorization|header)"\s*:\s*["'][Bb]earer\s+[A-Za-z0-9_-]+["']/gi,
|
|
96
|
+
category: 'ai_mcp_config_secrets',
|
|
97
|
+
baseSeverity: 'critical',
|
|
98
|
+
description: 'Bearer token hardcoded in MCP configuration. This is a security risk.',
|
|
99
|
+
suggestedFix: 'Use environment variable reference: "Bearer ${MCP_TOKEN}"',
|
|
100
|
+
},
|
|
101
|
+
// Environment variable with actual value (not reference)
|
|
102
|
+
{
|
|
103
|
+
name: 'Environment variable with hardcoded value',
|
|
104
|
+
pattern: /"env"\s*:\s*\{[^}]*(?:KEY|TOKEN|SECRET|PASSWORD)\s*"\s*:\s*"(?!\$\{)[^"]+"/gi,
|
|
105
|
+
category: 'ai_mcp_config_secrets',
|
|
106
|
+
baseSeverity: 'high',
|
|
107
|
+
description: 'Environment variable set to hardcoded secret value in MCP config.',
|
|
108
|
+
suggestedFix: 'Set environment variables outside the config file or use a secrets manager.',
|
|
109
|
+
},
|
|
110
|
+
// Disabled approval requirement
|
|
111
|
+
{
|
|
112
|
+
name: 'Tool approval disabled',
|
|
113
|
+
pattern: /"requireApproval"\s*:\s*false/gi,
|
|
114
|
+
category: 'ai_mcp_config_permissions',
|
|
115
|
+
baseSeverity: 'medium',
|
|
116
|
+
description: 'Tool approval is disabled. AI can execute tools without user confirmation.',
|
|
117
|
+
suggestedFix: 'Enable tool approval for sensitive operations: "requireApproval": true',
|
|
118
|
+
},
|
|
119
|
+
// Auto-approve all
|
|
120
|
+
{
|
|
121
|
+
name: 'Auto-approve all tools',
|
|
122
|
+
pattern: /"autoApprove"\s*:\s*(?:true|"\*"|"all"|\["\*"\])/gi,
|
|
123
|
+
category: 'ai_mcp_config_permissions',
|
|
124
|
+
baseSeverity: 'high',
|
|
125
|
+
description: 'All tools are auto-approved. This bypasses user confirmation for all operations.',
|
|
126
|
+
suggestedFix: 'Limit auto-approval to specific safe tools: "autoApprove": ["read_file", "list_files"]',
|
|
127
|
+
},
|
|
128
|
+
// Infinite or very long timeout
|
|
129
|
+
{
|
|
130
|
+
name: 'Unlimited tool timeout',
|
|
131
|
+
pattern: /"(?:toolTimeout|timeout)"\s*:\s*(?:0|null|"infinite"|999999+)/gi,
|
|
132
|
+
category: 'ai_mcp_config_permissions',
|
|
133
|
+
baseSeverity: 'medium',
|
|
134
|
+
description: 'Tool timeout is disabled or very long. Tools could run indefinitely.',
|
|
135
|
+
suggestedFix: 'Set a reasonable timeout: "toolTimeout": 30000 (30 seconds)',
|
|
136
|
+
},
|
|
137
|
+
// HTTP URL (not HTTPS)
|
|
138
|
+
{
|
|
139
|
+
name: 'Insecure HTTP transport',
|
|
140
|
+
pattern: /"(?:url|endpoint|server)"\s*:\s*"http:\/\/(?!localhost|127\.0\.0\.1)[^"]+"/gi,
|
|
141
|
+
category: 'ai_mcp_config_permissions',
|
|
142
|
+
baseSeverity: 'medium',
|
|
143
|
+
description: 'MCP server uses insecure HTTP transport. Data could be intercepted.',
|
|
144
|
+
suggestedFix: 'Use HTTPS for MCP server URLs: "url": "https://..."',
|
|
145
|
+
},
|
|
146
|
+
// Wildcard allowed tools
|
|
147
|
+
{
|
|
148
|
+
name: 'Wildcard tool permissions',
|
|
149
|
+
pattern: /"(?:allowedTools|tools|permissions)"\s*:\s*(?:\["\*"\]|"\*"|"all")/gi,
|
|
150
|
+
category: 'ai_mcp_config_permissions',
|
|
151
|
+
baseSeverity: 'medium',
|
|
152
|
+
description: 'All tools are allowed without restriction. Consider limiting to specific tools.',
|
|
153
|
+
suggestedFix: 'Explicitly list allowed tools: "allowedTools": ["search", "read_file"]',
|
|
154
|
+
},
|
|
155
|
+
// Privileged mode enabled
|
|
156
|
+
{
|
|
157
|
+
name: 'Privileged mode enabled',
|
|
158
|
+
pattern: /"(?:privileged|sudo|admin|root)"\s*:\s*true/gi,
|
|
159
|
+
category: 'ai_mcp_config_permissions',
|
|
160
|
+
baseSeverity: 'high',
|
|
161
|
+
description: 'MCP server running in privileged mode. This grants elevated permissions.',
|
|
162
|
+
suggestedFix: 'Disable privileged mode unless absolutely necessary. Apply principle of least privilege.',
|
|
163
|
+
},
|
|
164
|
+
// Disabled security features
|
|
165
|
+
{
|
|
166
|
+
name: 'Security feature disabled',
|
|
167
|
+
pattern: /"(?:secure|tls|verify|validation|sandbox)"\s*:\s*false/gi,
|
|
168
|
+
category: 'ai_mcp_config_permissions',
|
|
169
|
+
baseSeverity: 'medium',
|
|
170
|
+
description: 'Security feature is explicitly disabled in MCP configuration.',
|
|
171
|
+
suggestedFix: 'Enable security features: "secure": true, "validation": true',
|
|
172
|
+
},
|
|
173
|
+
// Command injection risk in args
|
|
174
|
+
{
|
|
175
|
+
name: 'Shell command in MCP args',
|
|
176
|
+
pattern: /"args"\s*:\s*\[[^\]]*(?:sh\s+-c|bash\s+-c|cmd\s+\/c|powershell)[^\]]*\]/gi,
|
|
177
|
+
category: 'ai_mcp_config_permissions',
|
|
178
|
+
baseSeverity: 'high',
|
|
179
|
+
description: 'MCP server args contain shell command execution. This is a command injection risk.',
|
|
180
|
+
suggestedFix: 'Avoid shell command execution in MCP args. Use direct command invocation.',
|
|
181
|
+
},
|
|
182
|
+
]
|
|
183
|
+
|
|
184
|
+
// ============================================================================
|
|
185
|
+
// Main Detection Function
|
|
186
|
+
// ============================================================================
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Main detection function for MCP configuration audit
|
|
190
|
+
*/
|
|
191
|
+
export function detectMCPConfigIssues(
|
|
192
|
+
content: string,
|
|
193
|
+
filePath: string
|
|
194
|
+
): Vulnerability[] {
|
|
195
|
+
const vulnerabilities: Vulnerability[] = []
|
|
196
|
+
|
|
197
|
+
// Skip non-applicable files
|
|
198
|
+
if (isScannerOrFixtureFile(filePath)) return vulnerabilities
|
|
199
|
+
if (isDocumentationFile(filePath)) return vulnerabilities
|
|
200
|
+
|
|
201
|
+
// Only scan MCP config files or files that might contain MCP config
|
|
202
|
+
if (!isMCPConfigFile(filePath) && !mightContainMCPConfig(filePath, content)) {
|
|
203
|
+
return vulnerabilities
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const lines = content.split('\n')
|
|
207
|
+
const isTestFile = isTestOrMockFile(filePath)
|
|
208
|
+
const isExample = isExampleDirectory(filePath)
|
|
209
|
+
|
|
210
|
+
// Track findings to avoid duplicates
|
|
211
|
+
const seenFindings = new Set<string>()
|
|
212
|
+
|
|
213
|
+
for (const pattern of MCP_CONFIG_PATTERNS) {
|
|
214
|
+
const regex = new RegExp(pattern.pattern.source, pattern.pattern.flags)
|
|
215
|
+
let match
|
|
216
|
+
|
|
217
|
+
while ((match = regex.exec(content)) !== null) {
|
|
218
|
+
const lineNumber = content.substring(0, match.index).split('\n').length
|
|
219
|
+
const lineContent = lines[lineNumber - 1]?.trim() || ''
|
|
220
|
+
|
|
221
|
+
// Skip comments
|
|
222
|
+
if (isComment(lineContent)) continue
|
|
223
|
+
|
|
224
|
+
// Create dedup key
|
|
225
|
+
const dedupKey = `${filePath}:${lineNumber}:${pattern.category}`
|
|
226
|
+
if (seenFindings.has(dedupKey)) continue
|
|
227
|
+
seenFindings.add(dedupKey)
|
|
228
|
+
|
|
229
|
+
let severity = pattern.baseSeverity
|
|
230
|
+
let description = pattern.description
|
|
231
|
+
const notes: string[] = []
|
|
232
|
+
|
|
233
|
+
// Check if value is an environment variable reference (safer)
|
|
234
|
+
if (/\$\{[A-Z_]+\}|\$[A-Z_]+/.test(lineContent)) {
|
|
235
|
+
if (pattern.category === 'ai_mcp_config_secrets') {
|
|
236
|
+
severity = 'low'
|
|
237
|
+
notes.push('Uses environment variable reference (safer pattern)')
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Downgrade test files
|
|
242
|
+
if (isTestFile) {
|
|
243
|
+
severity = 'info'
|
|
244
|
+
notes.push('in test file')
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Downgrade example/demo directories
|
|
248
|
+
if (isExample && severity !== 'info') {
|
|
249
|
+
severity = 'info'
|
|
250
|
+
notes.push('in example/demo directory')
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Build final description
|
|
254
|
+
if (notes.length > 0) {
|
|
255
|
+
description += ` (${notes.join('; ')})`
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
vulnerabilities.push({
|
|
259
|
+
id: `mcp-config-${filePath}-${lineNumber}-${pattern.name.replace(/\s+/g, '-')}`,
|
|
260
|
+
filePath,
|
|
261
|
+
lineNumber,
|
|
262
|
+
lineContent,
|
|
263
|
+
severity,
|
|
264
|
+
category: pattern.category,
|
|
265
|
+
title: pattern.name,
|
|
266
|
+
description,
|
|
267
|
+
suggestedFix: pattern.suggestedFix,
|
|
268
|
+
confidence: pattern.category === 'ai_mcp_config_secrets' ? 'high' : 'medium',
|
|
269
|
+
layer: 1,
|
|
270
|
+
requiresAIValidation: severity !== 'info' && severity !== 'low',
|
|
271
|
+
})
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return vulnerabilities
|
|
276
|
+
}
|
package/src/layer1/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { detectDangerousFiles } from './file-flags'
|
|
|
13
13
|
import { detectAICommentPatterns } from './comments'
|
|
14
14
|
import { detectSensitiveURLs } from './urls'
|
|
15
15
|
import { detectWeakCrypto } from './weak-crypto'
|
|
16
|
+
import { detectMCPConfigIssues } from './config-mcp-audit'
|
|
16
17
|
import {
|
|
17
18
|
type TierStats,
|
|
18
19
|
computeTierStats,
|
|
@@ -47,12 +48,15 @@ export interface Layer1Result {
|
|
|
47
48
|
stats: Layer1Stats
|
|
48
49
|
}
|
|
49
50
|
|
|
51
|
+
// Extended stats type to include MCP config detector
|
|
52
|
+
type Layer1StatsRecord = Record<Layer1DetectorName, number> & { mcp_config: number }
|
|
53
|
+
|
|
50
54
|
// Process a single file through all Layer 1 detectors
|
|
51
|
-
function processFileLayer1(file: ScanFile): {
|
|
52
|
-
findings: Vulnerability[],
|
|
53
|
-
stats:
|
|
55
|
+
function processFileLayer1(file: ScanFile): {
|
|
56
|
+
findings: Vulnerability[],
|
|
57
|
+
stats: Layer1StatsRecord
|
|
54
58
|
} {
|
|
55
|
-
const stats:
|
|
59
|
+
const stats: Layer1StatsRecord = {
|
|
56
60
|
known_secrets: 0,
|
|
57
61
|
weak_crypto: 0,
|
|
58
62
|
sensitive_urls: 0,
|
|
@@ -60,6 +64,7 @@ function processFileLayer1(file: ScanFile): {
|
|
|
60
64
|
config_audit: 0,
|
|
61
65
|
file_flags: 0,
|
|
62
66
|
ai_comments: 0,
|
|
67
|
+
mcp_config: 0,
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
const entropyFindings = detectHighEntropyStrings(file.content, file.path)
|
|
@@ -69,6 +74,7 @@ function processFileLayer1(file: ScanFile): {
|
|
|
69
74
|
const commentFindings = detectAICommentPatterns(file.content, file.path)
|
|
70
75
|
const urlFindings = detectSensitiveURLs(file.content, file.path)
|
|
71
76
|
const cryptoFindings = detectWeakCrypto(file.content, file.path)
|
|
77
|
+
const mcpConfigFindings = detectMCPConfigIssues(file.content, file.path)
|
|
72
78
|
|
|
73
79
|
stats.entropy = entropyFindings.length
|
|
74
80
|
stats.known_secrets = patternFindings.length
|
|
@@ -77,6 +83,7 @@ function processFileLayer1(file: ScanFile): {
|
|
|
77
83
|
stats.ai_comments = commentFindings.length
|
|
78
84
|
stats.sensitive_urls = urlFindings.length
|
|
79
85
|
stats.weak_crypto = cryptoFindings.length
|
|
86
|
+
stats.mcp_config = mcpConfigFindings.length
|
|
80
87
|
|
|
81
88
|
return {
|
|
82
89
|
findings: [
|
|
@@ -87,6 +94,7 @@ function processFileLayer1(file: ScanFile): {
|
|
|
87
94
|
...commentFindings,
|
|
88
95
|
...urlFindings,
|
|
89
96
|
...cryptoFindings,
|
|
97
|
+
...mcpConfigFindings,
|
|
90
98
|
],
|
|
91
99
|
stats,
|
|
92
100
|
}
|
|
@@ -106,7 +114,7 @@ export async function runLayer1Scan(
|
|
|
106
114
|
const vulnerabilities: Vulnerability[] = []
|
|
107
115
|
|
|
108
116
|
// Track raw counts per detector (before dedupe)
|
|
109
|
-
const rawStats:
|
|
117
|
+
const rawStats: Layer1StatsRecord = {
|
|
110
118
|
known_secrets: 0,
|
|
111
119
|
weak_crypto: 0,
|
|
112
120
|
sensitive_urls: 0,
|
|
@@ -114,6 +122,7 @@ export async function runLayer1Scan(
|
|
|
114
122
|
config_audit: 0,
|
|
115
123
|
file_flags: 0,
|
|
116
124
|
ai_comments: 0,
|
|
125
|
+
mcp_config: 0,
|
|
117
126
|
}
|
|
118
127
|
|
|
119
128
|
// Track progress for frequent updates
|
|
@@ -132,7 +141,7 @@ export async function runLayer1Scan(
|
|
|
132
141
|
vulnerabilities.push(...result.findings)
|
|
133
142
|
// Accumulate stats
|
|
134
143
|
for (const [key, value] of Object.entries(result.stats)) {
|
|
135
|
-
rawStats[key as
|
|
144
|
+
rawStats[key as keyof Layer1StatsRecord] += value
|
|
136
145
|
}
|
|
137
146
|
}
|
|
138
147
|
|
|
@@ -221,3 +230,4 @@ export { detectDangerousFiles } from './file-flags'
|
|
|
221
230
|
export { detectAICommentPatterns } from './comments'
|
|
222
231
|
export { detectSensitiveURLs } from './urls'
|
|
223
232
|
export { detectWeakCrypto } from './weak-crypto'
|
|
233
|
+
export { detectMCPConfigIssues } from './config-mcp-audit'
|