@oculum/scanner 1.0.11 → 1.0.13
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/ai-context/index.d.ts +6 -0
- package/dist/ai-context/index.d.ts.map +1 -0
- package/dist/ai-context/index.js +13 -0
- package/dist/ai-context/index.js.map +1 -0
- package/dist/ai-context/manager.d.ts +67 -0
- package/dist/ai-context/manager.d.ts.map +1 -0
- package/dist/ai-context/manager.js +104 -0
- package/dist/ai-context/manager.js.map +1 -0
- package/dist/category-filter.d.ts +125 -0
- package/dist/category-filter.d.ts.map +1 -0
- package/dist/category-filter.js +360 -0
- package/dist/category-filter.js.map +1 -0
- package/dist/detect/ai-code/agent-tools.d.ts +22 -0
- package/dist/detect/ai-code/agent-tools.d.ts.map +1 -0
- package/dist/detect/ai-code/agent-tools.js +1509 -0
- package/dist/detect/ai-code/agent-tools.js.map +1 -0
- package/dist/detect/ai-code/byok-patterns.d.ts +15 -0
- package/dist/detect/ai-code/byok-patterns.d.ts.map +1 -0
- package/dist/detect/ai-code/byok-patterns.js +313 -0
- package/dist/detect/ai-code/byok-patterns.js.map +1 -0
- package/dist/detect/ai-code/endpoint-protection.d.ts +38 -0
- package/dist/detect/ai-code/endpoint-protection.d.ts.map +1 -0
- package/dist/detect/ai-code/endpoint-protection.js +349 -0
- package/dist/detect/ai-code/endpoint-protection.js.map +1 -0
- package/dist/detect/ai-code/execution-sinks.d.ts +21 -0
- package/dist/detect/ai-code/execution-sinks.d.ts.map +1 -0
- package/dist/detect/ai-code/execution-sinks.js +1158 -0
- package/dist/detect/ai-code/execution-sinks.js.map +1 -0
- package/dist/detect/ai-code/fingerprinting.d.ts +10 -0
- package/dist/detect/ai-code/fingerprinting.d.ts.map +1 -0
- package/dist/detect/ai-code/fingerprinting.js +665 -0
- package/dist/detect/ai-code/fingerprinting.js.map +1 -0
- package/dist/detect/ai-code/index.d.ts +12 -0
- package/dist/detect/ai-code/index.d.ts.map +1 -0
- package/dist/detect/ai-code/index.js +26 -0
- package/dist/detect/ai-code/index.js.map +1 -0
- package/dist/detect/ai-code/mcp-security.d.ts +20 -0
- package/dist/detect/ai-code/mcp-security.d.ts.map +1 -0
- package/dist/detect/ai-code/mcp-security.js +880 -0
- package/dist/detect/ai-code/mcp-security.js.map +1 -0
- package/dist/detect/ai-code/model-supply-chain.d.ts +23 -0
- package/dist/detect/ai-code/model-supply-chain.d.ts.map +1 -0
- package/dist/detect/ai-code/model-supply-chain.js +447 -0
- package/dist/detect/ai-code/model-supply-chain.js.map +1 -0
- package/dist/detect/ai-code/package-hallucination.d.ts +22 -0
- package/dist/detect/ai-code/package-hallucination.d.ts.map +1 -0
- package/dist/detect/ai-code/package-hallucination.js +841 -0
- package/dist/detect/ai-code/package-hallucination.js.map +1 -0
- package/dist/detect/ai-code/prompt-hygiene.d.ts +22 -0
- package/dist/detect/ai-code/prompt-hygiene.d.ts.map +1 -0
- package/dist/detect/ai-code/prompt-hygiene.js +1177 -0
- package/dist/detect/ai-code/prompt-hygiene.js.map +1 -0
- package/dist/detect/ai-code/rag-safety.d.ts +24 -0
- package/dist/detect/ai-code/rag-safety.d.ts.map +1 -0
- package/dist/detect/ai-code/rag-safety.js +913 -0
- package/dist/detect/ai-code/rag-safety.js.map +1 -0
- package/dist/detect/ai-code/schema-validation.d.ts +28 -0
- package/dist/detect/ai-code/schema-validation.d.ts.map +1 -0
- package/dist/detect/ai-code/schema-validation.js +378 -0
- package/dist/detect/ai-code/schema-validation.js.map +1 -0
- package/dist/detect/config/agent-skill-injection.d.ts +27 -0
- package/dist/detect/config/agent-skill-injection.d.ts.map +1 -0
- package/dist/detect/config/agent-skill-injection.js +472 -0
- package/dist/detect/config/agent-skill-injection.js.map +1 -0
- package/dist/detect/config/comments.d.ts +11 -0
- package/dist/detect/config/comments.d.ts.map +1 -0
- package/dist/detect/config/comments.js +206 -0
- package/dist/detect/config/comments.js.map +1 -0
- package/dist/detect/config/file-flags.d.ts +10 -0
- package/dist/detect/config/file-flags.d.ts.map +1 -0
- package/dist/detect/config/file-flags.js +124 -0
- package/dist/detect/config/file-flags.js.map +1 -0
- package/dist/detect/config/index.d.ts +7 -0
- package/dist/detect/config/index.d.ts.map +1 -0
- package/dist/detect/config/index.js +17 -0
- package/dist/detect/config/index.js.map +1 -0
- package/dist/detect/config/osv-check.d.ts +75 -0
- package/dist/detect/config/osv-check.d.ts.map +1 -0
- package/dist/detect/config/osv-check.js +309 -0
- package/dist/detect/config/osv-check.js.map +1 -0
- package/dist/detect/config/package-check.d.ts +63 -0
- package/dist/detect/config/package-check.d.ts.map +1 -0
- package/dist/detect/config/package-check.js +509 -0
- package/dist/detect/config/package-check.js.map +1 -0
- package/dist/detect/config/urls.d.ts +11 -0
- package/dist/detect/config/urls.d.ts.map +1 -0
- package/dist/detect/config/urls.js +450 -0
- package/dist/detect/config/urls.js.map +1 -0
- package/dist/detect/index.d.ts +37 -0
- package/dist/detect/index.d.ts.map +1 -0
- package/dist/detect/index.js +77 -0
- package/dist/detect/index.js.map +1 -0
- package/dist/detect/secrets/config-audit.d.ts +11 -0
- package/dist/detect/secrets/config-audit.d.ts.map +1 -0
- package/dist/detect/secrets/config-audit.js +315 -0
- package/dist/detect/secrets/config-audit.js.map +1 -0
- package/dist/detect/secrets/config-mcp-audit.d.ts +23 -0
- package/dist/detect/secrets/config-mcp-audit.d.ts.map +1 -0
- package/dist/detect/secrets/config-mcp-audit.js +243 -0
- package/dist/detect/secrets/config-mcp-audit.js.map +1 -0
- package/dist/detect/secrets/entropy.d.ts +11 -0
- package/dist/detect/secrets/entropy.d.ts.map +1 -0
- package/dist/detect/secrets/entropy.js +751 -0
- package/dist/detect/secrets/entropy.js.map +1 -0
- package/dist/detect/secrets/index.d.ts +36 -0
- package/dist/detect/secrets/index.d.ts.map +1 -0
- package/dist/detect/secrets/index.js +174 -0
- package/dist/detect/secrets/index.js.map +1 -0
- package/dist/detect/secrets/patterns.d.ts +11 -0
- package/dist/detect/secrets/patterns.d.ts.map +1 -0
- package/dist/detect/secrets/patterns.js +518 -0
- package/dist/detect/secrets/patterns.js.map +1 -0
- package/dist/detect/secrets/weak-crypto.d.ts +10 -0
- package/dist/detect/secrets/weak-crypto.d.ts.map +1 -0
- package/dist/detect/secrets/weak-crypto.js +432 -0
- package/dist/detect/secrets/weak-crypto.js.map +1 -0
- package/dist/detect/structural/auth-patterns.d.ts +22 -0
- package/dist/detect/structural/auth-patterns.d.ts.map +1 -0
- package/dist/detect/structural/auth-patterns.js +533 -0
- package/dist/detect/structural/auth-patterns.js.map +1 -0
- package/dist/detect/structural/dangerous-functions/child-process.d.ts +16 -0
- package/dist/detect/structural/dangerous-functions/child-process.d.ts.map +1 -0
- package/dist/detect/structural/dangerous-functions/child-process.js +74 -0
- package/dist/detect/structural/dangerous-functions/child-process.js.map +1 -0
- package/dist/detect/structural/dangerous-functions/dom-xss.d.ts +34 -0
- package/dist/detect/structural/dangerous-functions/dom-xss.d.ts.map +1 -0
- package/dist/detect/structural/dangerous-functions/dom-xss.js +230 -0
- package/dist/detect/structural/dangerous-functions/dom-xss.js.map +1 -0
- package/dist/detect/structural/dangerous-functions/index.d.ts +16 -0
- package/dist/detect/structural/dangerous-functions/index.d.ts.map +1 -0
- package/dist/detect/structural/dangerous-functions/index.js +1193 -0
- package/dist/detect/structural/dangerous-functions/index.js.map +1 -0
- package/dist/detect/structural/dangerous-functions/json-parse.d.ts +31 -0
- package/dist/detect/structural/dangerous-functions/json-parse.d.ts.map +1 -0
- package/dist/detect/structural/dangerous-functions/json-parse.js +326 -0
- package/dist/detect/structural/dangerous-functions/json-parse.js.map +1 -0
- package/dist/detect/structural/dangerous-functions/math-random.d.ts +111 -0
- package/dist/detect/structural/dangerous-functions/math-random.d.ts.map +1 -0
- package/dist/detect/structural/dangerous-functions/math-random.js +684 -0
- package/dist/detect/structural/dangerous-functions/math-random.js.map +1 -0
- package/dist/detect/structural/dangerous-functions/patterns.d.ts +21 -0
- package/dist/detect/structural/dangerous-functions/patterns.d.ts.map +1 -0
- package/dist/detect/structural/dangerous-functions/patterns.js +163 -0
- package/dist/detect/structural/dangerous-functions/patterns.js.map +1 -0
- package/dist/detect/structural/dangerous-functions/request-validation.d.ts +13 -0
- package/dist/detect/structural/dangerous-functions/request-validation.d.ts.map +1 -0
- package/dist/detect/structural/dangerous-functions/request-validation.js +126 -0
- package/dist/detect/structural/dangerous-functions/request-validation.js.map +1 -0
- package/dist/detect/structural/dangerous-functions/utils/control-flow.d.ts +24 -0
- package/dist/detect/structural/dangerous-functions/utils/control-flow.d.ts.map +1 -0
- package/dist/detect/structural/dangerous-functions/utils/control-flow.js +70 -0
- package/dist/detect/structural/dangerous-functions/utils/control-flow.js.map +1 -0
- package/dist/detect/structural/dangerous-functions/utils/helpers.d.ts +31 -0
- package/dist/detect/structural/dangerous-functions/utils/helpers.d.ts.map +1 -0
- package/dist/detect/structural/dangerous-functions/utils/helpers.js +147 -0
- package/dist/detect/structural/dangerous-functions/utils/helpers.js.map +1 -0
- package/dist/detect/structural/dangerous-functions/utils/index.d.ts +9 -0
- package/dist/detect/structural/dangerous-functions/utils/index.d.ts.map +1 -0
- package/dist/detect/structural/dangerous-functions/utils/index.js +23 -0
- package/dist/detect/structural/dangerous-functions/utils/index.js.map +1 -0
- package/dist/detect/structural/dangerous-functions/utils/schema-validation.d.ts +22 -0
- package/dist/detect/structural/dangerous-functions/utils/schema-validation.d.ts.map +1 -0
- package/dist/detect/structural/dangerous-functions/utils/schema-validation.js +102 -0
- package/dist/detect/structural/dangerous-functions/utils/schema-validation.js.map +1 -0
- package/dist/detect/structural/data-exposure.d.ts +19 -0
- package/dist/detect/structural/data-exposure.d.ts.map +1 -0
- package/dist/detect/structural/data-exposure.js +262 -0
- package/dist/detect/structural/data-exposure.js.map +1 -0
- package/dist/detect/structural/framework-checks.d.ts +10 -0
- package/dist/detect/structural/framework-checks.d.ts.map +1 -0
- package/dist/detect/structural/framework-checks.js +389 -0
- package/dist/detect/structural/framework-checks.js.map +1 -0
- package/dist/detect/structural/index.d.ts +71 -0
- package/dist/detect/structural/index.d.ts.map +1 -0
- package/dist/detect/structural/index.js +510 -0
- package/dist/detect/structural/index.js.map +1 -0
- package/dist/detect/structural/log-injection.d.ts +18 -0
- package/dist/detect/structural/log-injection.d.ts.map +1 -0
- package/dist/detect/structural/log-injection.js +217 -0
- package/dist/detect/structural/log-injection.js.map +1 -0
- package/dist/detect/structural/logic-gates.d.ts +10 -0
- package/dist/detect/structural/logic-gates.d.ts.map +1 -0
- package/dist/detect/structural/logic-gates.js +227 -0
- package/dist/detect/structural/logic-gates.js.map +1 -0
- package/dist/detect/structural/risky-imports.d.ts +10 -0
- package/dist/detect/structural/risky-imports.d.ts.map +1 -0
- package/dist/detect/structural/risky-imports.js +168 -0
- package/dist/detect/structural/risky-imports.js.map +1 -0
- package/dist/detect/structural/security-headers.d.ts +18 -0
- package/dist/detect/structural/security-headers.d.ts.map +1 -0
- package/dist/detect/structural/security-headers.js +196 -0
- package/dist/detect/structural/security-headers.js.map +1 -0
- package/dist/detect/structural/ssrf-detection.d.ts +18 -0
- package/dist/detect/structural/ssrf-detection.d.ts.map +1 -0
- package/dist/detect/structural/ssrf-detection.js +263 -0
- package/dist/detect/structural/ssrf-detection.js.map +1 -0
- package/dist/detect/structural/variables.d.ts +11 -0
- package/dist/detect/structural/variables.d.ts.map +1 -0
- package/dist/detect/structural/variables.js +159 -0
- package/dist/detect/structural/variables.js.map +1 -0
- package/dist/detect/structural/xxe-detection.d.ts +18 -0
- package/dist/detect/structural/xxe-detection.d.ts.map +1 -0
- package/dist/detect/structural/xxe-detection.js +245 -0
- package/dist/detect/structural/xxe-detection.js.map +1 -0
- package/dist/filtering/context-adjustments.d.ts +23 -0
- package/dist/filtering/context-adjustments.d.ts.map +1 -0
- package/dist/filtering/context-adjustments.js +100 -0
- package/dist/filtering/context-adjustments.js.map +1 -0
- package/dist/filtering/index.d.ts +3 -0
- package/dist/filtering/index.d.ts.map +1 -0
- package/dist/filtering/index.js +8 -0
- package/dist/filtering/index.js.map +1 -0
- package/dist/filtering/pipeline.d.ts +48 -0
- package/dist/filtering/pipeline.d.ts.map +1 -0
- package/dist/filtering/pipeline.js +76 -0
- package/dist/filtering/pipeline.js.map +1 -0
- package/dist/formatters/ai-context.d.ts +23 -0
- package/dist/formatters/ai-context.d.ts.map +1 -0
- package/dist/formatters/ai-context.js +238 -0
- package/dist/formatters/ai-context.js.map +1 -0
- 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 +2 -2
- package/dist/formatters/github-comment.js.map +1 -1
- package/dist/formatters/ide/claude-code.d.ts +17 -0
- package/dist/formatters/ide/claude-code.d.ts.map +1 -0
- package/dist/formatters/ide/claude-code.js +94 -0
- package/dist/formatters/ide/claude-code.js.map +1 -0
- package/dist/formatters/ide/cursor.d.ts +13 -0
- package/dist/formatters/ide/cursor.d.ts.map +1 -0
- package/dist/formatters/ide/cursor.js +125 -0
- package/dist/formatters/ide/cursor.js.map +1 -0
- package/dist/formatters/ide/index.d.ts +62 -0
- package/dist/formatters/ide/index.d.ts.map +1 -0
- package/dist/formatters/ide/index.js +184 -0
- package/dist/formatters/ide/index.js.map +1 -0
- package/dist/formatters/ide/windsurf.d.ts +13 -0
- package/dist/formatters/ide/windsurf.d.ts.map +1 -0
- package/dist/formatters/ide/windsurf.js +117 -0
- package/dist/formatters/ide/windsurf.js.map +1 -0
- package/dist/formatters/index.d.ts +2 -0
- package/dist/formatters/index.d.ts.map +1 -1
- package/dist/formatters/index.js +17 -1
- package/dist/formatters/index.js.map +1 -1
- package/dist/index.d.ts +17 -60
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +67 -824
- package/dist/index.js.map +1 -1
- package/dist/layer1/comments.d.ts +4 -1
- package/dist/layer1/comments.d.ts.map +1 -1
- package/dist/layer1/comments.js +1 -1
- package/dist/layer1/comments.js.map +1 -1
- package/dist/layer1/config-audit.d.ts +4 -1
- package/dist/layer1/config-audit.d.ts.map +1 -1
- package/dist/layer1/config-audit.js +45 -11
- package/dist/layer1/config-audit.js.map +1 -1
- package/dist/layer1/config-mcp-audit.d.ts +4 -1
- package/dist/layer1/config-mcp-audit.d.ts.map +1 -1
- package/dist/layer1/config-mcp-audit.js +2 -2
- package/dist/layer1/config-mcp-audit.js.map +1 -1
- package/dist/layer1/entropy.d.ts +4 -1
- package/dist/layer1/entropy.d.ts.map +1 -1
- package/dist/layer1/entropy.js +212 -1
- package/dist/layer1/entropy.js.map +1 -1
- package/dist/layer1/file-flags.d.ts +4 -1
- package/dist/layer1/file-flags.d.ts.map +1 -1
- package/dist/layer1/file-flags.js +12 -5
- package/dist/layer1/file-flags.js.map +1 -1
- package/dist/layer1/index.d.ts.map +1 -1
- package/dist/layer1/index.js +14 -19
- package/dist/layer1/index.js.map +1 -1
- package/dist/layer1/patterns.d.ts +4 -1
- package/dist/layer1/patterns.d.ts.map +1 -1
- package/dist/layer1/patterns.js +34 -4
- package/dist/layer1/patterns.js.map +1 -1
- package/dist/layer1/urls.d.ts +4 -1
- package/dist/layer1/urls.d.ts.map +1 -1
- package/dist/layer1/urls.js +162 -14
- package/dist/layer1/urls.js.map +1 -1
- package/dist/layer1/weak-crypto.d.ts +4 -1
- package/dist/layer1/weak-crypto.d.ts.map +1 -1
- package/dist/layer1/weak-crypto.js +144 -7
- package/dist/layer1/weak-crypto.js.map +1 -1
- package/dist/layer2/ai-agent-tools.d.ts +4 -1
- package/dist/layer2/ai-agent-tools.d.ts.map +1 -1
- package/dist/layer2/ai-agent-tools.js +661 -2
- package/dist/layer2/ai-agent-tools.js.map +1 -1
- package/dist/layer2/ai-endpoint-protection.d.ts +2 -0
- package/dist/layer2/ai-endpoint-protection.d.ts.map +1 -1
- package/dist/layer2/ai-endpoint-protection.js +1 -1
- package/dist/layer2/ai-endpoint-protection.js.map +1 -1
- package/dist/layer2/ai-execution-sinks.d.ts +4 -1
- package/dist/layer2/ai-execution-sinks.d.ts.map +1 -1
- package/dist/layer2/ai-execution-sinks.js +252 -43
- package/dist/layer2/ai-execution-sinks.js.map +1 -1
- package/dist/layer2/ai-fingerprinting.d.ts +4 -1
- package/dist/layer2/ai-fingerprinting.d.ts.map +1 -1
- package/dist/layer2/ai-fingerprinting.js +25 -32
- package/dist/layer2/ai-fingerprinting.js.map +1 -1
- package/dist/layer2/ai-mcp-security.d.ts +4 -1
- package/dist/layer2/ai-mcp-security.d.ts.map +1 -1
- package/dist/layer2/ai-mcp-security.js +200 -2
- package/dist/layer2/ai-mcp-security.js.map +1 -1
- package/dist/layer2/ai-package-hallucination.d.ts +4 -1
- package/dist/layer2/ai-package-hallucination.d.ts.map +1 -1
- package/dist/layer2/ai-package-hallucination.js +136 -4
- package/dist/layer2/ai-package-hallucination.js.map +1 -1
- package/dist/layer2/ai-prompt-hygiene.d.ts +4 -1
- package/dist/layer2/ai-prompt-hygiene.d.ts.map +1 -1
- package/dist/layer2/ai-prompt-hygiene.js +342 -28
- package/dist/layer2/ai-prompt-hygiene.js.map +1 -1
- package/dist/layer2/ai-rag-safety.d.ts +4 -1
- package/dist/layer2/ai-rag-safety.d.ts.map +1 -1
- package/dist/layer2/ai-rag-safety.js +82 -2
- package/dist/layer2/ai-rag-safety.js.map +1 -1
- package/dist/layer2/ai-schema-validation.d.ts +4 -1
- package/dist/layer2/ai-schema-validation.d.ts.map +1 -1
- package/dist/layer2/ai-schema-validation.js +2 -2
- package/dist/layer2/ai-schema-validation.js.map +1 -1
- package/dist/layer2/auth-antipatterns.d.ts +2 -0
- package/dist/layer2/auth-antipatterns.d.ts.map +1 -1
- package/dist/layer2/auth-antipatterns.js +205 -20
- package/dist/layer2/auth-antipatterns.js.map +1 -1
- package/dist/layer2/byok-patterns.d.ts +4 -1
- package/dist/layer2/byok-patterns.d.ts.map +1 -1
- package/dist/layer2/byok-patterns.js +2 -2
- package/dist/layer2/byok-patterns.js.map +1 -1
- package/dist/layer2/dangerous-functions/dom-xss.d.ts +9 -4
- package/dist/layer2/dangerous-functions/dom-xss.d.ts.map +1 -1
- package/dist/layer2/dangerous-functions/dom-xss.js +73 -22
- package/dist/layer2/dangerous-functions/dom-xss.js.map +1 -1
- package/dist/layer2/dangerous-functions/index.d.ts +4 -1
- package/dist/layer2/dangerous-functions/index.d.ts.map +1 -1
- package/dist/layer2/dangerous-functions/index.js +551 -20
- package/dist/layer2/dangerous-functions/index.js.map +1 -1
- package/dist/layer2/dangerous-functions/math-random.d.ts +54 -4
- package/dist/layer2/dangerous-functions/math-random.d.ts.map +1 -1
- package/dist/layer2/dangerous-functions/math-random.js +241 -16
- package/dist/layer2/dangerous-functions/math-random.js.map +1 -1
- package/dist/layer2/dangerous-functions/patterns.d.ts.map +1 -1
- package/dist/layer2/dangerous-functions/patterns.js +3 -1
- package/dist/layer2/dangerous-functions/patterns.js.map +1 -1
- package/dist/layer2/dangerous-functions/utils/control-flow.d.ts +3 -2
- package/dist/layer2/dangerous-functions/utils/control-flow.d.ts.map +1 -1
- package/dist/layer2/dangerous-functions/utils/control-flow.js +41 -120
- package/dist/layer2/dangerous-functions/utils/control-flow.js.map +1 -1
- package/dist/layer2/dangerous-functions/utils/helpers.d.ts.map +1 -1
- package/dist/layer2/dangerous-functions/utils/helpers.js +26 -3
- package/dist/layer2/dangerous-functions/utils/helpers.js.map +1 -1
- package/dist/layer2/dangerous-functions/utils/schema-validation.d.ts.map +1 -1
- package/dist/layer2/dangerous-functions/utils/schema-validation.js +14 -1
- package/dist/layer2/dangerous-functions/utils/schema-validation.js.map +1 -1
- package/dist/layer2/data-exposure.d.ts +4 -1
- package/dist/layer2/data-exposure.d.ts.map +1 -1
- package/dist/layer2/data-exposure.js +11 -38
- package/dist/layer2/data-exposure.js.map +1 -1
- package/dist/layer2/framework-checks.d.ts +4 -1
- package/dist/layer2/framework-checks.d.ts.map +1 -1
- package/dist/layer2/framework-checks.js +3 -10
- package/dist/layer2/framework-checks.js.map +1 -1
- package/dist/layer2/index.d.ts +13 -1
- package/dist/layer2/index.d.ts.map +1 -1
- package/dist/layer2/index.js +107 -52
- package/dist/layer2/index.js.map +1 -1
- package/dist/layer2/log-injection.d.ts +18 -0
- package/dist/layer2/log-injection.d.ts.map +1 -0
- package/dist/layer2/log-injection.js +214 -0
- package/dist/layer2/log-injection.js.map +1 -0
- package/dist/layer2/logic-gates.d.ts +4 -1
- package/dist/layer2/logic-gates.d.ts.map +1 -1
- package/dist/layer2/logic-gates.js +54 -20
- package/dist/layer2/logic-gates.js.map +1 -1
- package/dist/layer2/model-supply-chain.d.ts +4 -1
- package/dist/layer2/model-supply-chain.d.ts.map +1 -1
- package/dist/layer2/model-supply-chain.js +72 -4
- package/dist/layer2/model-supply-chain.js.map +1 -1
- package/dist/layer2/risky-imports.d.ts +4 -1
- package/dist/layer2/risky-imports.d.ts.map +1 -1
- package/dist/layer2/risky-imports.js +2 -2
- package/dist/layer2/risky-imports.js.map +1 -1
- package/dist/layer2/security-headers.d.ts +18 -0
- package/dist/layer2/security-headers.d.ts.map +1 -0
- package/dist/layer2/security-headers.js +187 -0
- package/dist/layer2/security-headers.js.map +1 -0
- package/dist/layer2/ssrf-detection.d.ts +18 -0
- package/dist/layer2/ssrf-detection.d.ts.map +1 -0
- package/dist/layer2/ssrf-detection.js +252 -0
- package/dist/layer2/ssrf-detection.js.map +1 -0
- package/dist/layer2/variables.d.ts +4 -1
- package/dist/layer2/variables.d.ts.map +1 -1
- package/dist/layer2/variables.js +2 -2
- package/dist/layer2/variables.js.map +1 -1
- package/dist/layer2/xxe-detection.d.ts +18 -0
- package/dist/layer2/xxe-detection.d.ts.map +1 -0
- package/dist/layer2/xxe-detection.js +242 -0
- package/dist/layer2/xxe-detection.js.map +1 -0
- package/dist/layer3/anthropic/auto-dismiss.d.ts.map +1 -1
- package/dist/layer3/anthropic/auto-dismiss.js +11 -0
- package/dist/layer3/anthropic/auto-dismiss.js.map +1 -1
- package/dist/layer3/anthropic/prompts/index.d.ts +1 -1
- package/dist/layer3/anthropic/prompts/index.d.ts.map +1 -1
- package/dist/layer3/anthropic/prompts/index.js +3 -1
- package/dist/layer3/anthropic/prompts/index.js.map +1 -1
- package/dist/layer3/anthropic/prompts/modules/ai-patterns.d.ts +19 -0
- package/dist/layer3/anthropic/prompts/modules/ai-patterns.d.ts.map +1 -0
- package/dist/layer3/anthropic/prompts/modules/ai-patterns.js +156 -0
- package/dist/layer3/anthropic/prompts/modules/ai-patterns.js.map +1 -0
- package/dist/layer3/anthropic/prompts/modules/auth-access.d.ts +9 -0
- package/dist/layer3/anthropic/prompts/modules/auth-access.d.ts.map +1 -0
- package/dist/layer3/anthropic/prompts/modules/auth-access.js +25 -0
- package/dist/layer3/anthropic/prompts/modules/auth-access.js.map +1 -0
- package/dist/layer3/anthropic/prompts/modules/common.d.ts +11 -0
- package/dist/layer3/anthropic/prompts/modules/common.d.ts.map +1 -0
- package/dist/layer3/anthropic/prompts/modules/common.js +152 -0
- package/dist/layer3/anthropic/prompts/modules/common.js.map +1 -0
- package/dist/layer3/anthropic/prompts/modules/index.d.ts +54 -0
- package/dist/layer3/anthropic/prompts/modules/index.d.ts.map +1 -0
- package/dist/layer3/anthropic/prompts/modules/index.js +185 -0
- package/dist/layer3/anthropic/prompts/modules/index.js.map +1 -0
- package/dist/layer3/anthropic/prompts/modules/owasp-classic.d.ts +8 -0
- package/dist/layer3/anthropic/prompts/modules/owasp-classic.d.ts.map +1 -0
- package/dist/layer3/anthropic/prompts/modules/owasp-classic.js +84 -0
- package/dist/layer3/anthropic/prompts/modules/owasp-classic.js.map +1 -0
- package/dist/layer3/anthropic/prompts/modules/secrets-crypto.d.ts +8 -0
- package/dist/layer3/anthropic/prompts/modules/secrets-crypto.d.ts.map +1 -0
- package/dist/layer3/anthropic/prompts/modules/secrets-crypto.js +68 -0
- package/dist/layer3/anthropic/prompts/modules/secrets-crypto.js.map +1 -0
- package/dist/layer3/anthropic/prompts/modules/xss-prompt.d.ts +8 -0
- package/dist/layer3/anthropic/prompts/modules/xss-prompt.d.ts.map +1 -0
- package/dist/layer3/anthropic/prompts/modules/xss-prompt.js +22 -0
- package/dist/layer3/anthropic/prompts/modules/xss-prompt.js.map +1 -0
- package/dist/layer3/anthropic/prompts/validation.d.ts +9 -3
- package/dist/layer3/anthropic/prompts/validation.d.ts.map +1 -1
- package/dist/layer3/anthropic/prompts/validation.js +14 -410
- package/dist/layer3/anthropic/prompts/validation.js.map +1 -1
- package/dist/layer3/anthropic/providers/anthropic.d.ts.map +1 -1
- package/dist/layer3/anthropic/providers/anthropic.js +6 -3
- package/dist/layer3/anthropic/providers/anthropic.js.map +1 -1
- package/dist/layer3/anthropic/providers/openai.d.ts.map +1 -1
- package/dist/layer3/anthropic/providers/openai.js +6 -3
- package/dist/layer3/anthropic/providers/openai.js.map +1 -1
- package/dist/layer3/anthropic/request-builder.d.ts +11 -4
- package/dist/layer3/anthropic/request-builder.d.ts.map +1 -1
- package/dist/layer3/anthropic/request-builder.js +32 -16
- package/dist/layer3/anthropic/request-builder.js.map +1 -1
- package/dist/layer3/anthropic/utils/context-extractor.d.ts +55 -0
- package/dist/layer3/anthropic/utils/context-extractor.d.ts.map +1 -0
- package/dist/layer3/anthropic/utils/context-extractor.js +161 -0
- package/dist/layer3/anthropic/utils/context-extractor.js.map +1 -0
- package/dist/layer3/anthropic/utils/index.d.ts +2 -0
- package/dist/layer3/anthropic/utils/index.d.ts.map +1 -1
- package/dist/layer3/anthropic/utils/index.js +4 -1
- package/dist/layer3/anthropic/utils/index.js.map +1 -1
- package/dist/model/auth-helper-detector.d.ts +56 -0
- package/dist/model/auth-helper-detector.d.ts.map +1 -0
- package/dist/model/auth-helper-detector.js +360 -0
- package/dist/model/auth-helper-detector.js.map +1 -0
- package/dist/model/cross-file-taint.d.ts +40 -0
- package/dist/model/cross-file-taint.d.ts.map +1 -0
- package/dist/model/cross-file-taint.js +290 -0
- package/dist/model/cross-file-taint.js.map +1 -0
- package/dist/model/framework-models/django.d.ts +9 -0
- package/dist/model/framework-models/django.d.ts.map +1 -0
- package/dist/model/framework-models/django.js +82 -0
- package/dist/model/framework-models/django.js.map +1 -0
- package/dist/model/framework-models/express.d.ts +9 -0
- package/dist/model/framework-models/express.d.ts.map +1 -0
- package/dist/model/framework-models/express.js +52 -0
- package/dist/model/framework-models/express.js.map +1 -0
- package/dist/model/framework-models/index.d.ts +20 -0
- package/dist/model/framework-models/index.d.ts.map +1 -0
- package/dist/model/framework-models/index.js +102 -0
- package/dist/model/framework-models/index.js.map +1 -0
- package/dist/model/framework-models/nextjs.d.ts +9 -0
- package/dist/model/framework-models/nextjs.d.ts.map +1 -0
- package/dist/model/framework-models/nextjs.js +71 -0
- package/dist/model/framework-models/nextjs.js.map +1 -0
- package/dist/model/framework-models/prisma.d.ts +10 -0
- package/dist/model/framework-models/prisma.d.ts.map +1 -0
- package/dist/model/framework-models/prisma.js +54 -0
- package/dist/model/framework-models/prisma.js.map +1 -0
- package/dist/model/framework-models/react.d.ts +9 -0
- package/dist/model/framework-models/react.d.ts.map +1 -0
- package/dist/model/framework-models/react.js +67 -0
- package/dist/model/framework-models/react.js.map +1 -0
- package/dist/model/framework-models/sequelize.d.ts +9 -0
- package/dist/model/framework-models/sequelize.d.ts.map +1 -0
- package/dist/model/framework-models/sequelize.js +62 -0
- package/dist/model/framework-models/sequelize.js.map +1 -0
- package/dist/model/framework-models/types.d.ts +43 -0
- package/dist/model/framework-models/types.d.ts.map +1 -0
- package/dist/model/framework-models/types.js +10 -0
- package/dist/model/framework-models/types.js.map +1 -0
- package/dist/model/function-classifier.d.ts +32 -0
- package/dist/model/function-classifier.d.ts.map +1 -0
- package/dist/model/function-classifier.js +143 -0
- package/dist/model/function-classifier.js.map +1 -0
- package/dist/model/import-resolver.d.ts +45 -0
- package/dist/model/import-resolver.d.ts.map +1 -0
- package/dist/model/import-resolver.js +410 -0
- package/dist/model/import-resolver.js.map +1 -0
- package/dist/model/imported-auth-detector.d.ts +38 -0
- package/dist/model/imported-auth-detector.d.ts.map +1 -0
- package/dist/model/imported-auth-detector.js +199 -0
- package/dist/model/imported-auth-detector.js.map +1 -0
- package/dist/model/index.d.ts +63 -0
- package/dist/model/index.d.ts.map +1 -0
- package/dist/model/index.js +272 -0
- package/dist/model/index.js.map +1 -0
- package/dist/model/middleware-detector.d.ts +55 -0
- package/dist/model/middleware-detector.d.ts.map +1 -0
- package/dist/model/middleware-detector.js +382 -0
- package/dist/model/middleware-detector.js.map +1 -0
- package/dist/model/module-graph.d.ts +46 -0
- package/dist/model/module-graph.d.ts.map +1 -0
- package/dist/model/module-graph.js +187 -0
- package/dist/model/module-graph.js.map +1 -0
- package/dist/model/oauth-flow-detector.d.ts +41 -0
- package/dist/model/oauth-flow-detector.d.ts.map +1 -0
- package/dist/model/oauth-flow-detector.js +202 -0
- package/dist/model/oauth-flow-detector.js.map +1 -0
- package/dist/model/project-context.d.ts +119 -0
- package/dist/model/project-context.d.ts.map +1 -0
- package/dist/model/project-context.js +534 -0
- package/dist/model/project-context.js.map +1 -0
- package/dist/model/route-auth-resolver.d.ts +27 -0
- package/dist/model/route-auth-resolver.d.ts.map +1 -0
- package/dist/model/route-auth-resolver.js +182 -0
- package/dist/model/route-auth-resolver.js.map +1 -0
- package/dist/model/route-discovery/express.d.ts +25 -0
- package/dist/model/route-discovery/express.d.ts.map +1 -0
- package/dist/model/route-discovery/express.js +225 -0
- package/dist/model/route-discovery/express.js.map +1 -0
- package/dist/model/route-discovery/index.d.ts +21 -0
- package/dist/model/route-discovery/index.d.ts.map +1 -0
- package/dist/model/route-discovery/index.js +67 -0
- package/dist/model/route-discovery/index.js.map +1 -0
- package/dist/model/route-discovery/nextjs.d.ts +16 -0
- package/dist/model/route-discovery/nextjs.d.ts.map +1 -0
- package/dist/model/route-discovery/nextjs.js +179 -0
- package/dist/model/route-discovery/nextjs.js.map +1 -0
- package/dist/model/route-discovery/python.d.ts +16 -0
- package/dist/model/route-discovery/python.d.ts.map +1 -0
- package/dist/model/route-discovery/python.js +181 -0
- package/dist/model/route-discovery/python.js.map +1 -0
- package/dist/model/route-discovery/types.d.ts +36 -0
- package/dist/model/route-discovery/types.d.ts.map +1 -0
- package/dist/model/route-discovery/types.js +16 -0
- package/dist/model/route-discovery/types.js.map +1 -0
- package/dist/model/route-discovery/utils.d.ts +18 -0
- package/dist/model/route-discovery/utils.d.ts.map +1 -0
- package/dist/model/route-discovery/utils.js +55 -0
- package/dist/model/route-discovery/utils.js.map +1 -0
- package/dist/model/route-hierarchy.d.ts +50 -0
- package/dist/model/route-hierarchy.d.ts.map +1 -0
- package/dist/model/route-hierarchy.js +226 -0
- package/dist/model/route-hierarchy.js.map +1 -0
- package/dist/model/sanitiser-detection.d.ts +27 -0
- package/dist/model/sanitiser-detection.d.ts.map +1 -0
- package/dist/model/sanitiser-detection.js +224 -0
- package/dist/model/sanitiser-detection.js.map +1 -0
- package/dist/model/sink-matcher.d.ts +17 -0
- package/dist/model/sink-matcher.d.ts.map +1 -0
- package/dist/model/sink-matcher.js +141 -0
- package/dist/model/sink-matcher.js.map +1 -0
- package/dist/model/sink-patterns.d.ts +19 -0
- package/dist/model/sink-patterns.d.ts.map +1 -0
- package/dist/model/sink-patterns.js +88 -0
- package/dist/model/sink-patterns.js.map +1 -0
- package/dist/model/source-discovery.d.ts +15 -0
- package/dist/model/source-discovery.d.ts.map +1 -0
- package/dist/model/source-discovery.js +170 -0
- package/dist/model/source-discovery.js.map +1 -0
- package/dist/model/taint-tracker.d.ts +21 -0
- package/dist/model/taint-tracker.d.ts.map +1 -0
- package/dist/model/taint-tracker.js +281 -0
- package/dist/model/taint-tracker.js.map +1 -0
- package/dist/model/taint-types.d.ts +74 -0
- package/dist/model/taint-types.d.ts.map +1 -0
- package/dist/model/taint-types.js +9 -0
- package/dist/model/taint-types.js.map +1 -0
- package/dist/model/trpc-analyzer.d.ts +78 -0
- package/dist/model/trpc-analyzer.d.ts.map +1 -0
- package/dist/model/trpc-analyzer.js +297 -0
- package/dist/model/trpc-analyzer.js.map +1 -0
- package/dist/modes/incremental.js +1 -1
- package/dist/parse/file-classifier.d.ts +228 -0
- package/dist/parse/file-classifier.d.ts.map +1 -0
- package/dist/parse/file-classifier.js +933 -0
- package/dist/parse/file-classifier.js.map +1 -0
- package/dist/parse/path-exclusions.d.ts +55 -0
- package/dist/parse/path-exclusions.d.ts.map +1 -0
- package/dist/parse/path-exclusions.js +224 -0
- package/dist/parse/path-exclusions.js.map +1 -0
- package/dist/pipeline/config.d.ts +39 -0
- package/dist/pipeline/config.d.ts.map +1 -0
- package/dist/pipeline/config.js +46 -0
- package/dist/pipeline/config.js.map +1 -0
- package/dist/pipeline/index.d.ts +34 -0
- package/dist/pipeline/index.d.ts.map +1 -0
- package/dist/pipeline/index.js +377 -0
- package/dist/pipeline/index.js.map +1 -0
- package/dist/pipeline/modes/incremental.d.ts +66 -0
- package/dist/pipeline/modes/incremental.d.ts.map +1 -0
- package/dist/pipeline/modes/incremental.js +200 -0
- package/dist/pipeline/modes/incremental.js.map +1 -0
- package/dist/postprocess/aggregation.d.ts +14 -0
- package/dist/postprocess/aggregation.d.ts.map +1 -0
- package/dist/postprocess/aggregation.js +63 -0
- package/dist/postprocess/aggregation.js.map +1 -0
- package/dist/postprocess/contradictions.d.ts +18 -0
- package/dist/postprocess/contradictions.d.ts.map +1 -0
- package/dist/postprocess/contradictions.js +99 -0
- package/dist/postprocess/contradictions.js.map +1 -0
- package/dist/postprocess/dedup.d.ts +13 -0
- package/dist/postprocess/dedup.d.ts.map +1 -0
- package/dist/postprocess/dedup.js +58 -0
- package/dist/postprocess/dedup.js.map +1 -0
- package/dist/postprocess/filtering/context-adjustments.d.ts +23 -0
- package/dist/postprocess/filtering/context-adjustments.d.ts.map +1 -0
- package/dist/postprocess/filtering/context-adjustments.js +100 -0
- package/dist/postprocess/filtering/context-adjustments.js.map +1 -0
- package/dist/postprocess/filtering/index.d.ts +3 -0
- package/dist/postprocess/filtering/index.d.ts.map +1 -0
- package/dist/postprocess/filtering/index.js +8 -0
- package/dist/postprocess/filtering/index.js.map +1 -0
- package/dist/postprocess/filtering/pipeline.d.ts +48 -0
- package/dist/postprocess/filtering/pipeline.d.ts.map +1 -0
- package/dist/postprocess/filtering/pipeline.js +76 -0
- package/dist/postprocess/filtering/pipeline.js.map +1 -0
- package/dist/postprocess/index.d.ts +41 -0
- package/dist/postprocess/index.d.ts.map +1 -0
- package/dist/postprocess/index.js +85 -0
- package/dist/postprocess/index.js.map +1 -0
- package/dist/postprocess/suppression/config-loader.d.ts +74 -0
- package/dist/postprocess/suppression/config-loader.d.ts.map +1 -0
- package/dist/postprocess/suppression/config-loader.js +424 -0
- package/dist/postprocess/suppression/config-loader.js.map +1 -0
- package/dist/postprocess/suppression/hash.d.ts +48 -0
- package/dist/postprocess/suppression/hash.d.ts.map +1 -0
- package/dist/postprocess/suppression/hash.js +88 -0
- package/dist/postprocess/suppression/hash.js.map +1 -0
- package/dist/postprocess/suppression/index.d.ts +11 -0
- package/dist/postprocess/suppression/index.d.ts.map +1 -0
- package/dist/postprocess/suppression/index.js +39 -0
- package/dist/postprocess/suppression/index.js.map +1 -0
- package/dist/postprocess/suppression/inline-parser.d.ts +39 -0
- package/dist/postprocess/suppression/inline-parser.d.ts.map +1 -0
- package/dist/postprocess/suppression/inline-parser.js +218 -0
- package/dist/postprocess/suppression/inline-parser.js.map +1 -0
- package/dist/postprocess/suppression/manager.d.ts +94 -0
- package/dist/postprocess/suppression/manager.d.ts.map +1 -0
- package/dist/postprocess/suppression/manager.js +292 -0
- package/dist/postprocess/suppression/manager.js.map +1 -0
- package/dist/postprocess/suppression/types.d.ts +151 -0
- package/dist/postprocess/suppression/types.d.ts.map +1 -0
- package/dist/postprocess/suppression/types.js +28 -0
- package/dist/postprocess/suppression/types.js.map +1 -0
- package/dist/postprocess/validation-cap.d.ts +17 -0
- package/dist/postprocess/validation-cap.d.ts.map +1 -0
- package/dist/postprocess/validation-cap.js +64 -0
- package/dist/postprocess/validation-cap.js.map +1 -0
- package/dist/report/build-result.d.ts +33 -0
- package/dist/report/build-result.d.ts.map +1 -0
- package/dist/report/build-result.js +59 -0
- package/dist/report/build-result.js.map +1 -0
- package/dist/report/enrichment.d.ts +19 -0
- package/dist/report/enrichment.d.ts.map +1 -0
- package/dist/report/enrichment.js +44 -0
- package/dist/report/enrichment.js.map +1 -0
- package/dist/report/formatters/ai-context.d.ts +23 -0
- package/dist/report/formatters/ai-context.d.ts.map +1 -0
- package/dist/report/formatters/ai-context.js +238 -0
- package/dist/report/formatters/ai-context.js.map +1 -0
- package/dist/report/formatters/cli-terminal.d.ts +65 -0
- package/dist/report/formatters/cli-terminal.d.ts.map +1 -0
- package/dist/report/formatters/cli-terminal.js +735 -0
- package/dist/report/formatters/cli-terminal.js.map +1 -0
- package/dist/report/formatters/github-comment.d.ts +41 -0
- package/dist/report/formatters/github-comment.d.ts.map +1 -0
- package/dist/report/formatters/github-comment.js +370 -0
- package/dist/report/formatters/github-comment.js.map +1 -0
- package/dist/report/formatters/grouping.d.ts +52 -0
- package/dist/report/formatters/grouping.d.ts.map +1 -0
- package/dist/report/formatters/grouping.js +152 -0
- package/dist/report/formatters/grouping.js.map +1 -0
- package/dist/report/formatters/ide/claude-code.d.ts +17 -0
- package/dist/report/formatters/ide/claude-code.d.ts.map +1 -0
- package/dist/report/formatters/ide/claude-code.js +94 -0
- package/dist/report/formatters/ide/claude-code.js.map +1 -0
- package/dist/report/formatters/ide/cursor.d.ts +13 -0
- package/dist/report/formatters/ide/cursor.d.ts.map +1 -0
- package/dist/report/formatters/ide/cursor.js +125 -0
- package/dist/report/formatters/ide/cursor.js.map +1 -0
- package/dist/report/formatters/ide/index.d.ts +62 -0
- package/dist/report/formatters/ide/index.d.ts.map +1 -0
- package/dist/report/formatters/ide/index.js +184 -0
- package/dist/report/formatters/ide/index.js.map +1 -0
- package/dist/report/formatters/ide/windsurf.d.ts +13 -0
- package/dist/report/formatters/ide/windsurf.d.ts.map +1 -0
- package/dist/report/formatters/ide/windsurf.js +117 -0
- package/dist/report/formatters/ide/windsurf.js.map +1 -0
- package/dist/report/formatters/index.d.ts +11 -0
- package/dist/report/formatters/index.d.ts.map +1 -0
- package/dist/report/formatters/index.js +54 -0
- package/dist/report/formatters/index.js.map +1 -0
- package/dist/report/formatters/vscode-diagnostic.d.ts +103 -0
- package/dist/report/formatters/vscode-diagnostic.d.ts.map +1 -0
- package/dist/report/formatters/vscode-diagnostic.js +151 -0
- package/dist/report/formatters/vscode-diagnostic.js.map +1 -0
- package/dist/report/summary.d.ts +27 -0
- package/dist/report/summary.d.ts.map +1 -0
- package/dist/report/summary.js +57 -0
- package/dist/report/summary.js.map +1 -0
- package/dist/rules/metadata.d.ts.map +1 -1
- package/dist/rules/metadata.js +66 -0
- package/dist/rules/metadata.js.map +1 -1
- package/dist/score/adjustments.d.ts +22 -0
- package/dist/score/adjustments.d.ts.map +1 -0
- package/dist/score/adjustments.js +373 -0
- package/dist/score/adjustments.js.map +1 -0
- package/dist/score/auto-dismiss.d.ts +28 -0
- package/dist/score/auto-dismiss.d.ts.map +1 -0
- package/dist/score/auto-dismiss.js +200 -0
- package/dist/score/auto-dismiss.js.map +1 -0
- package/dist/score/confidence.d.ts +19 -0
- package/dist/score/confidence.d.ts.map +1 -0
- package/dist/score/confidence.js +52 -0
- package/dist/score/confidence.js.map +1 -0
- package/dist/score/index.d.ts +61 -0
- package/dist/score/index.d.ts.map +1 -0
- package/dist/score/index.js +250 -0
- package/dist/score/index.js.map +1 -0
- package/dist/score/types.d.ts +160 -0
- package/dist/score/types.d.ts.map +1 -0
- package/dist/score/types.js +14 -0
- package/dist/score/types.js.map +1 -0
- package/dist/shared/ai-context/index.d.ts +6 -0
- package/dist/shared/ai-context/index.d.ts.map +1 -0
- package/dist/shared/ai-context/index.js +13 -0
- package/dist/shared/ai-context/index.js.map +1 -0
- package/dist/shared/ai-context/manager.d.ts +67 -0
- package/dist/shared/ai-context/manager.d.ts.map +1 -0
- package/dist/shared/ai-context/manager.js +104 -0
- package/dist/shared/ai-context/manager.js.map +1 -0
- package/dist/shared/baseline/diff.d.ts +32 -0
- package/dist/shared/baseline/diff.d.ts.map +1 -0
- package/dist/shared/baseline/diff.js +119 -0
- package/dist/shared/baseline/diff.js.map +1 -0
- package/dist/shared/baseline/index.d.ts +9 -0
- package/dist/shared/baseline/index.d.ts.map +1 -0
- package/dist/shared/baseline/index.js +19 -0
- package/dist/shared/baseline/index.js.map +1 -0
- package/dist/shared/baseline/manager.d.ts +67 -0
- package/dist/shared/baseline/manager.d.ts.map +1 -0
- package/dist/shared/baseline/manager.js +180 -0
- package/dist/shared/baseline/manager.js.map +1 -0
- package/dist/shared/baseline/types.d.ts +91 -0
- package/dist/shared/baseline/types.d.ts.map +1 -0
- package/dist/shared/baseline/types.js +12 -0
- package/dist/shared/baseline/types.js.map +1 -0
- package/dist/shared/category-filter.d.ts +125 -0
- package/dist/shared/category-filter.d.ts.map +1 -0
- package/dist/shared/category-filter.js +360 -0
- package/dist/shared/category-filter.js.map +1 -0
- package/dist/shared/code-analysis.d.ts +39 -0
- package/dist/shared/code-analysis.d.ts.map +1 -0
- package/dist/shared/code-analysis.js +159 -0
- package/dist/shared/code-analysis.js.map +1 -0
- package/dist/shared/comment-analyzer.d.ts +38 -0
- package/dist/shared/comment-analyzer.d.ts.map +1 -0
- package/dist/shared/comment-analyzer.js +218 -0
- package/dist/shared/comment-analyzer.js.map +1 -0
- package/dist/shared/diff-detector.d.ts +53 -0
- package/dist/shared/diff-detector.d.ts.map +1 -0
- package/dist/shared/diff-detector.js +104 -0
- package/dist/shared/diff-detector.js.map +1 -0
- package/dist/shared/diff-parser.d.ts +80 -0
- package/dist/shared/diff-parser.d.ts.map +1 -0
- package/dist/shared/diff-parser.js +202 -0
- package/dist/shared/diff-parser.js.map +1 -0
- package/dist/shared/environment-context.d.ts +76 -0
- package/dist/shared/environment-context.d.ts.map +1 -0
- package/dist/shared/environment-context.js +271 -0
- package/dist/shared/environment-context.js.map +1 -0
- package/dist/shared/intent-detector.d.ts +66 -0
- package/dist/shared/intent-detector.d.ts.map +1 -0
- package/dist/shared/intent-detector.js +282 -0
- package/dist/shared/intent-detector.js.map +1 -0
- package/dist/shared/parsed-file.d.ts +51 -0
- package/dist/shared/parsed-file.d.ts.map +1 -0
- package/dist/shared/parsed-file.js +95 -0
- package/dist/shared/parsed-file.js.map +1 -0
- package/dist/shared/registry-clients.d.ts +93 -0
- package/dist/shared/registry-clients.d.ts.map +1 -0
- package/dist/shared/registry-clients.js +273 -0
- package/dist/shared/registry-clients.js.map +1 -0
- package/dist/shared/rules/framework-fixes.d.ts +48 -0
- package/dist/shared/rules/framework-fixes.d.ts.map +1 -0
- package/dist/shared/rules/framework-fixes.js +439 -0
- package/dist/shared/rules/framework-fixes.js.map +1 -0
- package/dist/shared/rules/index.d.ts +8 -0
- package/dist/shared/rules/index.d.ts.map +1 -0
- package/dist/shared/rules/index.js +18 -0
- package/dist/shared/rules/index.js.map +1 -0
- package/dist/shared/rules/metadata.d.ts +43 -0
- package/dist/shared/rules/metadata.d.ts.map +1 -0
- package/dist/shared/rules/metadata.js +819 -0
- package/dist/shared/rules/metadata.js.map +1 -0
- package/dist/shared/schema-semantics.d.ts +45 -0
- package/dist/shared/schema-semantics.d.ts.map +1 -0
- package/dist/shared/schema-semantics.js +193 -0
- package/dist/shared/schema-semantics.js.map +1 -0
- package/dist/shared/types.d.ts +337 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +126 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/tiers.d.ts +4 -4
- package/dist/tiers.d.ts.map +1 -1
- package/dist/tiers.js +17 -7
- package/dist/tiers.js.map +1 -1
- package/dist/types.d.ts +79 -9
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +34 -0
- package/dist/types.js.map +1 -1
- package/dist/utils/code-analysis.d.ts +39 -0
- package/dist/utils/code-analysis.d.ts.map +1 -0
- package/dist/utils/code-analysis.js +159 -0
- package/dist/utils/code-analysis.js.map +1 -0
- package/dist/utils/comment-analyzer.d.ts +38 -0
- package/dist/utils/comment-analyzer.d.ts.map +1 -0
- package/dist/utils/comment-analyzer.js +218 -0
- package/dist/utils/comment-analyzer.js.map +1 -0
- package/dist/utils/context-helpers.d.ts +108 -1
- package/dist/utils/context-helpers.d.ts.map +1 -1
- package/dist/utils/context-helpers.js +351 -2
- package/dist/utils/context-helpers.js.map +1 -1
- package/dist/utils/environment-context.d.ts +76 -0
- package/dist/utils/environment-context.d.ts.map +1 -0
- package/dist/utils/environment-context.js +271 -0
- package/dist/utils/environment-context.js.map +1 -0
- package/dist/utils/intent-detector.d.ts +66 -0
- package/dist/utils/intent-detector.d.ts.map +1 -0
- package/dist/utils/intent-detector.js +282 -0
- package/dist/utils/intent-detector.js.map +1 -0
- package/dist/utils/parsed-file.d.ts +51 -0
- package/dist/utils/parsed-file.d.ts.map +1 -0
- package/dist/utils/parsed-file.js +95 -0
- package/dist/utils/parsed-file.js.map +1 -0
- package/dist/utils/route-hierarchy.d.ts +50 -0
- package/dist/utils/route-hierarchy.d.ts.map +1 -0
- package/dist/utils/route-hierarchy.js +226 -0
- package/dist/utils/route-hierarchy.js.map +1 -0
- package/dist/utils/schema-semantics.d.ts +45 -0
- package/dist/utils/schema-semantics.d.ts.map +1 -0
- package/dist/utils/schema-semantics.js +193 -0
- package/dist/utils/schema-semantics.js.map +1 -0
- package/dist/validate/clients.d.ts +44 -0
- package/dist/validate/clients.d.ts.map +1 -0
- package/dist/validate/clients.js +81 -0
- package/dist/validate/clients.js.map +1 -0
- package/dist/validate/index.d.ts +41 -0
- package/dist/validate/index.d.ts.map +1 -0
- package/dist/validate/index.js +141 -0
- package/dist/validate/index.js.map +1 -0
- package/dist/validate/prompts/index.d.ts +8 -0
- package/dist/validate/prompts/index.d.ts.map +1 -0
- package/dist/validate/prompts/index.js +16 -0
- package/dist/validate/prompts/index.js.map +1 -0
- package/dist/validate/prompts/modules/ai-patterns.d.ts +19 -0
- package/dist/validate/prompts/modules/ai-patterns.d.ts.map +1 -0
- package/dist/validate/prompts/modules/ai-patterns.js +156 -0
- package/dist/validate/prompts/modules/ai-patterns.js.map +1 -0
- package/dist/validate/prompts/modules/auth-access.d.ts +9 -0
- package/dist/validate/prompts/modules/auth-access.d.ts.map +1 -0
- package/dist/validate/prompts/modules/auth-access.js +25 -0
- package/dist/validate/prompts/modules/auth-access.js.map +1 -0
- package/dist/validate/prompts/modules/common.d.ts +11 -0
- package/dist/validate/prompts/modules/common.d.ts.map +1 -0
- package/dist/validate/prompts/modules/common.js +186 -0
- package/dist/validate/prompts/modules/common.js.map +1 -0
- package/dist/validate/prompts/modules/index.d.ts +54 -0
- package/dist/validate/prompts/modules/index.d.ts.map +1 -0
- package/dist/validate/prompts/modules/index.js +186 -0
- package/dist/validate/prompts/modules/index.js.map +1 -0
- package/dist/validate/prompts/modules/owasp-classic.d.ts +8 -0
- package/dist/validate/prompts/modules/owasp-classic.d.ts.map +1 -0
- package/dist/validate/prompts/modules/owasp-classic.js +84 -0
- package/dist/validate/prompts/modules/owasp-classic.js.map +1 -0
- package/dist/validate/prompts/modules/secrets-crypto.d.ts +8 -0
- package/dist/validate/prompts/modules/secrets-crypto.d.ts.map +1 -0
- package/dist/validate/prompts/modules/secrets-crypto.js +68 -0
- package/dist/validate/prompts/modules/secrets-crypto.js.map +1 -0
- package/dist/validate/prompts/modules/xss-prompt.d.ts +8 -0
- package/dist/validate/prompts/modules/xss-prompt.d.ts.map +1 -0
- package/dist/validate/prompts/modules/xss-prompt.js +22 -0
- package/dist/validate/prompts/modules/xss-prompt.js.map +1 -0
- package/dist/validate/prompts/semantic-analysis.d.ts +15 -0
- package/dist/validate/prompts/semantic-analysis.d.ts.map +1 -0
- package/dist/validate/prompts/semantic-analysis.js +169 -0
- package/dist/validate/prompts/semantic-analysis.js.map +1 -0
- package/dist/validate/prompts/validation.d.ts +18 -0
- package/dist/validate/prompts/validation.d.ts.map +1 -0
- package/dist/validate/prompts/validation.js +25 -0
- package/dist/validate/prompts/validation.js.map +1 -0
- package/dist/validate/providers/anthropic.d.ts +17 -0
- package/dist/validate/providers/anthropic.d.ts.map +1 -0
- package/dist/validate/providers/anthropic.js +260 -0
- package/dist/validate/providers/anthropic.js.map +1 -0
- package/dist/validate/providers/index.d.ts +8 -0
- package/dist/validate/providers/index.d.ts.map +1 -0
- package/dist/validate/providers/index.js +13 -0
- package/dist/validate/providers/index.js.map +1 -0
- package/dist/validate/providers/openai.d.ts +14 -0
- package/dist/validate/providers/openai.d.ts.map +1 -0
- package/dist/validate/providers/openai.js +336 -0
- package/dist/validate/providers/openai.js.map +1 -0
- package/dist/validate/request-builder.d.ts +61 -0
- package/dist/validate/request-builder.d.ts.map +1 -0
- package/dist/validate/request-builder.js +346 -0
- package/dist/validate/request-builder.js.map +1 -0
- package/dist/validate/types.d.ts +88 -0
- package/dist/validate/types.d.ts.map +1 -0
- package/dist/validate/types.js +38 -0
- package/dist/validate/types.js.map +1 -0
- package/dist/validate/utils/context-extractor.d.ts +55 -0
- package/dist/validate/utils/context-extractor.d.ts.map +1 -0
- package/dist/validate/utils/context-extractor.js +161 -0
- package/dist/validate/utils/context-extractor.js.map +1 -0
- package/dist/validate/utils/index.d.ts +11 -0
- package/dist/validate/utils/index.d.ts.map +1 -0
- package/dist/validate/utils/index.js +27 -0
- package/dist/validate/utils/index.js.map +1 -0
- package/dist/validate/utils/path-helpers.d.ts +21 -0
- package/dist/validate/utils/path-helpers.d.ts.map +1 -0
- package/dist/validate/utils/path-helpers.js +69 -0
- package/dist/validate/utils/path-helpers.js.map +1 -0
- package/dist/validate/utils/response-parser.d.ts +40 -0
- package/dist/validate/utils/response-parser.d.ts.map +1 -0
- package/dist/validate/utils/response-parser.js +286 -0
- package/dist/validate/utils/response-parser.js.map +1 -0
- package/dist/validate/utils/retry.d.ts +15 -0
- package/dist/validate/utils/retry.d.ts.map +1 -0
- package/dist/validate/utils/retry.js +62 -0
- package/dist/validate/utils/retry.js.map +1 -0
- package/package.json +8 -7
- package/src/__tests__/benchmark/fixtures/layer1/agent-skill-injection.ts +204 -0
- package/src/__tests__/benchmark/fixtures/layer1/index.ts +3 -0
- package/src/__tests__/benchmark/fixtures/layer2/index.ts +27 -0
- package/src/__tests__/benchmark/fixtures/layer2/log-injection.ts +147 -0
- package/src/__tests__/benchmark/fixtures/layer2/phase5-excessive-agency.ts +580 -0
- package/src/__tests__/benchmark/fixtures/layer2/security-headers.ts +197 -0
- package/src/__tests__/benchmark/fixtures/layer2/sprint6-ai-enhancements.ts +515 -0
- package/src/__tests__/benchmark/fixtures/layer2/ssrf-detection.ts +210 -0
- package/src/__tests__/benchmark/fixtures/layer2/xxe-detection.ts +195 -0
- package/src/__tests__/benchmark/run-depth-validation.ts +12 -12
- package/src/__tests__/benchmark/run-real-world-test.ts +4 -4
- package/src/__tests__/benchmark/types.ts +1 -1
- package/src/__tests__/benchmark/utils/test-runner.ts +3 -3
- package/src/__tests__/category-filter.test.ts +478 -0
- package/src/__tests__/context-engine/cross-file-taint.test.ts +284 -0
- package/src/__tests__/context-engine/framework-models.test.ts +457 -0
- package/src/__tests__/context-engine/function-classifier.test.ts +146 -0
- package/src/__tests__/context-engine/import-resolver.test.ts +328 -0
- package/src/__tests__/context-engine/integration.test.ts +320 -0
- package/src/__tests__/context-engine/module-graph.test.ts +159 -0
- package/src/__tests__/context-engine/route-discovery/auth-resolver.test.ts +353 -0
- package/src/__tests__/context-engine/route-discovery/express.test.ts +150 -0
- package/src/__tests__/context-engine/route-discovery/nextjs.test.ts +138 -0
- package/src/__tests__/context-engine/route-discovery/python.test.ts +95 -0
- package/src/__tests__/context-engine/sanitiser-detection.test.ts +187 -0
- package/src/__tests__/context-engine/sink-matcher.test.ts +251 -0
- package/src/__tests__/context-engine/source-discovery.test.ts +186 -0
- package/src/__tests__/context-engine/taint-tracker.test.ts +182 -0
- package/src/__tests__/regression/agent-skill-benign.test.ts +174 -0
- package/src/__tests__/regression/known-false-positives.test.ts +801 -3
- package/src/__tests__/score/adjustments.test.ts +385 -0
- package/src/__tests__/score/confidence.test.ts +283 -0
- package/src/__tests__/score/framework-scoring.test.ts +275 -0
- package/src/__tests__/score/route-scoring.test.ts +156 -0
- package/src/__tests__/score/scoring-integration.test.ts +165 -0
- package/src/__tests__/score/taint-adjustments.test.ts +244 -0
- package/src/__tests__/snapshots/__snapshots__/anthropic-validation-refactor.test.ts.snap +50 -58
- package/src/__tests__/snapshots/__snapshots__/dangerous-functions-refactor.test.ts.snap +52 -0
- package/src/__tests__/snapshots/__snapshots__/scan-depth.test.ts.snap +3 -12
- package/src/__tests__/snapshots/anthropic-validation-refactor.test.ts +3 -3
- package/src/__tests__/snapshots/dangerous-functions-refactor.test.ts +1 -1
- package/src/__tests__/snapshots/scan-depth.test.ts +3 -3
- package/src/__tests__/validate/route-annotations.test.ts +138 -0
- package/src/__tests__/validation/analyze-results.ts +1 -1
- package/src/__tests__/validation/extract-for-triage.ts +1 -1
- package/src/__tests__/validation/fp-deep-analysis.ts +1 -1
- package/src/__tests__/validation/run-validation.ts +7 -7
- package/src/{layer2/ai-agent-tools.ts → detect/ai-code/agent-tools.ts} +729 -4
- package/src/{layer2 → detect/ai-code}/byok-patterns.ts +20 -6
- package/src/{layer2/ai-endpoint-protection.ts → detect/ai-code/endpoint-protection.ts} +10 -4
- package/src/{layer2/ai-execution-sinks.ts → detect/ai-code/execution-sinks.ts} +272 -46
- package/src/{layer2/ai-fingerprinting.ts → detect/ai-code/fingerprinting.ts} +46 -34
- package/src/detect/ai-code/index.ts +11 -0
- package/src/{layer2/ai-mcp-security.ts → detect/ai-code/mcp-security.ts} +212 -5
- package/src/{layer2 → detect/ai-code}/model-supply-chain.ts +85 -6
- package/src/{layer2/ai-package-hallucination.ts → detect/ai-code/package-hallucination.ts} +170 -6
- package/src/{layer2/ai-prompt-hygiene.ts → detect/ai-code/prompt-hygiene.ts} +393 -28
- package/src/{layer2/ai-rag-safety.ts → detect/ai-code/rag-safety.ts} +91 -4
- package/src/{layer2/ai-schema-validation.ts → detect/ai-code/schema-validation.ts} +10 -4
- package/src/detect/config/agent-skill-injection.ts +551 -0
- package/src/{layer1 → detect/config}/comments.ts +8 -2
- package/src/{layer1 → detect/config}/file-flags.ts +23 -6
- package/src/detect/config/index.ts +6 -0
- package/src/{layer3 → detect/config}/osv-check.ts +3 -2
- package/src/{layer3 → detect/config}/package-check.ts +3 -2
- package/src/{layer1 → detect/config}/urls.ts +196 -15
- package/src/detect/index.ts +131 -0
- package/src/{layer1 → detect/secrets}/config-audit.ts +56 -12
- package/src/{layer1 → detect/secrets}/config-mcp-audit.ts +11 -4
- package/src/{layer1 → detect/secrets}/entropy.ts +256 -11
- package/src/{layer1 → detect/secrets}/index.ts +43 -46
- package/src/{layer1 → detect/secrets}/patterns.ts +51 -6
- package/src/{layer1 → detect/secrets}/weak-crypto.ts +174 -17
- package/src/{layer2/auth-antipatterns.ts → detect/structural/auth-patterns.ts} +249 -27
- package/src/{layer2 → detect/structural}/dangerous-functions/dom-xss.ts +94 -22
- package/src/{layer2 → detect/structural}/dangerous-functions/index.ts +672 -65
- package/src/{layer2 → detect/structural}/dangerous-functions/json-parse.ts +10 -2
- package/src/{layer2 → detect/structural}/dangerous-functions/math-random.ts +269 -17
- package/src/{layer2 → detect/structural}/dangerous-functions/patterns.ts +4 -2
- package/src/{layer2 → detect/structural}/dangerous-functions/request-validation.ts +10 -2
- package/src/detect/structural/dangerous-functions/utils/control-flow.ts +35 -0
- package/src/{layer2 → detect/structural}/dangerous-functions/utils/schema-validation.ts +16 -1
- package/src/{layer2 → detect/structural}/data-exposure.ts +23 -40
- package/src/{layer2 → detect/structural}/framework-checks.ts +13 -12
- package/src/{layer2 → detect/structural}/index.ts +144 -122
- package/src/detect/structural/log-injection.ts +254 -0
- package/src/{layer2 → detect/structural}/logic-gates.ts +69 -24
- package/src/{layer2 → detect/structural}/risky-imports.ts +10 -4
- package/src/detect/structural/security-headers.ts +231 -0
- package/src/detect/structural/ssrf-detection.ts +300 -0
- package/src/{layer2 → detect/structural}/variables.ts +10 -4
- package/src/detect/structural/xxe-detection.ts +295 -0
- package/src/index.ts +64 -1038
- package/src/{utils → model}/auth-helper-detector.ts +1 -1
- package/src/model/cross-file-taint.ts +374 -0
- package/src/model/framework-models/django.ts +82 -0
- package/src/model/framework-models/express.ts +54 -0
- package/src/model/framework-models/index.ts +116 -0
- package/src/model/framework-models/nextjs.ts +69 -0
- package/src/model/framework-models/prisma.ts +57 -0
- package/src/model/framework-models/react.ts +63 -0
- package/src/model/framework-models/sequelize.ts +63 -0
- package/src/model/framework-models/types.ts +46 -0
- package/src/model/function-classifier.ts +184 -0
- package/src/model/import-resolver.ts +453 -0
- package/src/{utils → model}/imported-auth-detector.ts +21 -85
- package/src/model/index.ts +353 -0
- package/src/{utils → model}/middleware-detector.ts +156 -17
- package/src/model/module-graph.ts +254 -0
- package/src/{utils → model}/oauth-flow-detector.ts +1 -1
- package/src/{utils/project-context-builder.ts → model/project-context.ts} +1 -1
- package/src/model/route-auth-resolver.ts +216 -0
- package/src/model/route-discovery/express.ts +251 -0
- package/src/model/route-discovery/index.ts +83 -0
- package/src/model/route-discovery/nextjs.ts +216 -0
- package/src/model/route-discovery/python.ts +214 -0
- package/src/model/route-discovery/types.ts +48 -0
- package/src/model/route-discovery/utils.ts +54 -0
- package/src/model/route-hierarchy.ts +250 -0
- package/src/model/sanitiser-detection.ts +268 -0
- package/src/model/sink-matcher.ts +178 -0
- package/src/model/sink-patterns.ts +109 -0
- package/src/model/source-discovery.ts +209 -0
- package/src/model/taint-tracker.ts +333 -0
- package/src/model/taint-types.ts +149 -0
- package/src/{utils → model}/trpc-analyzer.ts +1 -1
- package/src/{utils/context-helpers.ts → parse/file-classifier.ts} +462 -2
- package/src/{utils → parse}/path-exclusions.ts +1 -1
- package/src/pipeline/config.ts +81 -0
- package/src/pipeline/index.ts +437 -0
- package/src/{modes → pipeline/modes}/incremental.ts +6 -6
- package/src/postprocess/aggregation.ts +74 -0
- package/src/postprocess/contradictions.ts +128 -0
- package/src/postprocess/dedup.ts +62 -0
- package/src/postprocess/filtering/__tests__/pipeline.test.ts +134 -0
- package/src/postprocess/filtering/context-adjustments.ts +111 -0
- package/src/postprocess/filtering/index.ts +10 -0
- package/src/postprocess/filtering/pipeline.ts +130 -0
- package/src/postprocess/index.ts +118 -0
- package/src/{suppression → postprocess/suppression}/config-loader.ts +1 -1
- package/src/{suppression → postprocess/suppression}/hash.ts +1 -1
- package/src/{suppression → postprocess/suppression}/inline-parser.ts +1 -1
- package/src/{suppression → postprocess/suppression}/manager.ts +1 -1
- package/src/{suppression → postprocess/suppression}/types.ts +2 -2
- package/src/postprocess/validation-cap.ts +66 -0
- package/src/report/build-result.ts +94 -0
- package/src/report/enrichment.ts +52 -0
- package/src/report/formatters/__tests__/ai-context.test.ts +254 -0
- package/src/report/formatters/ai-context.ts +302 -0
- package/src/{formatters → report/formatters}/cli-terminal.ts +11 -11
- package/src/{formatters → report/formatters}/github-comment.ts +4 -4
- package/src/{formatters → report/formatters}/grouping.ts +8 -8
- package/src/report/formatters/ide/__tests__/ide.test.ts +319 -0
- package/src/report/formatters/ide/claude-code.ts +110 -0
- package/src/report/formatters/ide/cursor.ts +147 -0
- package/src/report/formatters/ide/index.ts +216 -0
- package/src/report/formatters/ide/windsurf.ts +135 -0
- package/src/{formatters → report/formatters}/index.ts +24 -0
- package/src/{formatters → report/formatters}/vscode-diagnostic.ts +1 -1
- package/src/report/summary.ts +70 -0
- package/src/score/adjustments.ts +387 -0
- package/src/{layer3/anthropic → score}/auto-dismiss.ts +26 -14
- package/src/score/confidence.ts +66 -0
- package/src/score/index.ts +316 -0
- package/src/score/types.ts +187 -0
- package/src/shared/__tests__/code-analysis.test.ts +165 -0
- package/src/shared/__tests__/parsed-file.test.ts +124 -0
- package/src/shared/ai-context/__tests__/manager.test.ts +193 -0
- package/src/shared/ai-context/index.ts +15 -0
- package/src/shared/ai-context/manager.ts +145 -0
- package/src/{baseline → shared/baseline}/__tests__/diff.test.ts +2 -2
- package/src/{baseline → shared/baseline}/__tests__/manager.test.ts +2 -2
- package/src/{baseline → shared/baseline}/diff.ts +1 -1
- package/src/{baseline → shared/baseline}/manager.ts +1 -1
- package/src/shared/category-filter.ts +400 -0
- package/src/{layer2/dangerous-functions/utils/control-flow.ts → shared/code-analysis.ts} +56 -39
- package/src/shared/comment-analyzer.ts +249 -0
- package/src/shared/environment-context.ts +304 -0
- package/src/shared/intent-detector.ts +318 -0
- package/src/shared/parsed-file.ts +103 -0
- package/src/{rules → shared/rules}/__tests__/metadata.test.ts +7 -0
- package/src/{rules → shared/rules}/framework-fixes.ts +1 -1
- package/src/{rules → shared/rules}/metadata.ts +94 -0
- package/src/shared/schema-semantics.ts +233 -0
- package/src/{types.ts → shared/types.ts} +142 -11
- package/src/tiers.ts +27 -10
- package/src/validate/__tests__/context-extractor.test.ts +191 -0
- package/src/validate/__tests__/prompt-assembly.test.ts +233 -0
- package/src/validate/__tests__/request-builder.test.ts +347 -0
- package/src/{layer3/anthropic → validate}/index.ts +8 -7
- package/src/{layer3/anthropic → validate}/prompts/index.ts +2 -0
- package/src/validate/prompts/modules/ai-patterns.ts +153 -0
- package/src/validate/prompts/modules/auth-access.ts +22 -0
- package/src/validate/prompts/modules/common.ts +183 -0
- package/src/validate/prompts/modules/index.ts +204 -0
- package/src/validate/prompts/modules/owasp-classic.ts +81 -0
- package/src/validate/prompts/modules/secrets-crypto.ts +65 -0
- package/src/validate/prompts/modules/xss-prompt.ts +19 -0
- package/src/validate/prompts/validation.ts +20 -0
- package/src/{layer3/anthropic → validate}/providers/anthropic.ts +28 -27
- package/src/validate/providers/index.ts +8 -0
- package/src/{layer3/anthropic → validate}/providers/openai.ts +30 -25
- package/src/validate/request-builder.ts +448 -0
- package/src/{layer3/anthropic → validate}/types.ts +1 -1
- package/src/validate/utils/context-extractor.ts +220 -0
- package/src/{layer3/anthropic → validate}/utils/index.ts +10 -0
- package/src/{layer3/anthropic → validate}/utils/response-parser.ts +2 -1
- package/src/layer3/anthropic/prompts/validation.ts +0 -419
- package/src/layer3/anthropic/providers/index.ts +0 -8
- package/src/layer3/anthropic/request-builder.ts +0 -150
- package/src/layer3/index.ts +0 -168
- /package/src/{layer3 → detect/config}/__tests__/osv-check.test.ts +0 -0
- /package/src/{layer2 → detect/structural}/__tests__/math-random-enhanced.test.ts +0 -0
- /package/src/{layer2 → detect/structural}/dangerous-functions/child-process.ts +0 -0
- /package/src/{layer2 → detect/structural}/dangerous-functions/utils/helpers.ts +0 -0
- /package/src/{layer2 → detect/structural}/dangerous-functions/utils/index.ts +0 -0
- /package/src/{suppression → postprocess/suppression}/__tests__/config-loader.test.ts +0 -0
- /package/src/{suppression → postprocess/suppression}/__tests__/hash.test.ts +0 -0
- /package/src/{suppression → postprocess/suppression}/__tests__/inline-parser.test.ts +0 -0
- /package/src/{suppression → postprocess/suppression}/__tests__/manager.test.ts +0 -0
- /package/src/{suppression → postprocess/suppression}/index.ts +0 -0
- /package/src/{baseline → shared/baseline}/index.ts +0 -0
- /package/src/{baseline → shared/baseline}/types.ts +0 -0
- /package/src/{utils → shared}/diff-detector.ts +0 -0
- /package/src/{utils → shared}/diff-parser.ts +0 -0
- /package/src/{utils → shared}/registry-clients.ts +0 -0
- /package/src/{rules → shared/rules}/__tests__/framework-fixes.test.ts +0 -0
- /package/src/{rules → shared/rules}/index.ts +0 -0
- /package/src/{layer3/anthropic → validate}/clients.ts +0 -0
- /package/src/{layer3/anthropic → validate}/prompts/semantic-analysis.ts +0 -0
- /package/src/{layer3/anthropic → validate}/utils/path-helpers.ts +0 -0
- /package/src/{layer3/anthropic → validate}/utils/retry.ts +0 -0
|
@@ -0,0 +1,1193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Layer 2: Dangerous Function Call Analysis
|
|
4
|
+
*
|
|
5
|
+
* Detects usage of dangerous functions that can lead to security vulnerabilities.
|
|
6
|
+
* This module orchestrates detection across multiple specialized modules.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.DANGEROUS_FUNCTIONS = void 0;
|
|
10
|
+
exports.detectDangerousFunctions = detectDangerousFunctions;
|
|
11
|
+
const file_classifier_1 = require("../../../parse/file-classifier");
|
|
12
|
+
// Pattern definitions
|
|
13
|
+
const patterns_1 = require("./patterns");
|
|
14
|
+
// Child process detection
|
|
15
|
+
const child_process_1 = require("./child-process");
|
|
16
|
+
// DOM/XSS detection
|
|
17
|
+
const dom_xss_1 = require("./dom-xss");
|
|
18
|
+
// JSON.parse detection
|
|
19
|
+
const json_parse_1 = require("./json-parse");
|
|
20
|
+
// Math.random detection
|
|
21
|
+
const math_random_1 = require("./math-random");
|
|
22
|
+
// Request validation detection
|
|
23
|
+
const request_validation_1 = require("./request-validation");
|
|
24
|
+
// Utilities
|
|
25
|
+
const control_flow_1 = require("./utils/control-flow");
|
|
26
|
+
const schema_validation_1 = require("./utils/schema-validation");
|
|
27
|
+
const helpers_1 = require("./utils/helpers");
|
|
28
|
+
// Re-export types and patterns for external use
|
|
29
|
+
var patterns_2 = require("./patterns");
|
|
30
|
+
Object.defineProperty(exports, "DANGEROUS_FUNCTIONS", { enumerable: true, get: function () { return patterns_2.DANGEROUS_FUNCTIONS; } });
|
|
31
|
+
const BASE_CONFIDENCE = 0.40;
|
|
32
|
+
/**
|
|
33
|
+
* Main detection function for dangerous function calls
|
|
34
|
+
*/
|
|
35
|
+
function detectDangerousFunctions(content, filePath, options) {
|
|
36
|
+
const vulnerabilities = [];
|
|
37
|
+
// Skip scanner/fixture files to avoid self-detection
|
|
38
|
+
if ((0, file_classifier_1.isScannerOrFixtureFile)(filePath)) {
|
|
39
|
+
return vulnerabilities;
|
|
40
|
+
}
|
|
41
|
+
const lines = options?.parsed?.lines ?? content.split('\n');
|
|
42
|
+
const isTestFile = (0, file_classifier_1.isTestOrMockFile)(filePath);
|
|
43
|
+
lines.forEach((line, index) => {
|
|
44
|
+
// Skip comment lines
|
|
45
|
+
if ((0, file_classifier_1.isComment)(line))
|
|
46
|
+
return;
|
|
47
|
+
for (const funcPattern of patterns_1.DANGEROUS_FUNCTIONS) {
|
|
48
|
+
// Check language filter
|
|
49
|
+
if (!(0, patterns_1.matchesLanguage)(filePath, funcPattern.languages))
|
|
50
|
+
continue;
|
|
51
|
+
const regex = new RegExp(funcPattern.pattern.source, funcPattern.pattern.flags);
|
|
52
|
+
if (regex.test(line)) {
|
|
53
|
+
// Special handling for innerHTML patterns
|
|
54
|
+
if (funcPattern.name === 'innerHTML assignment' ||
|
|
55
|
+
funcPattern.name === 'dangerouslySetInnerHTML') {
|
|
56
|
+
handleInnerHTMLPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines);
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
// Note: JSON.parse is now handled by standalone detectJSONParseSafe() function
|
|
60
|
+
// which provides better source-aware severity classification
|
|
61
|
+
// Special handling for eval and Function constructor
|
|
62
|
+
if (funcPattern.name === 'eval() usage' ||
|
|
63
|
+
funcPattern.name === 'Function constructor') {
|
|
64
|
+
if (handleEvalPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities)) {
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
// Special handling for child_process exec - verify it's not RegExp.exec
|
|
70
|
+
if (funcPattern.name === 'child_process exec') {
|
|
71
|
+
if (handleChildProcessPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines)) {
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
// Special handling for SQL patterns - check for whitelist validation
|
|
77
|
+
if (funcPattern.name === 'Raw SQL query construction' ||
|
|
78
|
+
funcPattern.name === 'SQL template literal') {
|
|
79
|
+
handleSQLPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines);
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
// Special handling for dynamic file paths - check for path traversal protection
|
|
83
|
+
if (funcPattern.name === 'Dynamic file path' ||
|
|
84
|
+
funcPattern.name === 'Path traversal risk') {
|
|
85
|
+
handleFilePathPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines);
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
// Special handling for Math.random
|
|
89
|
+
if (funcPattern.name === 'Math.random for security') {
|
|
90
|
+
handleMathRandomPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities);
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
// Special handling for Python subprocess/os.system
|
|
94
|
+
if (funcPattern.name === 'os.system/subprocess (Python)') {
|
|
95
|
+
handlePythonSubprocessPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines);
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
// Special handling for regex patterns - check for escaped input
|
|
99
|
+
if (funcPattern.name === 'Potentially unsafe regex') {
|
|
100
|
+
handleRegexPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines);
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
// Special handling for spread operator with user input
|
|
104
|
+
if (funcPattern.name === 'Spread operator with user input') {
|
|
105
|
+
handleSpreadPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines);
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
// Standard handling for all other patterns
|
|
109
|
+
handleStandardPattern(funcPattern, line, index, filePath, isTestFile, vulnerabilities);
|
|
110
|
+
break; // Only report once per line
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
// Additional standalone checks (not in DANGEROUS_FUNCTIONS array)
|
|
115
|
+
// JSON.parse source-aware detection
|
|
116
|
+
(0, json_parse_1.detectJSONParseSafe)(content, filePath, isTestFile, vulnerabilities);
|
|
117
|
+
// request.json() / req.json() schema validation suggestion
|
|
118
|
+
(0, request_validation_1.detectRequestJsonValidation)(content, filePath, isTestFile, vulnerabilities);
|
|
119
|
+
return vulnerabilities;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Handle innerHTML/dangerouslySetInnerHTML patterns
|
|
123
|
+
*/
|
|
124
|
+
function handleInnerHTMLPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines) {
|
|
125
|
+
// Check if this is a style element (CSS injection is not XSS)
|
|
126
|
+
if ((0, dom_xss_1.isStyleElementInnerHTML)(line, content, index, lines)) {
|
|
127
|
+
// Style elements with CSS are safe - don't report anything
|
|
128
|
+
// CSS cannot execute JavaScript, so there's no XSS risk
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
// Check if this uses static content only - skip entirely (safe)
|
|
132
|
+
if ((0, dom_xss_1.isStaticHTMLContent)(line, content, index, lines)) {
|
|
133
|
+
return; // Static HTML is safe - no finding needed
|
|
134
|
+
}
|
|
135
|
+
// Check if DOMPurify or similar sanitization is used - skip entirely (safe)
|
|
136
|
+
if ((0, dom_xss_1.hasDOMPurifySanitization)(line, content, index, lines)) {
|
|
137
|
+
return; // Sanitized HTML is safe - no finding needed
|
|
138
|
+
}
|
|
139
|
+
// Check if this is a static bootstrap script (e.g., theme/font loader) - skip entirely (safe)
|
|
140
|
+
if ((0, dom_xss_1.isStaticBootstrapScript)(line, content, index, lines)) {
|
|
141
|
+
return; // Static bootstrap scripts are safe - no finding needed
|
|
142
|
+
}
|
|
143
|
+
// Check if this uses output from trusted HTML rendering libraries (Shiki, highlight.js, marked, etc.)
|
|
144
|
+
// These libraries produce sanitized HTML output
|
|
145
|
+
if ((0, dom_xss_1.isTrustedLibraryHTMLOutput)(line, content, index, lines)) {
|
|
146
|
+
return; // Trusted library output is safe - no finding needed
|
|
147
|
+
}
|
|
148
|
+
// Check if this is in LLM prompt context (not XSS - it's prompt injection)
|
|
149
|
+
if ((0, dom_xss_1.isLLMPromptContext)(line, content, filePath)) {
|
|
150
|
+
vulnerabilities.push({
|
|
151
|
+
id: `dangerous-func-${filePath}-${index + 1}-prompt-injection`,
|
|
152
|
+
filePath,
|
|
153
|
+
lineNumber: index + 1,
|
|
154
|
+
lineContent: line.trim(),
|
|
155
|
+
severity: 'info',
|
|
156
|
+
category: 'ai_pattern',
|
|
157
|
+
title: 'Potential prompt injection risk',
|
|
158
|
+
description: 'User content is being used in an LLM prompt context. This is NOT XSS (the content goes to an AI, not a DOM). However, untrusted content in prompts may lead to prompt injection attacks.',
|
|
159
|
+
suggestedFix: 'Consider input validation, content filtering, or structured prompts to limit prompt injection risk.',
|
|
160
|
+
confidence: 'low',
|
|
161
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
162
|
+
layer: 2,
|
|
163
|
+
source: 'structural',
|
|
164
|
+
});
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
// Dynamic content - full severity, needs AI validation
|
|
168
|
+
let severity = funcPattern.severity;
|
|
169
|
+
if (isTestFile) {
|
|
170
|
+
severity = 'low';
|
|
171
|
+
}
|
|
172
|
+
vulnerabilities.push({
|
|
173
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
174
|
+
filePath,
|
|
175
|
+
lineNumber: index + 1,
|
|
176
|
+
lineContent: line.trim(),
|
|
177
|
+
severity,
|
|
178
|
+
category: 'dangerous_function',
|
|
179
|
+
title: funcPattern.name,
|
|
180
|
+
description: funcPattern.description +
|
|
181
|
+
' This appears to use dynamic content which increases XSS risk.' +
|
|
182
|
+
(isTestFile ? ' (in test file)' : ''),
|
|
183
|
+
suggestedFix: funcPattern.suggestedFix,
|
|
184
|
+
confidence: isTestFile ? 'low' : 'high',
|
|
185
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
186
|
+
layer: 2,
|
|
187
|
+
source: 'structural', requiresAIValidation: true, // Dynamic HTML needs validation
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Handle eval and Function constructor patterns
|
|
192
|
+
* Returns true if a finding was added, false otherwise
|
|
193
|
+
*/
|
|
194
|
+
function handleEvalPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities) {
|
|
195
|
+
// Check if "eval" or "Function" appears inside a string literal
|
|
196
|
+
// e.g., const docs = "Don't use eval() in production"
|
|
197
|
+
// This is NOT an actual eval call, just documentation/comments
|
|
198
|
+
const evalInsideStringPattern = /(['"`])(?:[^\\]|\\.)*?\beval\s*\(.*?\1/;
|
|
199
|
+
const functionInsideStringPattern = /(['"`])(?:[^\\]|\\.)*?\bFunction\s*\(.*?\1/;
|
|
200
|
+
if (evalInsideStringPattern.test(line) || functionInsideStringPattern.test(line)) {
|
|
201
|
+
return true; // Skip - this is just a string mentioning eval, not actual eval()
|
|
202
|
+
}
|
|
203
|
+
// Suppress entirely in test files - test files legitimately test eval behavior
|
|
204
|
+
if (isTestFile) {
|
|
205
|
+
return true; // Skip reporting entirely
|
|
206
|
+
}
|
|
207
|
+
// Check if eval is inside a test assertion (expect(), test(), it(), describe())
|
|
208
|
+
const testAssertionPattern = /\b(expect|test|it|describe)\s*\(/;
|
|
209
|
+
if (testAssertionPattern.test(line)) {
|
|
210
|
+
return true; // Skip reporting - this is testing eval behavior
|
|
211
|
+
}
|
|
212
|
+
// Check if inputs are static literals (low risk) - skip entirely
|
|
213
|
+
if ((0, helpers_1.hasOnlyStaticInputs)(line, content, index)) {
|
|
214
|
+
return true; // Static eval is safe enough - no finding needed
|
|
215
|
+
}
|
|
216
|
+
vulnerabilities.push({
|
|
217
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
218
|
+
filePath,
|
|
219
|
+
lineNumber: index + 1,
|
|
220
|
+
lineContent: line.trim(),
|
|
221
|
+
severity: funcPattern.severity,
|
|
222
|
+
category: 'dangerous_function',
|
|
223
|
+
title: funcPattern.name,
|
|
224
|
+
description: funcPattern.description,
|
|
225
|
+
suggestedFix: funcPattern.suggestedFix,
|
|
226
|
+
confidence: 'high',
|
|
227
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
228
|
+
layer: 2,
|
|
229
|
+
source: 'structural', requiresAIValidation: true, // Code execution patterns need validation
|
|
230
|
+
});
|
|
231
|
+
return true;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Handle child_process exec patterns
|
|
235
|
+
* Returns true if a finding was added, false otherwise
|
|
236
|
+
*/
|
|
237
|
+
function handleChildProcessPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines) {
|
|
238
|
+
// First check if this is actually from child_process (not RegExp.exec)
|
|
239
|
+
const isExecMatch = /\bexec\s*\(/.test(line);
|
|
240
|
+
const isOtherMatch = /\b(execSync|spawn|spawnSync|execFile)\s*\(/.test(line);
|
|
241
|
+
if (isExecMatch && !isOtherMatch) {
|
|
242
|
+
// This matched 'exec(' - verify it's from child_process
|
|
243
|
+
if (!(0, child_process_1.isChildProcessExec)(content, line)) {
|
|
244
|
+
// This is RegExp.exec or similar - skip
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else if (isOtherMatch) {
|
|
249
|
+
// This matched spawn/execSync/etc - verify child_process import
|
|
250
|
+
if (!(0, child_process_1.isChildProcessSpawn)(content, line)) {
|
|
251
|
+
// No child_process import - skip
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// Check if arguments are validated via allowlist
|
|
256
|
+
const _lines = lines ?? content.split('\n');
|
|
257
|
+
const contextStart = Math.max(0, index - 15);
|
|
258
|
+
const contextEnd = Math.min(_lines.length, index + 5);
|
|
259
|
+
const context = _lines.slice(contextStart, contextEnd).join('\n');
|
|
260
|
+
// Detect allowlist validation patterns before exec/spawn
|
|
261
|
+
const hasArgAllowlist = /allowedArgs\.includes\s*\(/i.test(context) ||
|
|
262
|
+
/if\s*\(\s*!?allowedArgs\.includes/i.test(context) ||
|
|
263
|
+
/if\s*\(\s*!?\w+Args\.includes/i.test(context) ||
|
|
264
|
+
/validArgs\.includes/i.test(context) ||
|
|
265
|
+
// ALLOWED_COMMANDS pattern (common naming convention)
|
|
266
|
+
/ALLOWED_\w+\.includes\s*\(/i.test(context) ||
|
|
267
|
+
/if\s*\(\s*!?ALLOWED_\w+\.includes/i.test(context) ||
|
|
268
|
+
// allowedCommands, validCommands, safeCommands
|
|
269
|
+
/allowed(?:Commands?|Cmds?)\.includes\s*\(/i.test(context) ||
|
|
270
|
+
/valid(?:Commands?|Cmds?)\.includes\s*\(/i.test(context) ||
|
|
271
|
+
/safe(?:Commands?|Cmds?)\.includes\s*\(/i.test(context) ||
|
|
272
|
+
// Generic whitelist/allowlist check
|
|
273
|
+
/(?:whitelist|allowlist)\.includes\s*\(/i.test(context);
|
|
274
|
+
// execFile with hardcoded command is safe (safer than exec)
|
|
275
|
+
const isExecFileWithHardcodedCmd = /execFile\s*\(\s*['"][^'"]+['"]/i.test(line);
|
|
276
|
+
if (hasArgAllowlist || isExecFileWithHardcodedCmd) {
|
|
277
|
+
return true; // Allowlisted or execFile with hardcoded command - safe
|
|
278
|
+
}
|
|
279
|
+
if ((0, helpers_1.hasOnlyStaticInputs)(line, content, index)) {
|
|
280
|
+
return true; // Static command is safe - no finding needed
|
|
281
|
+
}
|
|
282
|
+
// Check for build/script context with hardcoded command + args array
|
|
283
|
+
const isBuildScript = /(build|generate|format|lint|setup|deploy|migrate|compile)/i.test(filePath) ||
|
|
284
|
+
/\/(scripts?|tools?|bin)\//i.test(filePath);
|
|
285
|
+
if (isBuildScript) {
|
|
286
|
+
// spawnSync("cmd", ["arg1", "arg2"]) with string literal command is safe in build scripts
|
|
287
|
+
const hasHardcodedCommand = /spawn(?:Sync)?\s*\(\s*['"][^'"]+['"]/.test(line);
|
|
288
|
+
if (hasHardcodedCommand) {
|
|
289
|
+
vulnerabilities.push({
|
|
290
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
291
|
+
filePath,
|
|
292
|
+
lineNumber: index + 1,
|
|
293
|
+
lineContent: line.trim(),
|
|
294
|
+
severity: 'info',
|
|
295
|
+
category: 'dangerous_function',
|
|
296
|
+
title: funcPattern.name + ' (build script)',
|
|
297
|
+
description: 'Shell command execution in build/tooling script with hardcoded command. Build scripts are developer-controlled.',
|
|
298
|
+
suggestedFix: 'Ensure this script is not exposed to untrusted input.',
|
|
299
|
+
confidence: 'low',
|
|
300
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
301
|
+
layer: 2,
|
|
302
|
+
source: 'structural',
|
|
303
|
+
});
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// Check for desktop app or MCP server context
|
|
308
|
+
// These contexts legitimately spawn processes
|
|
309
|
+
const isDesktopApp = (0, file_classifier_1.isDesktopAppContext)(filePath);
|
|
310
|
+
const isMcpServer = (0, file_classifier_1.isMcpServerContext)(filePath);
|
|
311
|
+
if (isDesktopApp || isMcpServer) {
|
|
312
|
+
// Desktop apps and MCP servers legitimately spawn processes
|
|
313
|
+
// Still report but with reduced severity and context
|
|
314
|
+
const contextType = isDesktopApp ? 'desktop app' : 'MCP server';
|
|
315
|
+
vulnerabilities.push({
|
|
316
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
317
|
+
filePath,
|
|
318
|
+
lineNumber: index + 1,
|
|
319
|
+
lineContent: line.trim(),
|
|
320
|
+
severity: 'medium', // Reduced from high
|
|
321
|
+
category: 'dangerous_function',
|
|
322
|
+
title: `${funcPattern.name} (${contextType})`,
|
|
323
|
+
description: `${funcPattern.description} (Expected in ${contextType} context - verify input validation)`,
|
|
324
|
+
suggestedFix: 'Ensure command arguments from IPC are validated against an allowlist.',
|
|
325
|
+
confidence: 'medium',
|
|
326
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
327
|
+
layer: 2,
|
|
328
|
+
source: 'structural',
|
|
329
|
+
});
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
// Dynamic command - report with standard severity
|
|
333
|
+
let severity = funcPattern.severity;
|
|
334
|
+
let confidence = 'high';
|
|
335
|
+
if (isTestFile) {
|
|
336
|
+
if (severity === 'critical') {
|
|
337
|
+
severity = 'medium';
|
|
338
|
+
}
|
|
339
|
+
else if (severity === 'high') {
|
|
340
|
+
severity = 'low';
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
severity = 'info';
|
|
344
|
+
}
|
|
345
|
+
confidence = 'low';
|
|
346
|
+
}
|
|
347
|
+
vulnerabilities.push({
|
|
348
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
349
|
+
filePath,
|
|
350
|
+
lineNumber: index + 1,
|
|
351
|
+
lineContent: line.trim(),
|
|
352
|
+
severity,
|
|
353
|
+
category: 'dangerous_function',
|
|
354
|
+
title: funcPattern.name,
|
|
355
|
+
description: funcPattern.description + (isTestFile ? ' (in test file)' : ''),
|
|
356
|
+
suggestedFix: funcPattern.suggestedFix,
|
|
357
|
+
confidence,
|
|
358
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
359
|
+
layer: 2,
|
|
360
|
+
source: 'structural',
|
|
361
|
+
});
|
|
362
|
+
return true;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Handle SQL injection patterns
|
|
366
|
+
*/
|
|
367
|
+
function handleSQLPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines) {
|
|
368
|
+
// Check for whitelist validation - skip entirely (safe)
|
|
369
|
+
if ((0, schema_validation_1.hasSQLWhitelistValidation)(content, index)) {
|
|
370
|
+
return; // Whitelist validated - safe, no finding needed
|
|
371
|
+
}
|
|
372
|
+
// Check for ORM methods (not raw SQL) - skip entirely (safe)
|
|
373
|
+
// Prisma: prisma.user.findMany({ where: {...} })
|
|
374
|
+
// Sequelize: Model.findAll({ where: {...} })
|
|
375
|
+
// TypeORM: repository.find({ where: {...} })
|
|
376
|
+
const ormMethodPattern = /\.(findMany|findUnique|findFirst|findAll|find|create|update|delete|upsert)\s*\(\s*\{/i;
|
|
377
|
+
if (ormMethodPattern.test(line)) {
|
|
378
|
+
return; // ORM method - safe, no finding needed
|
|
379
|
+
}
|
|
380
|
+
// Check for parameterized queries - skip entirely (safe)
|
|
381
|
+
// e.g., db.query('SELECT * FROM users WHERE id = $1', [userId])
|
|
382
|
+
const parameterizedQueryPattern = /\.\s*(query|execute)\s*\(\s*['"`][^${}]+['"`]\s*,\s*\[/;
|
|
383
|
+
if (parameterizedQueryPattern.test(line)) {
|
|
384
|
+
return; // Parameterized query - safe, no finding needed
|
|
385
|
+
}
|
|
386
|
+
// Knex .raw() with ? placeholders and array binding - this IS parameterized
|
|
387
|
+
// e.g., db.raw(`"table"."col" + ?`, [value]) or db.raw('SELECT ... WHERE id = ?', [id])
|
|
388
|
+
const knexRawParameterized = /\.raw\s*\(\s*[`'"]/i.test(line) &&
|
|
389
|
+
/\?\s*[`'"]\s*,\s*\[/.test(line);
|
|
390
|
+
if (knexRawParameterized) {
|
|
391
|
+
return; // Knex .raw() with ? placeholders is parameterized - safe
|
|
392
|
+
}
|
|
393
|
+
// Knex .raw() with only const enum/table name interpolation (not user input)
|
|
394
|
+
// e.g., db.raw(`"${TableName.Users}"."col"`) where TableName is a const enum
|
|
395
|
+
const knexRawConstInterpolation = /\.raw\s*\(\s*`/.test(line) &&
|
|
396
|
+
/\$\{[A-Z][A-Za-z]*\.[A-Z]/.test(line);
|
|
397
|
+
if (knexRawConstInterpolation) {
|
|
398
|
+
const interpolations = line.match(/\$\{([^}]+)\}/g) || [];
|
|
399
|
+
const allConst = interpolations.every(i => /^\$\{[A-Z_][A-Z_a-z]*\./.test(i));
|
|
400
|
+
if (allConst) {
|
|
401
|
+
return; // Only const enum interpolation - safe
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
// Knex .raw() for SET statement_timeout (infrastructure, not user input)
|
|
405
|
+
// e.g., trx.raw(`SET statement_timeout = ${QUERY_TIMEOUT_MS}`)
|
|
406
|
+
const isSetStatement = /\.raw\s*\(\s*[`'"]SET\s+/i.test(line);
|
|
407
|
+
if (isSetStatement) {
|
|
408
|
+
return; // SET statements are infrastructure config, not queries with user data
|
|
409
|
+
}
|
|
410
|
+
// DROP TRIGGER / DDL statements from migration/schema files
|
|
411
|
+
const isDDLStatement = /\.raw\s*\(\s*[`'"](DROP|CREATE|ALTER)\s+/i.test(line) &&
|
|
412
|
+
/(migration|schema|seed)/i.test(filePath);
|
|
413
|
+
if (isDDLStatement) {
|
|
414
|
+
return; // DDL in migration/schema files - not user-facing
|
|
415
|
+
}
|
|
416
|
+
// Check for Prisma tagged template literal - these ARE parameterized (safe)
|
|
417
|
+
// Prisma's $queryRaw`...${var}...` treats ${} as parameterized values, not string interpolation
|
|
418
|
+
// e.g., prisma.$queryRaw`SELECT * FROM users WHERE id = ${userId}`
|
|
419
|
+
const prismaTaggedTemplatePattern = /\$queryRaw\s*`[^`]*\$\{/i;
|
|
420
|
+
if (prismaTaggedTemplatePattern.test(line)) {
|
|
421
|
+
return; // Prisma tagged template - parameterized and safe, no finding needed
|
|
422
|
+
}
|
|
423
|
+
// Check for schema-validated input (zod .enum() for table/column names)
|
|
424
|
+
// e.g., z.enum(['users', 'posts']).parse(input) followed by SQL
|
|
425
|
+
const _lines = lines ?? content.split('\n');
|
|
426
|
+
const contextStart = Math.max(0, index - 20);
|
|
427
|
+
const contextEnd = index;
|
|
428
|
+
const previousContext = _lines.slice(contextStart, contextEnd).join('\n');
|
|
429
|
+
// Detect zod enum validation for SQL identifiers
|
|
430
|
+
const hasSchemaValidation = /z\s*\.\s*enum\s*\(\s*\[['"][^'"]+['"]/i.test(previousContext) ||
|
|
431
|
+
/\.parse\s*\(\s*JSON\.parse/.test(previousContext) ||
|
|
432
|
+
// Allow validated table/column names from parsed schema
|
|
433
|
+
/schema\.parse/.test(previousContext) ||
|
|
434
|
+
/const\s+parsed\s*=\s*schema/.test(previousContext);
|
|
435
|
+
if (hasSchemaValidation) {
|
|
436
|
+
return; // Schema-validated SQL identifiers - safe, no finding needed
|
|
437
|
+
}
|
|
438
|
+
// No whitelist - report with standard severity
|
|
439
|
+
let severity = funcPattern.severity;
|
|
440
|
+
let confidence = 'high';
|
|
441
|
+
if (isTestFile) {
|
|
442
|
+
if (severity === 'critical') {
|
|
443
|
+
severity = 'medium';
|
|
444
|
+
}
|
|
445
|
+
else if (severity === 'high') {
|
|
446
|
+
severity = 'low';
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
severity = 'info';
|
|
450
|
+
}
|
|
451
|
+
confidence = 'low';
|
|
452
|
+
}
|
|
453
|
+
vulnerabilities.push({
|
|
454
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
455
|
+
filePath,
|
|
456
|
+
lineNumber: index + 1,
|
|
457
|
+
lineContent: line.trim(),
|
|
458
|
+
severity,
|
|
459
|
+
category: 'dangerous_function',
|
|
460
|
+
title: funcPattern.name,
|
|
461
|
+
description: funcPattern.description + (isTestFile ? ' (in test file)' : ''),
|
|
462
|
+
suggestedFix: funcPattern.suggestedFix,
|
|
463
|
+
confidence,
|
|
464
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
465
|
+
layer: 2,
|
|
466
|
+
source: 'structural',
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Handle dynamic file path patterns
|
|
471
|
+
*/
|
|
472
|
+
function handleFilePathPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines) {
|
|
473
|
+
// Check for desktop app context (Electron, Tauri, etc.)
|
|
474
|
+
// Desktop apps legitimately access filesystem
|
|
475
|
+
const isDesktopApp = (0, file_classifier_1.isDesktopAppContext)(filePath);
|
|
476
|
+
// Check for file loader context
|
|
477
|
+
// File loaders legitimately access filesystem to process files
|
|
478
|
+
const isFileLoader = (0, file_classifier_1.isFileLoaderContext)(filePath);
|
|
479
|
+
// Desktop apps and file loaders are expected to access filesystem
|
|
480
|
+
if (isDesktopApp || isFileLoader) {
|
|
481
|
+
const contextType = isDesktopApp ? 'desktop app' : 'file loader';
|
|
482
|
+
vulnerabilities.push({
|
|
483
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
484
|
+
filePath,
|
|
485
|
+
lineNumber: index + 1,
|
|
486
|
+
lineContent: line.trim(),
|
|
487
|
+
severity: 'info',
|
|
488
|
+
category: 'dangerous_function',
|
|
489
|
+
title: `${funcPattern.name} (${contextType})`,
|
|
490
|
+
description: `Dynamic file path in ${contextType} context. File system access is expected functionality. Verify path inputs are validated.`,
|
|
491
|
+
suggestedFix: 'Ensure file paths are validated and constrained to expected directories.',
|
|
492
|
+
confidence: 'low',
|
|
493
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
494
|
+
layer: 2,
|
|
495
|
+
source: 'structural',
|
|
496
|
+
});
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
// Check file context for CLI/tooling (lower risk)
|
|
500
|
+
const isCLITool = /\/(cli|scripts?|tools?|bin)\//i.test(filePath) ||
|
|
501
|
+
/cli\.(ts|js)$/i.test(filePath);
|
|
502
|
+
// Check for GitHub Action context (workflow-controlled paths)
|
|
503
|
+
const isGitHubAction = /\/(github-action|actions?)\//i.test(filePath) ||
|
|
504
|
+
/action\.(ts|js)$/i.test(filePath);
|
|
505
|
+
// Check for utility/helper file context (called by trusted code)
|
|
506
|
+
const isUtilityFile = /\/(utils?|helpers?|lib|common|shared)\//i.test(filePath) ||
|
|
507
|
+
/(util(s)?|helper(s)?|checksum|hash)\.(ts|js)$/i.test(filePath);
|
|
508
|
+
// Check for server infrastructure/config files (transport, signing, credentials)
|
|
509
|
+
// These files read/write config-controlled paths, not user input
|
|
510
|
+
const isServerInfrastructureFile = /\/(transports?|signing|credentials?|certificates?|certs?)\//i.test(filePath) ||
|
|
511
|
+
/\/(config|infrastructure|provisioning)\//i.test(filePath) ||
|
|
512
|
+
/(transport|signer|credential|certificate)\.(ts|js)$/i.test(filePath);
|
|
513
|
+
// Get surrounding context for protection check
|
|
514
|
+
const _lines = lines ?? content.split('\n');
|
|
515
|
+
const contextStart = Math.max(0, index - 10);
|
|
516
|
+
const contextEnd = Math.min(_lines.length, index + 10);
|
|
517
|
+
const context = _lines.slice(contextStart, contextEnd).join('\n');
|
|
518
|
+
// Check if path comes from directory iteration (fs.readdir, fs.readdirSync)
|
|
519
|
+
// These paths are filesystem-controlled, not user input
|
|
520
|
+
const hasDirectoryIteration = /\b(readdir|readdirSync|opendir|opendirSync)\s*\(/.test(content) &&
|
|
521
|
+
(/for\s*\(\s*(const|let|var)\s+\w+\s+of/.test(context) ||
|
|
522
|
+
/\.forEach\s*\(/.test(context) ||
|
|
523
|
+
/\.map\s*\(/.test(context) || // array.map() iteration
|
|
524
|
+
/pMap\s*\(/.test(context) || // p-map library (parallel map)
|
|
525
|
+
/Promise\.all\s*\(/.test(context) || // Promise.all mapping
|
|
526
|
+
/entry\.(name|isFile|isDirectory)/.test(context) ||
|
|
527
|
+
/dirent\.(name|isFile|isDirectory)/.test(context));
|
|
528
|
+
if ((0, helpers_1.hasPathTraversalProtection)(context, line)) {
|
|
529
|
+
vulnerabilities.push({
|
|
530
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
531
|
+
filePath,
|
|
532
|
+
lineNumber: index + 1,
|
|
533
|
+
lineContent: line.trim(),
|
|
534
|
+
severity: 'info',
|
|
535
|
+
category: 'dangerous_function',
|
|
536
|
+
title: funcPattern.name + ' (protected)',
|
|
537
|
+
description: 'Dynamic file path with path traversal protection detected. Verify the protection is complete and covers all attack vectors.',
|
|
538
|
+
suggestedFix: 'Ensure path normalization and base directory checks are applied consistently.',
|
|
539
|
+
confidence: 'low',
|
|
540
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
541
|
+
layer: 2,
|
|
542
|
+
source: 'structural',
|
|
543
|
+
});
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
// Directory iteration paths are filesystem-controlled (not user input)
|
|
547
|
+
if (hasDirectoryIteration) {
|
|
548
|
+
// Skip entirely - paths from fs.readdir are not user-controlled
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
// Check for Object.entries/keys/values over hardcoded objects
|
|
552
|
+
// Pattern: for (const [key, val] of Object.entries(STATIC_OBJ))
|
|
553
|
+
const hasHardcodedObjectIteration = (() => {
|
|
554
|
+
// Look for Object.entries/keys/values in context
|
|
555
|
+
const hasObjectIteration = /Object\.(entries|keys|values)\s*\(/.test(context);
|
|
556
|
+
if (!hasObjectIteration)
|
|
557
|
+
return false;
|
|
558
|
+
// Check if the object being iterated is defined as a const literal nearby
|
|
559
|
+
// Pattern: const objName = { ... }; ... Object.entries(objName)
|
|
560
|
+
const objectMatch = context.match(/Object\.(entries|keys|values)\s*\(\s*(\w+)\s*\)/);
|
|
561
|
+
if (!objectMatch)
|
|
562
|
+
return false;
|
|
563
|
+
const objName = objectMatch[2];
|
|
564
|
+
// Check if objName is defined as a const object literal in the file
|
|
565
|
+
const isConstObject = new RegExp(`const\\s+${objName}\\s*=\\s*\\{`).test(content);
|
|
566
|
+
return isConstObject;
|
|
567
|
+
})();
|
|
568
|
+
if (hasHardcodedObjectIteration) {
|
|
569
|
+
// Skip entirely - iterating over hardcoded object, not user input
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
572
|
+
// GitHub Action paths are workflow-controlled (not arbitrary user input)
|
|
573
|
+
if (isGitHubAction) {
|
|
574
|
+
vulnerabilities.push({
|
|
575
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
576
|
+
filePath,
|
|
577
|
+
lineNumber: index + 1,
|
|
578
|
+
lineContent: line.trim(),
|
|
579
|
+
severity: 'info',
|
|
580
|
+
category: 'dangerous_function',
|
|
581
|
+
title: funcPattern.name + ' (GitHub Action)',
|
|
582
|
+
description: 'Dynamic file path in GitHub Action. Paths are typically controlled by workflow configuration, not arbitrary user input.',
|
|
583
|
+
suggestedFix: 'Verify paths come from trusted action inputs or environment variables.',
|
|
584
|
+
confidence: 'low',
|
|
585
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
586
|
+
layer: 2,
|
|
587
|
+
source: 'structural',
|
|
588
|
+
});
|
|
589
|
+
return;
|
|
590
|
+
}
|
|
591
|
+
// CLI tools with dynamic paths are lower risk (trusted operator)
|
|
592
|
+
if (isCLITool) {
|
|
593
|
+
vulnerabilities.push({
|
|
594
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
595
|
+
filePath,
|
|
596
|
+
lineNumber: index + 1,
|
|
597
|
+
lineContent: line.trim(),
|
|
598
|
+
severity: 'info',
|
|
599
|
+
category: 'dangerous_function',
|
|
600
|
+
title: funcPattern.name + ' (CLI tool)',
|
|
601
|
+
description: 'Dynamic file path in CLI tool. CLI tools typically have trusted operators, but consider adding path validation if user input is involved.',
|
|
602
|
+
suggestedFix: 'Add path validation if accepting paths from untrusted sources.',
|
|
603
|
+
confidence: 'low',
|
|
604
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
605
|
+
layer: 2,
|
|
606
|
+
source: 'structural',
|
|
607
|
+
});
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
// Utility/helper files with function parameters are lower risk (called by trusted code)
|
|
611
|
+
// Check if path variable appears to be a function parameter, not from request
|
|
612
|
+
const hasRequestData = /req\.(params|query|body)|request\.(params|query|body)/i.test(context);
|
|
613
|
+
if (isUtilityFile && !hasRequestData) {
|
|
614
|
+
// Skip entirely - utility functions receive paths from trusted callers
|
|
615
|
+
return;
|
|
616
|
+
}
|
|
617
|
+
// Server infrastructure files (signing, transport, credentials) use config-controlled paths
|
|
618
|
+
// These paths come from environment variables or internal configuration, not user input
|
|
619
|
+
if (isServerInfrastructureFile && !hasRequestData) {
|
|
620
|
+
// Check if path comes from environment variables or function parameters
|
|
621
|
+
const hasEnvVarPath = /process\.env\.|import\.meta\.env\.|env\s*\(/i.test(context);
|
|
622
|
+
const hasConfigPath = /config\.|settings\.|credentials?\./i.test(context);
|
|
623
|
+
const hasCertPath = /certPath|keyPath|credentialsPath|googleApplicationCredentials/i.test(context);
|
|
624
|
+
if (hasEnvVarPath || hasConfigPath || hasCertPath) {
|
|
625
|
+
// Skip entirely - paths from env vars/config are not user-controlled
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
// Check if file path variable comes from environment variable wrapper function
|
|
630
|
+
// Common pattern: env('VAR_NAME') || 'default', process.env.VAR, etc.
|
|
631
|
+
const hasEnvVarSource = /env\s*\(\s*['"][^'"]+['"]\s*\)|process\.env\.\w+|import\.meta\.env\.\w+/i.test(context);
|
|
632
|
+
const hasOnlyConfigSource = hasEnvVarSource && !hasRequestData;
|
|
633
|
+
if (hasOnlyConfigSource) {
|
|
634
|
+
// Path comes from environment variable, not user input - skip
|
|
635
|
+
return;
|
|
636
|
+
}
|
|
637
|
+
// Standard handling for unprotected paths
|
|
638
|
+
let severity = funcPattern.severity;
|
|
639
|
+
let confidence = 'high';
|
|
640
|
+
if (isTestFile) {
|
|
641
|
+
if (severity === 'critical') {
|
|
642
|
+
severity = 'medium';
|
|
643
|
+
}
|
|
644
|
+
else if (severity === 'high') {
|
|
645
|
+
severity = 'low';
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
severity = 'info';
|
|
649
|
+
}
|
|
650
|
+
confidence = 'low';
|
|
651
|
+
}
|
|
652
|
+
vulnerabilities.push({
|
|
653
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
654
|
+
filePath,
|
|
655
|
+
lineNumber: index + 1,
|
|
656
|
+
lineContent: line.trim(),
|
|
657
|
+
severity,
|
|
658
|
+
category: 'dangerous_function',
|
|
659
|
+
title: funcPattern.name,
|
|
660
|
+
description: funcPattern.description + (isTestFile ? ' (in test file)' : ''),
|
|
661
|
+
suggestedFix: funcPattern.suggestedFix,
|
|
662
|
+
confidence,
|
|
663
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
664
|
+
layer: 2,
|
|
665
|
+
source: 'structural',
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
/**
|
|
669
|
+
* Handle Math.random patterns with context-aware severity
|
|
670
|
+
*/
|
|
671
|
+
function handleMathRandomPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities) {
|
|
672
|
+
// Skip entirely for certain contexts
|
|
673
|
+
if ((0, math_random_1.shouldSkipMathRandom)(content, filePath, index)) {
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
// Analyze context
|
|
677
|
+
const functionName = (0, control_flow_1.extractFunctionContext)(content, index);
|
|
678
|
+
const functionIntent = (0, math_random_1.classifyFunctionIntent)(functionName);
|
|
679
|
+
const toStringPattern = (0, math_random_1.analyzeToStringPattern)(line);
|
|
680
|
+
const variableName = (0, math_random_1.extractMathRandomVariableName)(line);
|
|
681
|
+
const variableRisk = (0, math_random_1.classifyVariableNameRisk)(variableName);
|
|
682
|
+
const context = (0, math_random_1.analyzeMathRandomContext)(content, filePath, index);
|
|
683
|
+
// Determine severity based on all factors
|
|
684
|
+
let severity;
|
|
685
|
+
let confidence;
|
|
686
|
+
let description;
|
|
687
|
+
let suggestedFix;
|
|
688
|
+
let explanation = '';
|
|
689
|
+
// Variable name indicates security risk - check this FIRST before toString patterns
|
|
690
|
+
// This ensures 'secret', 'token', 'key' etc. are always flagged as high
|
|
691
|
+
if (variableRisk === 'high') {
|
|
692
|
+
severity = 'high';
|
|
693
|
+
confidence = 'high';
|
|
694
|
+
// Update context description to indicate security context
|
|
695
|
+
context.contextDescription = 'security-sensitive variable';
|
|
696
|
+
description = `Math.random() assigned to security-sensitive variable '${variableName}'. Math.random() is NOT cryptographically secure.`;
|
|
697
|
+
suggestedFix =
|
|
698
|
+
'Use crypto.randomBytes() or crypto.getRandomValues() for security-sensitive values.';
|
|
699
|
+
}
|
|
700
|
+
// Security-sensitive contexts get high severity
|
|
701
|
+
else if (context.inSecurityContext || functionIntent === 'security') {
|
|
702
|
+
severity = 'high';
|
|
703
|
+
confidence = 'high';
|
|
704
|
+
description =
|
|
705
|
+
'Math.random() is being used in a security-sensitive context. This is NOT cryptographically secure and should be replaced.';
|
|
706
|
+
suggestedFix =
|
|
707
|
+
'Use crypto.randomBytes() for Node.js or crypto.getRandomValues() for browsers.';
|
|
708
|
+
}
|
|
709
|
+
// Test contexts get info severity
|
|
710
|
+
else if (context.inTestContext) {
|
|
711
|
+
severity = 'info';
|
|
712
|
+
confidence = 'low';
|
|
713
|
+
description =
|
|
714
|
+
'Math.random() in test context. Acceptable for test data generation.';
|
|
715
|
+
suggestedFix = 'No change needed for test data.';
|
|
716
|
+
}
|
|
717
|
+
// UUID/CAPTCHA generation - legitimate use
|
|
718
|
+
else if (functionIntent === 'uuid' || functionIntent === 'captcha') {
|
|
719
|
+
severity = 'info';
|
|
720
|
+
confidence = 'low';
|
|
721
|
+
description = `Math.random() used for ${functionIntent === 'uuid' ? 'ID generation' : 'CAPTCHA/puzzle'} (not security-sensitive).`;
|
|
722
|
+
suggestedFix =
|
|
723
|
+
'For truly unique IDs, consider crypto.randomUUID(). For security tokens, use crypto.randomBytes().';
|
|
724
|
+
}
|
|
725
|
+
// Demo/seed data - legitimate use
|
|
726
|
+
else if (functionIntent === 'demo') {
|
|
727
|
+
severity = 'info';
|
|
728
|
+
confidence = 'low';
|
|
729
|
+
description =
|
|
730
|
+
'Math.random() for demo/seed data generation. Acceptable for non-production data.';
|
|
731
|
+
suggestedFix = 'No change needed for demo/seed data.';
|
|
732
|
+
}
|
|
733
|
+
// Short UI IDs (.toString(36).substring(2,9)) - info
|
|
734
|
+
else if (toStringPattern.intent === 'short-ui-id') {
|
|
735
|
+
severity = 'info';
|
|
736
|
+
confidence = 'low';
|
|
737
|
+
explanation = ` (${toStringPattern.truncationLength || '?'}-char string)`;
|
|
738
|
+
// Override context description for UI IDs
|
|
739
|
+
context.contextDescription = 'UI identifier generation';
|
|
740
|
+
description = `Math.random() generating short UI identifier${explanation}. Acceptable for React keys, temp IDs.`;
|
|
741
|
+
suggestedFix =
|
|
742
|
+
'For security tokens, use crypto.randomBytes(). For unique IDs, crypto.randomUUID().';
|
|
743
|
+
}
|
|
744
|
+
// Business IDs (.toString(36) with medium truncation) - low
|
|
745
|
+
else if (toStringPattern.intent === 'business-id') {
|
|
746
|
+
severity = 'low';
|
|
747
|
+
confidence = 'low';
|
|
748
|
+
explanation = variableName ? ` (variable: ${variableName})` : '';
|
|
749
|
+
description = `Math.random() generating business identifier${explanation}. Verify this is not used for security purposes.`;
|
|
750
|
+
suggestedFix =
|
|
751
|
+
'For business IDs, crypto.randomUUID() is preferred. For security tokens, use crypto.randomBytes().';
|
|
752
|
+
}
|
|
753
|
+
// Full token (.toString(36) without truncation) - severity based on variable name
|
|
754
|
+
else if (toStringPattern.intent === 'full-token') {
|
|
755
|
+
// Note: high-risk variable names are already handled above
|
|
756
|
+
if (variableRisk === 'low') {
|
|
757
|
+
severity = 'low';
|
|
758
|
+
confidence = 'low';
|
|
759
|
+
}
|
|
760
|
+
else {
|
|
761
|
+
severity = 'medium';
|
|
762
|
+
confidence = 'medium';
|
|
763
|
+
}
|
|
764
|
+
explanation = variableName ? ` (variable: ${variableName})` : '';
|
|
765
|
+
description = `Math.random() generating full-length random string${explanation}. This pattern is often used for security tokens.`;
|
|
766
|
+
suggestedFix =
|
|
767
|
+
'Use crypto.randomBytes() for security tokens. Use crypto.randomUUID() for unique IDs.';
|
|
768
|
+
}
|
|
769
|
+
// UI/cosmetic context - info (skeleton widths, animations, visual effects)
|
|
770
|
+
else if (context.inUIContext) {
|
|
771
|
+
severity = 'info';
|
|
772
|
+
confidence = 'low';
|
|
773
|
+
description =
|
|
774
|
+
'Math.random() in UI/cosmetic context. Acceptable for visual effects, skeleton loading, animations.';
|
|
775
|
+
suggestedFix = 'No change needed for UI/cosmetic randomness.';
|
|
776
|
+
}
|
|
777
|
+
// Business logic context - low
|
|
778
|
+
else if (context.inBusinessLogicContext) {
|
|
779
|
+
severity = 'low';
|
|
780
|
+
confidence = 'low';
|
|
781
|
+
description =
|
|
782
|
+
'Math.random() in business logic context (backoff, sampling, experiments). Verify this is not for security.';
|
|
783
|
+
suggestedFix =
|
|
784
|
+
'If used for security, replace with crypto.randomBytes(). Otherwise, usage is acceptable.';
|
|
785
|
+
}
|
|
786
|
+
// Unknown context - medium
|
|
787
|
+
else {
|
|
788
|
+
severity = 'medium';
|
|
789
|
+
confidence = 'medium';
|
|
790
|
+
description =
|
|
791
|
+
'Math.random() is being used. Verify this is not for security-critical purposes like tokens, session IDs, or cryptographic operations.';
|
|
792
|
+
suggestedFix =
|
|
793
|
+
'If used for security, replace with crypto.randomBytes(). For unique IDs, use crypto.randomUUID()';
|
|
794
|
+
}
|
|
795
|
+
// Update title with context
|
|
796
|
+
const title = `Math.random() in ${context.contextDescription}${explanation}`;
|
|
797
|
+
vulnerabilities.push({
|
|
798
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
799
|
+
filePath,
|
|
800
|
+
lineNumber: index + 1,
|
|
801
|
+
lineContent: line.trim(),
|
|
802
|
+
severity,
|
|
803
|
+
category: 'dangerous_function',
|
|
804
|
+
title,
|
|
805
|
+
description,
|
|
806
|
+
suggestedFix,
|
|
807
|
+
confidence,
|
|
808
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
809
|
+
layer: 2,
|
|
810
|
+
source: 'structural',
|
|
811
|
+
});
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* Extract the full Python function call block starting from the trigger line.
|
|
815
|
+
* Uses paren-balancing to collect up to `maxLines` forward, capturing multi-line calls.
|
|
816
|
+
* Returns the joined block string.
|
|
817
|
+
*/
|
|
818
|
+
function extractPythonCallBlock(lines, startIndex, maxLines = 10) {
|
|
819
|
+
let depth = 0;
|
|
820
|
+
let started = false;
|
|
821
|
+
const blockLines = [];
|
|
822
|
+
for (let i = startIndex; i < Math.min(lines.length, startIndex + maxLines); i++) {
|
|
823
|
+
const ln = lines[i];
|
|
824
|
+
blockLines.push(ln);
|
|
825
|
+
for (const ch of ln) {
|
|
826
|
+
if (ch === '(') {
|
|
827
|
+
depth++;
|
|
828
|
+
started = true;
|
|
829
|
+
}
|
|
830
|
+
else if (ch === ')') {
|
|
831
|
+
depth--;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
// Once we've opened at least one paren and balanced back to 0, we're done
|
|
835
|
+
if (started && depth <= 0)
|
|
836
|
+
break;
|
|
837
|
+
}
|
|
838
|
+
return blockLines.join('\n');
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Check if a Python list (as a string) contains only static string literals.
|
|
842
|
+
* Returns true if every element is a plain string literal (no f-strings, no variables).
|
|
843
|
+
*/
|
|
844
|
+
function isPythonListAllStatic(listContent) {
|
|
845
|
+
// Remove the outer brackets
|
|
846
|
+
const inner = listContent.replace(/^\[/, '').replace(/\]$/, '').trim();
|
|
847
|
+
if (!inner)
|
|
848
|
+
return true; // empty list
|
|
849
|
+
// Split on commas (rough — good enough for typical subprocess args)
|
|
850
|
+
const elements = inner.split(',').map(e => e.trim()).filter(e => e.length > 0);
|
|
851
|
+
for (const el of elements) {
|
|
852
|
+
// Must be a plain string literal: 'foo', "bar", or """...""" / '''...'''
|
|
853
|
+
// Reject f-strings, variables, function calls
|
|
854
|
+
if (/^f['"`]/.test(el))
|
|
855
|
+
return false; // f-string
|
|
856
|
+
if (/^['"]/.test(el) && /['"]$/.test(el))
|
|
857
|
+
continue; // simple string literal
|
|
858
|
+
if (/^"""/.test(el) || /^'''/.test(el))
|
|
859
|
+
continue; // triple-quoted
|
|
860
|
+
return false; // variable, function call, or other expression
|
|
861
|
+
}
|
|
862
|
+
return true;
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Handle Python subprocess/os.system patterns with multi-line awareness.
|
|
866
|
+
*
|
|
867
|
+
* Decision tree:
|
|
868
|
+
* 1. os.system(...) → HIGH (always dangerous)
|
|
869
|
+
* 2. shell=True in call block? → HIGH
|
|
870
|
+
* 3. First arg is inline list [...]?
|
|
871
|
+
* a. All string literals, no f-strings → SKIP (safe)
|
|
872
|
+
* b. Has f-strings or variables → LOW (list args prevent shell injection)
|
|
873
|
+
* 4. First arg is a variable name?
|
|
874
|
+
* a. Resolved to list nearby, all static → SKIP
|
|
875
|
+
* b. Resolved to list nearby, has dynamics → LOW
|
|
876
|
+
* c. Can't resolve → LOW (unresolved, flag for review)
|
|
877
|
+
* 5. f-string as direct arg (not in list)? → HIGH (command injection)
|
|
878
|
+
* 6. Everything else → HIGH (fallback)
|
|
879
|
+
*/
|
|
880
|
+
function handlePythonSubprocessPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines) {
|
|
881
|
+
// 1. os.system is always dangerous - no safe usage
|
|
882
|
+
if (/os\.system\s*\(/i.test(line)) {
|
|
883
|
+
handleStandardPattern(funcPattern, line, index, filePath, isTestFile, vulnerabilities);
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
const _lines = lines ?? content.split('\n');
|
|
887
|
+
// Extract the full multi-line call block (up to 10 lines forward)
|
|
888
|
+
const callBlock = extractPythonCallBlock(_lines, index);
|
|
889
|
+
// 2. Check for shell=True across the entire call block
|
|
890
|
+
const hasShellTrue = /shell\s*=\s*True/i.test(callBlock);
|
|
891
|
+
if (hasShellTrue) {
|
|
892
|
+
handleStandardPattern(funcPattern, line, index, filePath, isTestFile, vulnerabilities);
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
// 3. Check for inline list args in the call block (not just same line)
|
|
896
|
+
const inlineListMatch = callBlock.match(/subprocess\.(run|call|check_output|Popen)\s*\(\s*\[([\s\S]*?)\]/i);
|
|
897
|
+
if (inlineListMatch) {
|
|
898
|
+
const listContent = '[' + inlineListMatch[2] + ']';
|
|
899
|
+
if (isPythonListAllStatic(listContent)) {
|
|
900
|
+
// 3a. All static string literals → SKIP (safe)
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
// 3b. Has f-strings or variables → LOW (list args prevent shell injection)
|
|
904
|
+
vulnerabilities.push({
|
|
905
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
906
|
+
filePath,
|
|
907
|
+
lineNumber: index + 1,
|
|
908
|
+
lineContent: line.trim(),
|
|
909
|
+
severity: isTestFile ? 'info' : 'low',
|
|
910
|
+
category: 'dangerous_function',
|
|
911
|
+
title: funcPattern.name + ' (list args)',
|
|
912
|
+
description: 'subprocess with list arguments (safer than shell=True). Some arguments contain variables or f-strings — verify they are validated.',
|
|
913
|
+
suggestedFix: 'Ensure dynamic arguments are validated and sanitized.',
|
|
914
|
+
confidence: 'low',
|
|
915
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
916
|
+
layer: 2,
|
|
917
|
+
source: 'structural',
|
|
918
|
+
});
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
// 4. Check for variable reference as first arg
|
|
922
|
+
// Pattern: subprocess.run(args, ...) or subprocess.check_output(cmd, ...)
|
|
923
|
+
const varArgMatch = callBlock.match(/subprocess\.(run|call|check_output|Popen)\s*\(\s*([a-zA-Z_]\w*)\s*[,)]/i);
|
|
924
|
+
if (varArgMatch) {
|
|
925
|
+
const varName = varArgMatch[2];
|
|
926
|
+
// Look backwards up to 15 lines for assignment: varName = [...]
|
|
927
|
+
const searchStart = Math.max(0, index - 15);
|
|
928
|
+
const previousLines = _lines.slice(searchStart, index + 1).join('\n');
|
|
929
|
+
// Match varName = [...] assignment (possibly multi-line)
|
|
930
|
+
const assignmentPattern = new RegExp(varName + '\\s*=\\s*\\[([\\s\\S]*?)\\]', 'i');
|
|
931
|
+
const assignmentMatch = previousLines.match(assignmentPattern);
|
|
932
|
+
if (assignmentMatch) {
|
|
933
|
+
const listContent = '[' + assignmentMatch[1] + ']';
|
|
934
|
+
if (isPythonListAllStatic(listContent)) {
|
|
935
|
+
// 4a. Variable resolves to all-static list → SKIP
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
// 4b. Variable resolves to list with dynamic elements → LOW
|
|
939
|
+
vulnerabilities.push({
|
|
940
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
941
|
+
filePath,
|
|
942
|
+
lineNumber: index + 1,
|
|
943
|
+
lineContent: line.trim(),
|
|
944
|
+
severity: isTestFile ? 'info' : 'low',
|
|
945
|
+
category: 'dangerous_function',
|
|
946
|
+
title: funcPattern.name + ' (list args via variable)',
|
|
947
|
+
description: `subprocess called with variable '${varName}' which resolves to a list. List arguments prevent shell injection, but some elements are dynamic.`,
|
|
948
|
+
suggestedFix: 'Ensure dynamic list elements are validated and sanitized.',
|
|
949
|
+
confidence: 'low',
|
|
950
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
951
|
+
layer: 2,
|
|
952
|
+
source: 'structural',
|
|
953
|
+
});
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
// 4c. Can't resolve the variable — flag for review at LOW
|
|
957
|
+
vulnerabilities.push({
|
|
958
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
959
|
+
filePath,
|
|
960
|
+
lineNumber: index + 1,
|
|
961
|
+
lineContent: line.trim(),
|
|
962
|
+
severity: isTestFile ? 'info' : 'low',
|
|
963
|
+
category: 'dangerous_function',
|
|
964
|
+
title: funcPattern.name + ' (unresolved variable)',
|
|
965
|
+
description: `subprocess called with variable '${varName}' — could not resolve its value nearby. If it is a list, shell injection risk is low.`,
|
|
966
|
+
suggestedFix: 'Verify the variable is a list (not a string) and arguments are validated.',
|
|
967
|
+
confidence: 'low',
|
|
968
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
969
|
+
layer: 2,
|
|
970
|
+
source: 'structural',
|
|
971
|
+
});
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
// 5. f-string as direct arg (not inside a list) → HIGH (command injection)
|
|
975
|
+
const hasFStringDirectArg = /subprocess\.(run|call|check_output|Popen)\s*\(\s*f['"`]/i.test(callBlock);
|
|
976
|
+
if (hasFStringDirectArg) {
|
|
977
|
+
handleStandardPattern(funcPattern, line, index, filePath, isTestFile, vulnerabilities);
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
// 6. Everything else → HIGH (fallback)
|
|
981
|
+
handleStandardPattern(funcPattern, line, index, filePath, isTestFile, vulnerabilities);
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Handle regex patterns - check for escaped input
|
|
985
|
+
* Pattern: new RegExp(escapedInput) or new RegExp(input.replaceAll(...escaped...))
|
|
986
|
+
*/
|
|
987
|
+
function handleRegexPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines) {
|
|
988
|
+
const _lines = lines ?? content.split('\n');
|
|
989
|
+
const contextStart = Math.max(0, index - 15);
|
|
990
|
+
const contextEnd = Math.min(_lines.length, index + 3);
|
|
991
|
+
const context = _lines.slice(contextStart, contextEnd).join('\n');
|
|
992
|
+
// Check for RegExp object property access (.source, .flags)
|
|
993
|
+
// This indicates input is already a validated RegExp, not user string
|
|
994
|
+
// e.g., new RegExp(existingRegex.source, existingRegex.flags)
|
|
995
|
+
const isRegExpFromRegExp = /\.source\s*[,)\s]/.test(line);
|
|
996
|
+
if (isRegExpFromRegExp) {
|
|
997
|
+
return; // Safe - .source only exists on RegExp objects (already validated)
|
|
998
|
+
}
|
|
999
|
+
// Check for escaping ON THE SAME LINE as new RegExp() - this is a strong signal
|
|
1000
|
+
const sameLineEscapingPatterns = [
|
|
1001
|
+
/\.replaceAll\s*\([^)]*\)\s*[,)]/i, // .replaceAll(...)) - escaping before RegExp
|
|
1002
|
+
/escape\w*\s*\([^)]*\)\s*[,)]/i, // escapeRegExp(input)) - function result used
|
|
1003
|
+
/\.replace\s*\([^,]+,[^)]+\)\s*[,)]/i, // .replace(..., ...) followed by closing
|
|
1004
|
+
];
|
|
1005
|
+
if (sameLineEscapingPatterns.some(p => p.test(line))) {
|
|
1006
|
+
return; // Safe - escaping applied on same line before RegExp construction
|
|
1007
|
+
}
|
|
1008
|
+
// Check previous 5 lines for escaping assignment (extended from 3 to catch multi-line patterns)
|
|
1009
|
+
const prevLinesStart = Math.max(0, index - 5);
|
|
1010
|
+
const prevLines = _lines.slice(prevLinesStart, index + 1).join('\n');
|
|
1011
|
+
// Check for escaping patterns before new RegExp
|
|
1012
|
+
const escapingPatterns = [
|
|
1013
|
+
// Direct escaping function calls
|
|
1014
|
+
/escapeRegExp\s*\(/i, // escapeRegExp(input)
|
|
1015
|
+
/escapeString\s*\(/i, // escapeString(input)
|
|
1016
|
+
/escape\s*\(\s*pattern/i, // escape(pattern)
|
|
1017
|
+
/escapeForRegex\s*\(/i, // escapeForRegex(input)
|
|
1018
|
+
/regexEscape\s*\(/i, // regexEscape(input)
|
|
1019
|
+
// replaceAll with regex escape pattern - original strict patterns
|
|
1020
|
+
/\.replaceAll\s*\(\s*\/\[.*\\\\\]\s*\/[gi]*\s*,\s*['"`]\\\\?\$&['"`]\s*\)/, // .replaceAll(/[special]/g, '\\$&')
|
|
1021
|
+
/\.replace\s*\(\s*\/\[.*\\\\\]\s*\/[gi]*\s*,\s*['"`]\\\\?\$&['"`]\s*\)/, // .replace(/[special]/g, '\\$&')
|
|
1022
|
+
// More permissive $& replacement detection (the escape marker)
|
|
1023
|
+
// $& is the regex replacement marker that inserts the matched string - used for escaping
|
|
1024
|
+
/\.replace(?:All)?[\s\S]*?['"`]\\*\$&['"`]/, // .replace/.replaceAll with $& anywhere in call
|
|
1025
|
+
/\.replaceAll?[^;]*\$&/, // .replace/.replaceAll until semicolon with $&
|
|
1026
|
+
// Lodash/underscore escapeRegExp
|
|
1027
|
+
/_\.escapeRegExp\s*\(/, // _.escapeRegExp(input)
|
|
1028
|
+
/lodash.*escapeRegExp/i, // lodash.escapeRegExp
|
|
1029
|
+
// Variable assignment with escaping (check previous lines)
|
|
1030
|
+
/escaped\w*\s*=.*\.replace/i, // escapedInput = input.replace(...)
|
|
1031
|
+
/safe\w*\s*=.*escape/i, // safePattern = escapeRegExp(...)
|
|
1032
|
+
];
|
|
1033
|
+
// Check both previous lines and full context
|
|
1034
|
+
const hasEscaping = escapingPatterns.some(p => p.test(line) || p.test(prevLines) || p.test(context));
|
|
1035
|
+
// Check for try-catch wrapping (ReDoS contained)
|
|
1036
|
+
const hasTryCatch = /try\s*\{[^}]*new\s+RegExp/i.test(context) ||
|
|
1037
|
+
(context.includes('try {') && _lines.slice(Math.max(0, index - 5), index + 1).some(l => /try\s*\{/.test(l)));
|
|
1038
|
+
// Check for configuration-based patterns (trusted input)
|
|
1039
|
+
const isConfigBased = /config\./i.test(line) ||
|
|
1040
|
+
/settings\./i.test(line) ||
|
|
1041
|
+
/rules\./i.test(line) ||
|
|
1042
|
+
/options\.\w+Pattern/i.test(line) ||
|
|
1043
|
+
/urlPattern/i.test(line) ||
|
|
1044
|
+
/routePattern/i.test(line);
|
|
1045
|
+
// Escaped input is safe - skip entirely
|
|
1046
|
+
if (hasEscaping) {
|
|
1047
|
+
return;
|
|
1048
|
+
}
|
|
1049
|
+
// Config-based patterns are trusted - skip
|
|
1050
|
+
if (isConfigBased) {
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
// Check if regex source is an object property (app-controlled data, not user input)
|
|
1054
|
+
// Patterns: obj.pattern, item.regex, l.urlRegExp, entry.matchPattern
|
|
1055
|
+
const objectPropertySource = /new\s+RegExp\s*\(\s*\w+\.\w*(regex|pattern|regexp|match|rule|expression|filter)\w*/i.test(line);
|
|
1056
|
+
if (objectPropertySource) {
|
|
1057
|
+
vulnerabilities.push({
|
|
1058
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
1059
|
+
filePath,
|
|
1060
|
+
lineNumber: index + 1,
|
|
1061
|
+
lineContent: line.trim(),
|
|
1062
|
+
severity: 'info',
|
|
1063
|
+
category: 'dangerous_function',
|
|
1064
|
+
title: funcPattern.name + ' (app-controlled)',
|
|
1065
|
+
description: 'Dynamic regex from object property. If the regex source is app-defined (not user input), ReDoS risk is minimal.',
|
|
1066
|
+
suggestedFix: 'Ensure regex patterns come from trusted, validated sources.',
|
|
1067
|
+
confidence: 'low',
|
|
1068
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
1069
|
+
layer: 2,
|
|
1070
|
+
source: 'structural',
|
|
1071
|
+
});
|
|
1072
|
+
return;
|
|
1073
|
+
}
|
|
1074
|
+
// Check if regex source is from array iteration over app data
|
|
1075
|
+
// Pattern: for (const item of items) { new RegExp(item.xxx) }
|
|
1076
|
+
const isArrayIterationContext = /for\s*\(\s*(const|let|var)\s+\w+\s+(of|in)\s+/.test(context) &&
|
|
1077
|
+
/new\s+RegExp\s*\(\s*\w+\./.test(line);
|
|
1078
|
+
if (isArrayIterationContext) {
|
|
1079
|
+
vulnerabilities.push({
|
|
1080
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
1081
|
+
filePath,
|
|
1082
|
+
lineNumber: index + 1,
|
|
1083
|
+
lineContent: line.trim(),
|
|
1084
|
+
severity: 'info',
|
|
1085
|
+
category: 'dangerous_function',
|
|
1086
|
+
title: funcPattern.name + ' (iteration)',
|
|
1087
|
+
description: 'Dynamic regex in array iteration. If iterating over app-defined data, ReDoS risk is minimal.',
|
|
1088
|
+
suggestedFix: 'Ensure regex patterns come from trusted sources, not user input.',
|
|
1089
|
+
confidence: 'low',
|
|
1090
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
1091
|
+
layer: 2,
|
|
1092
|
+
source: 'structural',
|
|
1093
|
+
});
|
|
1094
|
+
return;
|
|
1095
|
+
}
|
|
1096
|
+
// Try-catch wrapped - lower severity (ReDoS contained)
|
|
1097
|
+
if (hasTryCatch) {
|
|
1098
|
+
vulnerabilities.push({
|
|
1099
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
1100
|
+
filePath,
|
|
1101
|
+
lineNumber: index + 1,
|
|
1102
|
+
lineContent: line.trim(),
|
|
1103
|
+
severity: 'info',
|
|
1104
|
+
category: 'dangerous_function',
|
|
1105
|
+
title: funcPattern.name + ' (try-catch wrapped)',
|
|
1106
|
+
description: 'Dynamic regex with try-catch error handling. ReDoS attacks are contained but may still cause performance issues.',
|
|
1107
|
+
suggestedFix: 'Consider using safe-regex library or adding timeout for regex operations.',
|
|
1108
|
+
confidence: 'low',
|
|
1109
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
1110
|
+
layer: 2,
|
|
1111
|
+
source: 'structural',
|
|
1112
|
+
});
|
|
1113
|
+
return;
|
|
1114
|
+
}
|
|
1115
|
+
// Standard handling for unprotected regex
|
|
1116
|
+
handleStandardPattern(funcPattern, line, index, filePath, isTestFile, vulnerabilities);
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Handle spread operator with user input patterns
|
|
1120
|
+
* Checks for schema validation (Fastify, Zod, tRPC) that strips unknown properties
|
|
1121
|
+
*/
|
|
1122
|
+
function handleSpreadPattern(funcPattern, line, content, index, filePath, isTestFile, vulnerabilities, lines) {
|
|
1123
|
+
const _lines = lines ?? content.split('\n');
|
|
1124
|
+
const contextStart = Math.max(0, index - 30);
|
|
1125
|
+
const contextEnd = index;
|
|
1126
|
+
const context = _lines.slice(contextStart, contextEnd).join('\n');
|
|
1127
|
+
// Fastify/Hapi schema validation on route - body is pre-validated
|
|
1128
|
+
// Pattern: schema: { body: someSchema } before handler
|
|
1129
|
+
const hasRouteSchemaValidation = /schema\s*:\s*\{[^}]*body\s*:\s*\w+/i.test(context) ||
|
|
1130
|
+
/body\s*:\s*\w+Schema/i.test(context);
|
|
1131
|
+
// Express + Zod/Joi/Yup middleware validation
|
|
1132
|
+
const hasMiddlewareValidation = /validate\s*\(\s*\w+Schema\s*\)/i.test(context) ||
|
|
1133
|
+
/\.parse\s*\(\s*req\.body\s*\)/i.test(context) ||
|
|
1134
|
+
/celebrate\s*\(/i.test(context);
|
|
1135
|
+
// tRPC input validation
|
|
1136
|
+
const hasTRPCValidation = /\.input\s*\(\s*z\./i.test(context) ||
|
|
1137
|
+
/\.input\s*\(\s*\w+Schema\s*\)/i.test(context);
|
|
1138
|
+
if (hasRouteSchemaValidation || hasMiddlewareValidation || hasTRPCValidation) {
|
|
1139
|
+
vulnerabilities.push({
|
|
1140
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
1141
|
+
filePath,
|
|
1142
|
+
lineNumber: index + 1,
|
|
1143
|
+
lineContent: line.trim(),
|
|
1144
|
+
severity: 'info',
|
|
1145
|
+
category: 'dangerous_function',
|
|
1146
|
+
title: funcPattern.name + ' (schema-validated)',
|
|
1147
|
+
description: 'Request body is spread but has schema validation. Schema validation strips unknown properties, reducing mass assignment risk.',
|
|
1148
|
+
suggestedFix: 'Ensure schema validation is strict (no .passthrough() in Zod, no additionalProperties in JSON Schema).',
|
|
1149
|
+
confidence: 'low',
|
|
1150
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
1151
|
+
layer: 2,
|
|
1152
|
+
source: 'structural',
|
|
1153
|
+
});
|
|
1154
|
+
return;
|
|
1155
|
+
}
|
|
1156
|
+
// No schema validation - standard handling
|
|
1157
|
+
handleStandardPattern(funcPattern, line, index, filePath, isTestFile, vulnerabilities);
|
|
1158
|
+
}
|
|
1159
|
+
/**
|
|
1160
|
+
* Handle standard patterns without special logic
|
|
1161
|
+
*/
|
|
1162
|
+
function handleStandardPattern(funcPattern, line, index, filePath, isTestFile, vulnerabilities) {
|
|
1163
|
+
let severity = funcPattern.severity;
|
|
1164
|
+
let confidence = 'high';
|
|
1165
|
+
if (isTestFile) {
|
|
1166
|
+
if (severity === 'critical') {
|
|
1167
|
+
severity = 'medium';
|
|
1168
|
+
}
|
|
1169
|
+
else if (severity === 'high') {
|
|
1170
|
+
severity = 'low';
|
|
1171
|
+
}
|
|
1172
|
+
else {
|
|
1173
|
+
severity = 'info';
|
|
1174
|
+
}
|
|
1175
|
+
confidence = 'low';
|
|
1176
|
+
}
|
|
1177
|
+
vulnerabilities.push({
|
|
1178
|
+
id: `dangerous-func-${filePath}-${index + 1}-${funcPattern.name}`,
|
|
1179
|
+
filePath,
|
|
1180
|
+
lineNumber: index + 1,
|
|
1181
|
+
lineContent: line.trim(),
|
|
1182
|
+
severity,
|
|
1183
|
+
category: 'dangerous_function',
|
|
1184
|
+
title: funcPattern.name,
|
|
1185
|
+
description: funcPattern.description + (isTestFile ? ' (in test file)' : ''),
|
|
1186
|
+
suggestedFix: funcPattern.suggestedFix,
|
|
1187
|
+
confidence,
|
|
1188
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
1189
|
+
layer: 2,
|
|
1190
|
+
source: 'structural',
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1193
|
+
//# sourceMappingURL=index.js.map
|