@oculum/scanner 1.0.12 → 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/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/index.d.ts +17 -64
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +49 -1034
- package/dist/index.js.map +1 -1
- package/dist/layer2/framework-checks.d.ts.map +1 -1
- package/dist/layer2/framework-checks.js +1 -8
- package/dist/layer2/framework-checks.js.map +1 -1
- package/dist/layer2/index.d.ts +4 -0
- package/dist/layer2/index.d.ts.map +1 -1
- package/dist/layer2/index.js +50 -1
- 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/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/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/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/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 +2 -2
- package/dist/tiers.d.ts.map +1 -1
- package/dist/tiers.js +10 -0
- package/dist/tiers.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- 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 +15 -0
- package/src/__tests__/benchmark/fixtures/layer2/log-injection.ts +147 -0
- package/src/__tests__/benchmark/fixtures/layer2/security-headers.ts +197 -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 +3 -3
- 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 +2 -2
- 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 +312 -4
- 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 +37 -49
- package/src/__tests__/snapshots/__snapshots__/dangerous-functions-refactor.test.ts.snap +52 -0
- package/src/__tests__/snapshots/__snapshots__/scan-depth.test.ts.snap +3 -3
- package/src/__tests__/snapshots/anthropic-validation-refactor.test.ts +2 -2
- 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/{layer2/ai-agent-tools.ts → detect/ai-code/agent-tools.ts} +23 -3
- package/src/{layer2 → detect/ai-code}/byok-patterns.ts +17 -5
- package/src/{layer2/ai-endpoint-protection.ts → detect/ai-code/endpoint-protection.ts} +8 -4
- package/src/{layer2/ai-execution-sinks.ts → detect/ai-code/execution-sinks.ts} +8 -4
- package/src/{layer2/ai-fingerprinting.ts → detect/ai-code/fingerprinting.ts} +20 -4
- package/src/detect/ai-code/index.ts +11 -0
- package/src/{layer2/ai-mcp-security.ts → detect/ai-code/mcp-security.ts} +7 -3
- package/src/{layer2 → detect/ai-code}/model-supply-chain.ts +7 -3
- package/src/{layer2/ai-package-hallucination.ts → detect/ai-code/package-hallucination.ts} +18 -3
- package/src/{layer2/ai-prompt-hygiene.ts → detect/ai-code/prompt-hygiene.ts} +25 -3
- package/src/{layer2/ai-rag-safety.ts → detect/ai-code/rag-safety.ts} +7 -3
- package/src/{layer2/ai-schema-validation.ts → detect/ai-code/schema-validation.ts} +7 -3
- package/src/detect/config/agent-skill-injection.ts +551 -0
- package/src/{layer1 → detect/config}/comments.ts +6 -2
- package/src/{layer1 → detect/config}/file-flags.ts +9 -3
- 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 +12 -5
- package/src/detect/index.ts +131 -0
- package/src/{layer1 → detect/secrets}/config-audit.ts +7 -2
- package/src/{layer1 → detect/secrets}/config-mcp-audit.ts +8 -3
- package/src/{layer1 → detect/secrets}/entropy.ts +23 -11
- package/src/{layer1 → detect/secrets}/index.ts +31 -30
- package/src/{layer1 → detect/secrets}/patterns.ts +10 -3
- package/src/{layer1 → detect/secrets}/weak-crypto.ts +7 -2
- package/src/{layer2/auth-antipatterns.ts → detect/structural/auth-patterns.ts} +23 -11
- package/src/{layer2 → detect/structural}/dangerous-functions/dom-xss.ts +1 -1
- package/src/{layer2 → detect/structural}/dangerous-functions/index.ts +47 -24
- package/src/{layer2 → detect/structural}/dangerous-functions/json-parse.ts +10 -2
- package/src/{layer2 → detect/structural}/dangerous-functions/math-random.ts +2 -2
- package/src/{layer2 → detect/structural}/dangerous-functions/patterns.ts +1 -1
- package/src/{layer2 → detect/structural}/dangerous-functions/request-validation.ts +10 -2
- package/src/{layer2 → detect/structural}/dangerous-functions/utils/control-flow.ts +2 -2
- package/src/{layer2 → detect/structural}/data-exposure.ts +11 -3
- package/src/{layer2 → detect/structural}/framework-checks.ts +10 -11
- package/src/{layer2 → detect/structural}/index.ts +80 -77
- package/src/detect/structural/log-injection.ts +254 -0
- package/src/{layer2 → detect/structural}/logic-gates.ts +13 -5
- package/src/{layer2 → detect/structural}/risky-imports.ts +7 -3
- 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 +7 -3
- package/src/detect/structural/xxe-detection.ts +295 -0
- package/src/index.ts +39 -1291
- 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/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} +54 -0
- 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 +5 -5
- package/src/postprocess/aggregation.ts +74 -0
- package/src/postprocess/contradictions.ts +128 -0
- package/src/postprocess/dedup.ts +62 -0
- package/src/{filtering → postprocess/filtering}/__tests__/pipeline.test.ts +1 -1
- package/src/{filtering → postprocess/filtering}/context-adjustments.ts +2 -2
- package/src/{filtering → postprocess/filtering}/pipeline.ts +2 -2
- 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/{formatters → report/formatters}/ai-context.ts +1 -1
- package/src/{formatters → report/formatters}/cli-terminal.ts +11 -11
- package/src/{formatters → report/formatters}/github-comment.ts +1 -1
- package/src/{formatters → report/formatters}/grouping.ts +8 -8
- package/src/{formatters → report/formatters}/ide/claude-code.ts +1 -1
- package/src/{formatters → report/formatters}/ide/cursor.ts +1 -1
- package/src/{formatters → report/formatters}/ide/windsurf.ts +1 -1
- 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 +15 -14
- package/src/score/confidence.ts +66 -0
- package/src/score/index.ts +316 -0
- package/src/score/types.ts +187 -0
- package/src/{baseline → shared/baseline}/__tests__/diff.test.ts +2 -2
- package/src/{baseline → shared/baseline}/diff.ts +1 -1
- package/src/{baseline → shared/baseline}/manager.ts +1 -1
- package/src/{category-filter.ts → shared/category-filter.ts} +1 -1
- package/src/{utils → shared}/code-analysis.ts +1 -1
- 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/{types.ts → shared/types.ts} +22 -5
- package/src/tiers.ts +18 -1
- 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/{layer2 → detect/structural}/dangerous-functions/utils/schema-validation.ts +0 -0
- /package/src/{utils → model}/route-hierarchy.ts +0 -0
- /package/src/{filtering → postprocess/filtering}/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/{formatters → report/formatters}/__tests__/ai-context.test.ts +0 -0
- /package/src/{formatters → report/formatters}/ide/__tests__/ide.test.ts +0 -0
- /package/src/{formatters → report/formatters}/ide/index.ts +0 -0
- /package/src/{formatters → report/formatters}/index.ts +0 -0
- /package/src/{utils → shared}/__tests__/code-analysis.test.ts +0 -0
- /package/src/{utils → shared}/__tests__/parsed-file.test.ts +0 -0
- /package/src/{ai-context → shared/ai-context}/__tests__/manager.test.ts +0 -0
- /package/src/{ai-context → shared/ai-context}/index.ts +0 -0
- /package/src/{ai-context → shared/ai-context}/manager.ts +0 -0
- /package/src/{baseline → shared/baseline}/__tests__/manager.test.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}/comment-analyzer.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}/environment-context.ts +0 -0
- /package/src/{utils → shared}/intent-detector.ts +0 -0
- /package/src/{utils → shared}/parsed-file.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/{utils → shared}/schema-semantics.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,913 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Layer 2: RAG Data Safety Detection
|
|
4
|
+
* Detects data exfiltration risks in Retrieval Augmented Generation systems
|
|
5
|
+
*
|
|
6
|
+
* Covers:
|
|
7
|
+
* - M5.1: RAG data exfiltration (cross-tenant retrieval, raw context exposure)
|
|
8
|
+
* - Unscoped vector store queries
|
|
9
|
+
* - Raw retrieved context in responses
|
|
10
|
+
* - Context logging risks
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.detectRAGSafetyIssues = detectRAGSafetyIssues;
|
|
14
|
+
exports.isRAGContextFile = isRAGContextFile;
|
|
15
|
+
const file_classifier_1 = require("../../parse/file-classifier");
|
|
16
|
+
const BASE_CONFIDENCE = 0.45;
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Context Detection
|
|
19
|
+
// ============================================================================
|
|
20
|
+
/**
|
|
21
|
+
* Check if file uses client-side fuzzy search libraries (not vector stores)
|
|
22
|
+
* These are safe local search implementations, not cross-tenant data access risks
|
|
23
|
+
*/
|
|
24
|
+
function isClientSideFuzzySearch(content) {
|
|
25
|
+
const fuzzySearchPatterns = [
|
|
26
|
+
// Fuse.js - client-side fuzzy search
|
|
27
|
+
/import.*from\s+['"]fuse\.js['"]/i,
|
|
28
|
+
/require\s*\(\s*['"]fuse\.js['"]\s*\)/i,
|
|
29
|
+
/new\s+Fuse\s*\(/i,
|
|
30
|
+
// Other client-side search libraries
|
|
31
|
+
/import.*from\s+['"]flexsearch['"]/i,
|
|
32
|
+
/import.*from\s+['"]lunr['"]/i,
|
|
33
|
+
/import.*from\s+['"]minisearch['"]/i,
|
|
34
|
+
/import.*from\s+['"]fuzzysort['"]/i,
|
|
35
|
+
/import.*from\s+['"]match-sorter['"]/i,
|
|
36
|
+
];
|
|
37
|
+
return fuzzySearchPatterns.some(p => p.test(content));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check if a line contains a generic query pattern that is NOT a vector store query
|
|
41
|
+
* These are common web framework patterns that should not be flagged as RAG issues
|
|
42
|
+
*/
|
|
43
|
+
function isGenericQueryPattern(lineContent) {
|
|
44
|
+
const genericQueryPatterns = [
|
|
45
|
+
// Express/Hono/Koa query params
|
|
46
|
+
/req\.query\s*\(/i,
|
|
47
|
+
/c\.req\.query\s*\(/i,
|
|
48
|
+
/ctx\.query\s*\(/i,
|
|
49
|
+
/request\.query\s*\(/i,
|
|
50
|
+
// URL search params
|
|
51
|
+
/searchParams\.get\s*\(/i,
|
|
52
|
+
/url\.searchParams/i,
|
|
53
|
+
/URLSearchParams/i,
|
|
54
|
+
// Query string parsing
|
|
55
|
+
/querystring\.parse/i,
|
|
56
|
+
/qs\.parse/i,
|
|
57
|
+
// Database query builders (not vector stores)
|
|
58
|
+
/\.query\s*\(\s*['"`]SELECT/i,
|
|
59
|
+
/\.query\s*\(\s*['"`]INSERT/i,
|
|
60
|
+
/\.query\s*\(\s*['"`]UPDATE/i,
|
|
61
|
+
/\.query\s*\(\s*['"`]DELETE/i,
|
|
62
|
+
// GraphQL queries
|
|
63
|
+
/graphql.*query/i,
|
|
64
|
+
/useQuery\s*\(/i,
|
|
65
|
+
/useLazyQuery\s*\(/i,
|
|
66
|
+
// tRPC/React Query
|
|
67
|
+
/trpc\.\w+\.\w+\.query/i,
|
|
68
|
+
/\.useQuery\s*\(/i,
|
|
69
|
+
// Prisma/Drizzle queries
|
|
70
|
+
/prisma\.\w+\.findMany/i,
|
|
71
|
+
/db\.query\./i,
|
|
72
|
+
// Generic method chaining that isn't vector search
|
|
73
|
+
/\.query\s*\(\s*\)/i, // Empty query call
|
|
74
|
+
];
|
|
75
|
+
return genericQueryPatterns.some(p => p.test(lineContent));
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Check if file has vector store imports (required for RAG detection)
|
|
79
|
+
*/
|
|
80
|
+
function hasVectorStoreImport(content) {
|
|
81
|
+
const vectorStoreImports = [
|
|
82
|
+
/from\s+['"]pinecone/i,
|
|
83
|
+
/from\s+['"]@pinecone-database/i,
|
|
84
|
+
/from\s+['"]weaviate/i,
|
|
85
|
+
/from\s+['"]chromadb/i,
|
|
86
|
+
/from\s+['"]@qdrant/i,
|
|
87
|
+
/from\s+['"]qdrant/i,
|
|
88
|
+
/from\s+['"]@langchain\/vectorstores/i,
|
|
89
|
+
/from\s+['"]langchain\/vectorstores/i,
|
|
90
|
+
/from\s+['"]faiss/i,
|
|
91
|
+
/from\s+['"]milvus/i,
|
|
92
|
+
/from\s+['"]@supabase.*vector/i,
|
|
93
|
+
/pgvector/i,
|
|
94
|
+
/VectorStore/i,
|
|
95
|
+
/Embeddings/i,
|
|
96
|
+
];
|
|
97
|
+
return vectorStoreImports.some(p => p.test(content));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check if a file is in a RAG/retrieval context based on path and content
|
|
101
|
+
*/
|
|
102
|
+
function isRAGContextFile(filePath, content) {
|
|
103
|
+
// Skip client-side fuzzy search libraries - these are NOT vector stores
|
|
104
|
+
if (isClientSideFuzzySearch(content)) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
// Must have vector store imports to be considered RAG context
|
|
108
|
+
if (!hasVectorStoreImport(content)) {
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
// File path indicators of RAG code
|
|
112
|
+
const ragPathPatterns = [
|
|
113
|
+
/\/(rag|retrieval|retriever|embedding|vector|knowledge)\//i,
|
|
114
|
+
/\/(search|index|indexer|embeddings?)\//i,
|
|
115
|
+
/(rag|retriever|embedding|vector|knowledge).*\.(ts|js|tsx|jsx|py)$/i,
|
|
116
|
+
/(search|retrieval|indexer).*\.(ts|js|tsx|jsx|py)$/i,
|
|
117
|
+
];
|
|
118
|
+
if (ragPathPatterns.some(p => p.test(filePath))) {
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
// Content patterns suggesting RAG usage - must be actual vector store clients
|
|
122
|
+
const ragContentPatterns = [
|
|
123
|
+
// Vector store patterns - specific to actual vector DBs
|
|
124
|
+
/VectorStore|Embeddings?|Retriever/i,
|
|
125
|
+
/similaritySearch|query_engine|retriever/i,
|
|
126
|
+
/vectorStore|embeddingModel|documentLoader/i,
|
|
127
|
+
// Framework imports - actual vector store SDKs
|
|
128
|
+
/from\s+['"](?:langchain|llama[-_]?index|@pinecone|@qdrant|chromadb|weaviate)/i,
|
|
129
|
+
/import.*(?:Pinecone|Chroma|Weaviate|Qdrant|Milvus|PGVector)/i,
|
|
130
|
+
// Vercel AI SDK RAG
|
|
131
|
+
/VercelKVVectorStore|SupabaseVectorStore|createEmbedding/i,
|
|
132
|
+
// Query patterns - but NOT generic .search() which could be Fuse.js
|
|
133
|
+
/\.retrieve\(|\.query\(/i,
|
|
134
|
+
/sourceDocuments|retrievedDocs|retrievedChunks/i,
|
|
135
|
+
// Supabase vector search
|
|
136
|
+
/\.rpc\s*\(\s*['"`]match_documents/i,
|
|
137
|
+
/pgvector|embedding.*vector/i,
|
|
138
|
+
];
|
|
139
|
+
return ragContentPatterns.some(p => p.test(content));
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Check if line/context has access control scoping
|
|
143
|
+
*/
|
|
144
|
+
function hasAccessControlScoping(context) {
|
|
145
|
+
const accessPatterns = [
|
|
146
|
+
// User/tenant scoping
|
|
147
|
+
/userId|user_id|user\.id|currentUser/i,
|
|
148
|
+
/tenantId|tenant_id|tenant\.id|orgId|org_id|workspaceId/i,
|
|
149
|
+
// Filter parameters
|
|
150
|
+
/filter\s*[:=]\s*\{[^}]*(?:user|tenant|org)/i,
|
|
151
|
+
/where\s*[:=].*(?:user|tenant|org)/i,
|
|
152
|
+
/metadata\s*[:=].*(?:user|tenant|org)/i,
|
|
153
|
+
/namespace\s*[:=]/i,
|
|
154
|
+
// Access check functions
|
|
155
|
+
/checkAccess|verifyPermission|canRead|canAccess|hasAccess/i,
|
|
156
|
+
/getAuthorized|filterByUser|filterByTenant/i,
|
|
157
|
+
];
|
|
158
|
+
return accessPatterns.some(p => p.test(context));
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Check if response is filtered/processed before return
|
|
162
|
+
*/
|
|
163
|
+
function hasResponseFiltering(context) {
|
|
164
|
+
const filterPatterns = [
|
|
165
|
+
// Content filtering
|
|
166
|
+
/\.map\s*\([^)]*\.(title|name|id|metadata)\)/i,
|
|
167
|
+
/\.filter\s*\(/i,
|
|
168
|
+
/sanitize|redact|mask|strip/i,
|
|
169
|
+
// Only returning specific fields
|
|
170
|
+
/return\s*\{[^}]*(?:id|title|summary)[^}]*\}(?![^}]*content)/i,
|
|
171
|
+
];
|
|
172
|
+
return filterPatterns.some(p => p.test(context));
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Check if there's authentication in the route/function
|
|
176
|
+
*/
|
|
177
|
+
function hasAuthenticationInContext(content) {
|
|
178
|
+
const authPatterns = [
|
|
179
|
+
/getSession|getCurrentUser|getServerSession/i,
|
|
180
|
+
/auth\(\)|requireAuth|verifyToken/i,
|
|
181
|
+
/req\.user|request\.user|context\.user/i,
|
|
182
|
+
/isAuthenticated|checkAuth|withAuth/i,
|
|
183
|
+
/Authorization.*Bearer/i,
|
|
184
|
+
/userId|user\.id|currentUserId/i,
|
|
185
|
+
];
|
|
186
|
+
return authPatterns.some(p => p.test(content));
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Get surrounding context lines
|
|
190
|
+
*/
|
|
191
|
+
function getSurroundingContext(content, lineIndex, windowSize = 25) {
|
|
192
|
+
const lines = content.split('\n');
|
|
193
|
+
const start = Math.max(0, lineIndex - windowSize);
|
|
194
|
+
const end = Math.min(lines.length, lineIndex + windowSize);
|
|
195
|
+
return lines.slice(start, end).join('\n');
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Unscoped retrieval query patterns
|
|
199
|
+
* Detects vector store queries without user/tenant filtering
|
|
200
|
+
*/
|
|
201
|
+
const UNSCOPED_RETRIEVAL_PATTERNS = [
|
|
202
|
+
// Generic vector store queries
|
|
203
|
+
{
|
|
204
|
+
name: 'Unscoped vector store query',
|
|
205
|
+
pattern: /\.(?:query|search|similaritySearch|retrieve)\s*\(\s*(?:["'`][^"'`]+["'`]|[a-zA-Z_]\w*)\s*\)/gi,
|
|
206
|
+
riskType: 'unscoped_retrieval',
|
|
207
|
+
baseSeverity: 'high',
|
|
208
|
+
description: 'Vector store query without user/tenant scoping. Retrieved documents may belong to other users, enabling cross-tenant data access.',
|
|
209
|
+
suggestedFix: 'Add filter/metadata parameter to scope queries: .query(query, { filter: { userId: currentUser.id } })',
|
|
210
|
+
},
|
|
211
|
+
// LangChain retriever invoke
|
|
212
|
+
{
|
|
213
|
+
name: 'LangChain retriever without filter',
|
|
214
|
+
pattern: /retriever\.(?:invoke|getRelevantDocuments)\s*\(\s*(?:["'`][^"'`]+["'`]|[a-zA-Z_]\w*)\s*\)/gi,
|
|
215
|
+
riskType: 'unscoped_retrieval',
|
|
216
|
+
baseSeverity: 'high',
|
|
217
|
+
description: 'LangChain retriever invocation without metadata filter. Documents from all users may be retrieved.',
|
|
218
|
+
suggestedFix: 'Use a filtered retriever or add metadata filter: retriever.invoke(query, { filter: { userId } })',
|
|
219
|
+
},
|
|
220
|
+
// LlamaIndex query engine
|
|
221
|
+
{
|
|
222
|
+
name: 'LlamaIndex query engine without filter',
|
|
223
|
+
pattern: /query_engine\.query\s*\(\s*["'`][^"'`]+["'`]\s*\)/gi,
|
|
224
|
+
riskType: 'unscoped_retrieval',
|
|
225
|
+
baseSeverity: 'high',
|
|
226
|
+
description: 'LlamaIndex query without node postprocessors or filters. All indexed documents are searchable.',
|
|
227
|
+
suggestedFix: 'Add node_postprocessors to filter by user/tenant metadata before retrieval.',
|
|
228
|
+
},
|
|
229
|
+
// Pinecone query
|
|
230
|
+
{
|
|
231
|
+
name: 'Pinecone query without metadata filter',
|
|
232
|
+
pattern: /\.query\s*\(\s*\{[^}]*(?:vector|topK)[^}]*\}\s*\)/gi,
|
|
233
|
+
riskType: 'unscoped_retrieval',
|
|
234
|
+
baseSeverity: 'medium',
|
|
235
|
+
description: 'Pinecone query may lack metadata filtering. Verify namespace or filter is set.',
|
|
236
|
+
suggestedFix: 'Add filter parameter: .query({ vector, topK, filter: { userId: { $eq: currentUserId } } })',
|
|
237
|
+
},
|
|
238
|
+
// Chroma query
|
|
239
|
+
{
|
|
240
|
+
name: 'Chroma collection query',
|
|
241
|
+
pattern: /collection\.query\s*\(\s*\{[^}]*query_texts[^}]*\}\s*\)/gi,
|
|
242
|
+
riskType: 'unscoped_retrieval',
|
|
243
|
+
baseSeverity: 'medium',
|
|
244
|
+
description: 'ChromaDB query without where filter. All documents in collection are searchable.',
|
|
245
|
+
suggestedFix: 'Add where parameter: collection.query({ query_texts, where: { userId: currentUserId } })',
|
|
246
|
+
},
|
|
247
|
+
// Weaviate search
|
|
248
|
+
{
|
|
249
|
+
name: 'Weaviate search without filter',
|
|
250
|
+
pattern: /\.nearText\s*\([^)]+\)\.(?:do|withLimit)/gi,
|
|
251
|
+
riskType: 'unscoped_retrieval',
|
|
252
|
+
baseSeverity: 'medium',
|
|
253
|
+
description: 'Weaviate nearText search without where filter. Results may include other users\' data.',
|
|
254
|
+
suggestedFix: 'Add .withWhere() to filter by user: .nearText({...}).withWhere({ path: ["userId"], operator: "Equal", valueString: userId })',
|
|
255
|
+
},
|
|
256
|
+
// Supabase vector search
|
|
257
|
+
{
|
|
258
|
+
name: 'Supabase vector search without RLS',
|
|
259
|
+
pattern: /\.rpc\s*\(\s*['"`]match_documents['"`]/gi,
|
|
260
|
+
riskType: 'unscoped_retrieval',
|
|
261
|
+
baseSeverity: 'medium',
|
|
262
|
+
description: 'Supabase vector search function called. Ensure RLS policies filter by user.',
|
|
263
|
+
suggestedFix: 'Verify Row Level Security (RLS) is enabled and filters documents by authenticated user.',
|
|
264
|
+
},
|
|
265
|
+
];
|
|
266
|
+
/**
|
|
267
|
+
* Raw context exposure patterns
|
|
268
|
+
* Detects retrieved documents being returned directly to clients
|
|
269
|
+
*/
|
|
270
|
+
const CONTEXT_EXPOSURE_PATTERNS = [
|
|
271
|
+
// Returning sourceDocuments in response
|
|
272
|
+
{
|
|
273
|
+
name: 'Source documents in API response',
|
|
274
|
+
pattern: /(?:res\.json|NextResponse\.json|return)\s*\([^)]*(?:sourceDocuments|retrievedDocs|documents|chunks)/gi,
|
|
275
|
+
riskType: 'context_exposure',
|
|
276
|
+
baseSeverity: 'medium',
|
|
277
|
+
description: 'Raw retrieved documents returned in API response. Source content may leak sensitive information from the knowledge base.',
|
|
278
|
+
suggestedFix: 'Return only synthesized response or document IDs/titles. If source attribution needed, filter to metadata only.',
|
|
279
|
+
},
|
|
280
|
+
// Spreading documents into response
|
|
281
|
+
{
|
|
282
|
+
name: 'Retrieved context spread in response',
|
|
283
|
+
pattern: /(?:res\.json|return)\s*\(\s*\{[^}]*\.\.\.(?:docs|documents|chunks|sourceDocuments|context)/gi,
|
|
284
|
+
riskType: 'context_exposure',
|
|
285
|
+
baseSeverity: 'medium',
|
|
286
|
+
description: 'Retrieved document objects spread into response. Full document content may be exposed.',
|
|
287
|
+
suggestedFix: 'Extract and return only safe fields: { sources: docs.map(d => ({ id: d.id, title: d.title })) }',
|
|
288
|
+
},
|
|
289
|
+
// Returning raw context in response object
|
|
290
|
+
{
|
|
291
|
+
name: 'Raw retrieval context in response',
|
|
292
|
+
pattern: /return\s*\{[^}]*(?:context|retrievedContext|ragContext)\s*:/gi,
|
|
293
|
+
riskType: 'context_exposure',
|
|
294
|
+
baseSeverity: 'low',
|
|
295
|
+
description: 'Retrieved context included in response object. Review what data is actually exposed.',
|
|
296
|
+
suggestedFix: 'Ensure context field contains only safe, summarized content - not raw document text.',
|
|
297
|
+
},
|
|
298
|
+
// WebSocket/stream context exposure
|
|
299
|
+
{
|
|
300
|
+
name: 'Context in streaming response',
|
|
301
|
+
pattern: /(?:socket|ws|stream)\.(?:send|emit|write)\s*\([^)]*(?:sourceDocuments|context|chunks)/gi,
|
|
302
|
+
riskType: 'context_exposure',
|
|
303
|
+
baseSeverity: 'medium',
|
|
304
|
+
description: 'Retrieved context sent via streaming/WebSocket. Clients receive raw source data.',
|
|
305
|
+
suggestedFix: 'Stream only AI-generated text. Send source attribution separately with filtered metadata.',
|
|
306
|
+
},
|
|
307
|
+
];
|
|
308
|
+
/**
|
|
309
|
+
* Context logging patterns
|
|
310
|
+
* Detects logging of retrieved documents or prompts with context
|
|
311
|
+
*/
|
|
312
|
+
const CONTEXT_LOGGING_PATTERNS = [
|
|
313
|
+
// Logging retrieved documents
|
|
314
|
+
{
|
|
315
|
+
name: 'Retrieved documents logged',
|
|
316
|
+
pattern: /(?:console|logger)\.\w+\s*\([^)]*(?:retrievedDocs|sourceDocuments|documents|chunks)/gi,
|
|
317
|
+
riskType: 'context_logging',
|
|
318
|
+
baseSeverity: 'info',
|
|
319
|
+
description: 'Retrieved documents logged. If logs are accessible, sensitive document content may be exposed.',
|
|
320
|
+
suggestedFix: 'Log document IDs/titles only: console.log("Retrieved:", docs.map(d => d.id))',
|
|
321
|
+
},
|
|
322
|
+
// Logging full prompt with context
|
|
323
|
+
{
|
|
324
|
+
name: 'Full prompt with context logged',
|
|
325
|
+
pattern: /(?:console|logger)\.\w+\s*\([^)]*(?:fullPrompt|promptWithContext|augmentedPrompt)/gi,
|
|
326
|
+
riskType: 'context_logging',
|
|
327
|
+
baseSeverity: 'low',
|
|
328
|
+
description: 'Full prompt (including retrieved context) logged. May expose sensitive document content in logs.',
|
|
329
|
+
suggestedFix: 'Log prompt length/metadata only. Avoid logging full prompt content in production.',
|
|
330
|
+
},
|
|
331
|
+
// Debug logging of RAG context
|
|
332
|
+
{
|
|
333
|
+
name: 'RAG context debug logging',
|
|
334
|
+
pattern: /(?:console\.(?:debug|log)|logger\.debug)\s*\([^)]*(?:context|ragContext|retrievalContext)/gi,
|
|
335
|
+
riskType: 'context_logging',
|
|
336
|
+
baseSeverity: 'info',
|
|
337
|
+
description: 'RAG context logged for debugging. Ensure debug logging is disabled in production.',
|
|
338
|
+
suggestedFix: 'Use conditional logging: if (process.env.NODE_ENV !== "production") console.debug(...)',
|
|
339
|
+
},
|
|
340
|
+
// Storing prompts with context
|
|
341
|
+
{
|
|
342
|
+
name: 'Prompt with context persisted',
|
|
343
|
+
pattern: /(?:\.create|\.insert|\.save)\s*\([^)]*(?:fullPrompt|promptWithContext|augmentedPrompt)/gi,
|
|
344
|
+
riskType: 'context_logging',
|
|
345
|
+
baseSeverity: 'medium',
|
|
346
|
+
description: 'Full prompt with retrieved context being persisted. May store sensitive document content.',
|
|
347
|
+
suggestedFix: 'Store user query and response separately. Do not persist raw retrieved context.',
|
|
348
|
+
},
|
|
349
|
+
];
|
|
350
|
+
// ============================================================================
|
|
351
|
+
// AI Detection Roadmap Phase 1: Enhanced RAG Detection
|
|
352
|
+
// ============================================================================
|
|
353
|
+
/**
|
|
354
|
+
* Corpus Poisoning Patterns
|
|
355
|
+
* Detects user uploads directly embedded without sanitization
|
|
356
|
+
*/
|
|
357
|
+
const CORPUS_POISONING_PATTERNS = [
|
|
358
|
+
// User content embedded directly
|
|
359
|
+
{
|
|
360
|
+
name: 'User content embedded directly',
|
|
361
|
+
pattern: /(?:embeddings?\.create|createEmbedding|embed)\s*\([^)]*(?:document\.content|user\.content|req\.body|req\.json|upload|file\.content)/gi,
|
|
362
|
+
riskType: 'corpus_poisoning',
|
|
363
|
+
baseSeverity: 'high',
|
|
364
|
+
description: 'User-provided content embedded directly without sanitization. Malicious instructions in uploads could poison the RAG corpus.',
|
|
365
|
+
suggestedFix: 'Sanitize user content before embedding: const sanitized = sanitizeForRAG(content); await embed(sanitized)',
|
|
366
|
+
},
|
|
367
|
+
// External content fetched and embedded
|
|
368
|
+
{
|
|
369
|
+
name: 'External content embedded without validation',
|
|
370
|
+
pattern: /(?:fetch|axios\.get|httpx\.get)\s*\([^)]+\)[^;]*(?:embed|addDocument|upsert|index)/gi,
|
|
371
|
+
riskType: 'corpus_poisoning',
|
|
372
|
+
baseSeverity: 'high',
|
|
373
|
+
description: 'External content fetched and embedded without validation. External sources could contain prompt injection payloads.',
|
|
374
|
+
suggestedFix: 'Validate and sanitize external content before embedding. Check source trustworthiness.',
|
|
375
|
+
},
|
|
376
|
+
// PDF/file content indexed without scanning
|
|
377
|
+
{
|
|
378
|
+
name: 'File content indexed without sanitization',
|
|
379
|
+
pattern: /(?:pdfParser|parse|readFile)[^;]*(?:addToCorpus|embedDocument|vectorStore\.add|index\.upsert)/gi,
|
|
380
|
+
riskType: 'corpus_poisoning',
|
|
381
|
+
baseSeverity: 'medium',
|
|
382
|
+
description: 'File content indexed without sanitization. PDFs and documents may contain hidden injection instructions.',
|
|
383
|
+
suggestedFix: 'Scan file content for injection patterns before indexing. Consider content classification.',
|
|
384
|
+
},
|
|
385
|
+
// User messages embedded
|
|
386
|
+
{
|
|
387
|
+
name: 'User messages embedded to corpus',
|
|
388
|
+
pattern: /(?:messages?|msg|chat)[^;]*(?:embedDocument|addToCorpus|vectorStore\.add)/gi,
|
|
389
|
+
riskType: 'corpus_poisoning',
|
|
390
|
+
baseSeverity: 'medium',
|
|
391
|
+
description: 'User messages being embedded into corpus. Messages could contain crafted injection payloads.',
|
|
392
|
+
suggestedFix: 'Filter user messages for instruction-like patterns. Use separate namespace for user content.',
|
|
393
|
+
},
|
|
394
|
+
// Direct upsert without sanitization
|
|
395
|
+
{
|
|
396
|
+
name: 'Direct vector upsert with user data',
|
|
397
|
+
pattern: /\.upsert\s*\(\s*\[\s*\{[^}]*content\s*:\s*(?:document|user|upload|req)/gi,
|
|
398
|
+
riskType: 'corpus_poisoning',
|
|
399
|
+
baseSeverity: 'high',
|
|
400
|
+
description: 'User data upserted directly to vector store. Content should be sanitized first.',
|
|
401
|
+
suggestedFix: 'Sanitize content before upserting: { content: sanitize(document.content), ... }',
|
|
402
|
+
},
|
|
403
|
+
];
|
|
404
|
+
/**
|
|
405
|
+
* PII Leakage Patterns
|
|
406
|
+
* Detects PII fields in embedded documents or retrieval responses
|
|
407
|
+
*/
|
|
408
|
+
const PII_LEAKAGE_PATTERNS = [
|
|
409
|
+
// PII fields in metadata
|
|
410
|
+
{
|
|
411
|
+
name: 'PII in document metadata',
|
|
412
|
+
pattern: /metadata\s*:\s*\{[^}]*(?:email|ssn|phone(?:Number)?|fullName|dateOfBirth|dob|address|socialSecurity)/gi,
|
|
413
|
+
riskType: 'pii_leakage',
|
|
414
|
+
baseSeverity: 'high',
|
|
415
|
+
description: 'PII fields stored in document metadata. This data will be exposed when documents are retrieved.',
|
|
416
|
+
suggestedFix: 'Remove PII from metadata. Store only non-sensitive identifiers: { userId: user.id, category: doc.type }',
|
|
417
|
+
},
|
|
418
|
+
// SSN/financial data in embedded docs
|
|
419
|
+
{
|
|
420
|
+
name: 'Sensitive financial/identity data embedded',
|
|
421
|
+
pattern: /(?:metadata|doc|document)\s*[:{][^}]*(?:ssn|socialSecurity|cardNumber|cvv|accountNum|insuranceId)/gi,
|
|
422
|
+
riskType: 'pii_leakage',
|
|
423
|
+
baseSeverity: 'critical',
|
|
424
|
+
description: 'Highly sensitive data (SSN, financial) in embedded documents. This is a compliance violation.',
|
|
425
|
+
suggestedFix: 'Never embed SSN, card numbers, or financial account data. Use tokenized references instead.',
|
|
426
|
+
},
|
|
427
|
+
// Patient/medical data in embeddings
|
|
428
|
+
{
|
|
429
|
+
name: 'PHI in embedded documents',
|
|
430
|
+
pattern: /(?:embed|metadata|doc)[^;]*(?:patientName|patientDob|patientSsn|medicalRecord|diagnosis)/gi,
|
|
431
|
+
riskType: 'pii_leakage',
|
|
432
|
+
baseSeverity: 'critical',
|
|
433
|
+
description: 'Protected Health Information (PHI) in embedded documents. HIPAA compliance violation.',
|
|
434
|
+
suggestedFix: 'Remove PHI before embedding. Use de-identification and tokenization for medical data.',
|
|
435
|
+
},
|
|
436
|
+
// Returning PII in search results
|
|
437
|
+
{
|
|
438
|
+
name: 'PII in retrieval response',
|
|
439
|
+
pattern: /return\s*(?:results\.map|docs\.map)[^}]*(?:email|phone|ssn|fullName|address)/gi,
|
|
440
|
+
riskType: 'pii_leakage',
|
|
441
|
+
baseSeverity: 'high',
|
|
442
|
+
description: 'PII fields returned in retrieval response. User PII may be exposed to unauthorized queries.',
|
|
443
|
+
suggestedFix: 'Filter PII from responses: return docs.map(d => ({ id: d.id, content: d.content })) // no PII',
|
|
444
|
+
},
|
|
445
|
+
// Direct metadata exposure with PII
|
|
446
|
+
{
|
|
447
|
+
name: 'Metadata with PII exposed in response',
|
|
448
|
+
pattern: /return\s*\{[^}]*metadata\.[^}]*(?:email|phone|ssn|name|address)/gi,
|
|
449
|
+
riskType: 'pii_leakage',
|
|
450
|
+
baseSeverity: 'high',
|
|
451
|
+
description: 'Document metadata containing PII exposed in response.',
|
|
452
|
+
suggestedFix: 'Filter metadata before returning. Only include non-sensitive fields.',
|
|
453
|
+
},
|
|
454
|
+
];
|
|
455
|
+
// ============================================================================
|
|
456
|
+
// Phase 1 Enhancement Backlog: Advanced RAG Attack Detection
|
|
457
|
+
// ============================================================================
|
|
458
|
+
/**
|
|
459
|
+
* Query Injection Patterns
|
|
460
|
+
* Detects user queries used in retrieval without sanitization
|
|
461
|
+
*/
|
|
462
|
+
const QUERY_INJECTION_PATTERNS = [
|
|
463
|
+
// User input directly in vector store query
|
|
464
|
+
{
|
|
465
|
+
name: 'User input directly in retrieval query',
|
|
466
|
+
pattern: /(?:vectorStore|retriever|index|collection)\.(?:query|invoke|search|similaritySearch)\s*\(\s*(?:req\.|user\.|input\.|body\.|params\.)/gi,
|
|
467
|
+
riskType: 'query_injection',
|
|
468
|
+
baseSeverity: 'high',
|
|
469
|
+
description: 'User input flows directly to vector store query without sanitization. Could manipulate retrieval results.',
|
|
470
|
+
suggestedFix: 'Validate and sanitize user queries: const sanitizedQuery = sanitizeQuery(userInput)',
|
|
471
|
+
},
|
|
472
|
+
// Query from request body without validation
|
|
473
|
+
{
|
|
474
|
+
name: 'Query from request body without validation',
|
|
475
|
+
pattern: /(?:const|let|var)\s*\{\s*query\s*\}.*(?:req\.body|req\.json|request\.body)[\s\S]{0,100}(?:search|query|retrieve|similaritySearch)/gi,
|
|
476
|
+
riskType: 'query_injection',
|
|
477
|
+
baseSeverity: 'medium',
|
|
478
|
+
description: 'Query destructured from request body and used in retrieval. Validate before use.',
|
|
479
|
+
suggestedFix: 'Add input validation: const { query } = validateSchema(req.body, querySchema)',
|
|
480
|
+
},
|
|
481
|
+
// Query template with user input interpolation
|
|
482
|
+
{
|
|
483
|
+
name: 'Query template with user input',
|
|
484
|
+
pattern: /(?:prompt|query|searchQuery)\s*=\s*[`'"].*\$\{.*(?:user|input|query|req).*\}.*[`'"]/gi,
|
|
485
|
+
riskType: 'query_injection',
|
|
486
|
+
baseSeverity: 'medium',
|
|
487
|
+
description: 'Query template interpolates user input. Could inject adversarial retrieval instructions.',
|
|
488
|
+
suggestedFix: 'Use parameterized queries or sanitize user input before interpolation.',
|
|
489
|
+
},
|
|
490
|
+
// Direct query passthrough in API
|
|
491
|
+
{
|
|
492
|
+
name: 'Query passthrough to vector store',
|
|
493
|
+
pattern: /app\.(?:post|get)\s*\([^)]+(?:search|query|retrieve)[^)]*\)[^{]*\{[^}]*(?:vectorStore|retriever)\.(?:query|search)\s*\(\s*(?:req|ctx)\.(?:body|query)/gi,
|
|
494
|
+
riskType: 'query_injection',
|
|
495
|
+
baseSeverity: 'high',
|
|
496
|
+
description: 'API endpoint passes request directly to vector store. No validation layer.',
|
|
497
|
+
suggestedFix: 'Add validation middleware. Sanitize and validate queries before retrieval.',
|
|
498
|
+
},
|
|
499
|
+
// No query length validation
|
|
500
|
+
{
|
|
501
|
+
name: 'Query without length validation',
|
|
502
|
+
pattern: /(?:query|search|retrieve)\s*\(\s*(?:userQuery|searchQuery|q)\s*\)(?![\s\S]{0,50}(?:\.length|\.trim\(\)|maxLength|minLength))/gi,
|
|
503
|
+
riskType: 'query_injection',
|
|
504
|
+
baseSeverity: 'low',
|
|
505
|
+
description: 'Query used without visible length validation. Consider adding bounds.',
|
|
506
|
+
suggestedFix: 'Add query length validation: if (query.length > MAX_QUERY_LENGTH) throw new Error("Query too long")',
|
|
507
|
+
},
|
|
508
|
+
];
|
|
509
|
+
/**
|
|
510
|
+
* Embedding Poisoning Patterns
|
|
511
|
+
* Detects adversarial document embedding vulnerabilities
|
|
512
|
+
*/
|
|
513
|
+
const EMBEDDING_POISONING_PATTERNS = [
|
|
514
|
+
// User document embedded without validation
|
|
515
|
+
{
|
|
516
|
+
name: 'User document embedded without validation',
|
|
517
|
+
pattern: /(?:embed|embeddings?\.(?:create|embed|generate)|createEmbedding)[\s\S]{0,50}(?:user|req\.|upload|file)[\s\S]{0,80}(?:vectorStore|index)\.(?:add|upsert|insert)/gis,
|
|
518
|
+
riskType: 'embedding_poisoning',
|
|
519
|
+
baseSeverity: 'high',
|
|
520
|
+
description: 'User-provided documents embedded directly. Adversarial content could poison retrieval.',
|
|
521
|
+
suggestedFix: 'Validate and sanitize user documents before embedding. Implement content classification.',
|
|
522
|
+
},
|
|
523
|
+
// Retrieval without similarity threshold
|
|
524
|
+
{
|
|
525
|
+
name: 'Retrieval without similarity threshold',
|
|
526
|
+
pattern: /similaritySearch\s*\(\s*[^,)]+\s*,\s*\d+\s*\)(?![\s\S]{0,50}(?:filter|threshold|score\s*>|minScore|scoreThreshold))/gi,
|
|
527
|
+
riskType: 'embedding_poisoning',
|
|
528
|
+
baseSeverity: 'medium',
|
|
529
|
+
description: 'Vector search without similarity threshold. Low-relevance adversarial content may be retrieved.',
|
|
530
|
+
suggestedFix: 'Add similarity threshold: similaritySearch(query, k, { scoreThreshold: 0.7 })',
|
|
531
|
+
},
|
|
532
|
+
// Batch embedding without deduplication
|
|
533
|
+
{
|
|
534
|
+
name: 'Batch embedding without duplicate detection',
|
|
535
|
+
pattern: /(?:for|forEach|map)\s*\([^)]+\)[\s\S]{0,100}(?:vectorStore|index)\.(?:add|upsert)(?![\s\S]{0,80}(?:exists|duplicate|similar|dedup))/gis,
|
|
536
|
+
riskType: 'embedding_poisoning',
|
|
537
|
+
baseSeverity: 'low',
|
|
538
|
+
description: 'Batch document embedding without duplicate detection. Attackers could flood corpus.',
|
|
539
|
+
suggestedFix: 'Check for duplicate or near-duplicate documents before embedding.',
|
|
540
|
+
},
|
|
541
|
+
// Dynamic embedding model selection
|
|
542
|
+
{
|
|
543
|
+
name: 'Dynamic embedding model from config',
|
|
544
|
+
pattern: /(?:embeddingModel|embeddings?)\s*=\s*(?:new\s+)?(?:config|options|params)\[?\s*['".]?(?:model|embedding)/gi,
|
|
545
|
+
riskType: 'embedding_poisoning',
|
|
546
|
+
baseSeverity: 'medium',
|
|
547
|
+
description: 'Embedding model selected from configuration. Malicious config could use compromised model.',
|
|
548
|
+
suggestedFix: 'Use hardcoded embedding model or validate against allowlist.',
|
|
549
|
+
},
|
|
550
|
+
// External URL content embedded
|
|
551
|
+
{
|
|
552
|
+
name: 'External URL content embedded directly',
|
|
553
|
+
pattern: /(?:fetch|axios\.get|httpx\.get)\s*\([^)]+\)[\s\S]{0,150}(?:embed|vectorStore\.add|index\.upsert)/gis,
|
|
554
|
+
riskType: 'embedding_poisoning',
|
|
555
|
+
baseSeverity: 'high',
|
|
556
|
+
description: 'Content from external URLs embedded without validation. Source could be compromised.',
|
|
557
|
+
suggestedFix: 'Validate URL source against allowlist. Sanitize fetched content before embedding.',
|
|
558
|
+
},
|
|
559
|
+
];
|
|
560
|
+
/**
|
|
561
|
+
* Phase 6 Task 4: Cross-Tenant RAG Detection Patterns
|
|
562
|
+
* Detect shared vector stores without tenant filtering that could leak data
|
|
563
|
+
*/
|
|
564
|
+
const CROSS_TENANT_PATTERNS = [
|
|
565
|
+
// Shared vector store without tenant filter
|
|
566
|
+
{
|
|
567
|
+
name: 'Shared vector store without tenant filter',
|
|
568
|
+
pattern: /\b(?:vectorStore|index|collection)\s*=\s*(?:new\s+)?(?:PineconeStore|ChromaDB|Weaviate|Qdrant|Milvus|PGVector|VectorStore)\s*\([^)]*\)(?![\s\S]{0,100}(?:filter|where|tenant|user|org|namespace))/gi,
|
|
569
|
+
riskType: 'unscoped_retrieval',
|
|
570
|
+
baseSeverity: 'high',
|
|
571
|
+
description: 'Vector store initialized without tenant filtering. In multi-tenant applications, this could leak data across tenants.',
|
|
572
|
+
suggestedFix: 'Always include tenant/user ID in vector store configuration or filters: new VectorStore({ namespace: tenantId })',
|
|
573
|
+
},
|
|
574
|
+
// Query without tenant in metadata filter
|
|
575
|
+
{
|
|
576
|
+
name: 'Vector query missing tenant filter',
|
|
577
|
+
pattern: /\.(?:query|search|similaritySearch)\s*\(\s*[^,)]+(?:,\s*\{[^}]*\})?\s*\)(?![\s\S]{0,80}(?:tenantId|tenant_id|orgId|org_id|userId|user_id|namespace))/gi,
|
|
578
|
+
riskType: 'unscoped_retrieval',
|
|
579
|
+
baseSeverity: 'high',
|
|
580
|
+
description: 'Vector store query without tenant filtering. Results may include documents from other tenants.',
|
|
581
|
+
suggestedFix: 'Add tenant filter to query: .query(q, { filter: { tenantId: ctx.tenant.id } })',
|
|
582
|
+
},
|
|
583
|
+
// Global index access pattern
|
|
584
|
+
{
|
|
585
|
+
name: 'Global index without scoping',
|
|
586
|
+
pattern: /(?:const|let|var)\s+(?:index|vectorIndex|searchIndex)\s*=\s*(?:await\s+)?(?:getIndex|loadIndex|connectIndex|initializeIndex)\s*\(\s*(?:['"`][^'"`]+['"`])?\s*\)(?![\s\S]{0,50}(?:tenant|user|org|scope))/gi,
|
|
587
|
+
riskType: 'unscoped_retrieval',
|
|
588
|
+
baseSeverity: 'medium',
|
|
589
|
+
description: 'Global index loaded without tenant scoping. Consider using tenant-specific indexes or namespaces.',
|
|
590
|
+
suggestedFix: 'Use tenant-scoped index: const index = await getIndex(tenantId) or use namespace parameter',
|
|
591
|
+
},
|
|
592
|
+
// Multi-tenant store without isolation
|
|
593
|
+
{
|
|
594
|
+
name: 'Multi-tenant store missing isolation',
|
|
595
|
+
pattern: /(?:multiTenant|shared|global)(?:Store|Index|Collection)\s*\.(?:query|search|add|upsert)(?![\s\S]{0,80}(?:tenantId|tenant_id|isolate|partition|namespace))/gi,
|
|
596
|
+
riskType: 'unscoped_retrieval',
|
|
597
|
+
baseSeverity: 'critical',
|
|
598
|
+
description: 'Multi-tenant store accessed without tenant isolation. Data from all tenants is accessible.',
|
|
599
|
+
suggestedFix: 'Always pass tenant identifier: multiTenantStore.query(q, { tenantId })',
|
|
600
|
+
},
|
|
601
|
+
// Embedding documents without tenant metadata
|
|
602
|
+
{
|
|
603
|
+
name: 'Document embedded without tenant metadata',
|
|
604
|
+
pattern: /\.(?:addDocuments|upsert|add)\s*\(\s*\[?\s*\{[^}]*(?:content|text|pageContent)[^}]*\}(?![^}]*(?:tenantId|tenant_id|orgId|organizationId|userId|user_id))/gi,
|
|
605
|
+
riskType: 'corpus_poisoning',
|
|
606
|
+
baseSeverity: 'high',
|
|
607
|
+
description: 'Documents embedded without tenant metadata. Without tenant ID, documents cannot be filtered per-tenant.',
|
|
608
|
+
suggestedFix: 'Include tenant ID in document metadata: { content, metadata: { tenantId: ctx.tenant.id } }',
|
|
609
|
+
},
|
|
610
|
+
// Retriever without tenant context
|
|
611
|
+
{
|
|
612
|
+
name: 'Retriever created without tenant context',
|
|
613
|
+
pattern: /(?:asRetriever|createRetriever|getRetriever)\s*\(\s*(?:\{[^}]*\})?\s*\)(?![\s\S]{0,80}(?:filter|tenant|user|org|metadata))/gi,
|
|
614
|
+
riskType: 'unscoped_retrieval',
|
|
615
|
+
baseSeverity: 'medium',
|
|
616
|
+
description: 'Retriever created without tenant filtering configuration. Retrieved documents may cross tenant boundaries.',
|
|
617
|
+
suggestedFix: 'Configure retriever with tenant filter: vectorStore.asRetriever({ filter: { tenantId } })',
|
|
618
|
+
},
|
|
619
|
+
// Semantic search across all tenants
|
|
620
|
+
{
|
|
621
|
+
name: 'Semantic search without tenant restriction',
|
|
622
|
+
pattern: /semanticSearch\s*\(\s*[^,)]+\s*\)(?![\s\S]{0,50}(?:tenant|user|org|filter|where|scope))/gi,
|
|
623
|
+
riskType: 'unscoped_retrieval',
|
|
624
|
+
baseSeverity: 'high',
|
|
625
|
+
description: 'Semantic search without tenant restriction. Search results span all tenants.',
|
|
626
|
+
suggestedFix: 'Add tenant restriction: semanticSearch(query, { tenantId: ctx.tenant.id })',
|
|
627
|
+
},
|
|
628
|
+
// RAG chain without tenant context
|
|
629
|
+
{
|
|
630
|
+
name: 'RAG chain missing tenant context',
|
|
631
|
+
pattern: /(?:createRetrievalChain|RetrievalQAChain|ConversationalRetrievalChain)\.(?:fromLLM|from)?\s*\([^)]*\)(?![\s\S]{0,100}(?:filter|tenant|user|metadata))/gi,
|
|
632
|
+
riskType: 'unscoped_retrieval',
|
|
633
|
+
baseSeverity: 'medium',
|
|
634
|
+
description: 'RAG chain created without tenant context. Chain may retrieve documents from all tenants.',
|
|
635
|
+
suggestedFix: 'Pass tenant-filtered retriever to chain or add metadata filtering',
|
|
636
|
+
},
|
|
637
|
+
];
|
|
638
|
+
/**
|
|
639
|
+
* Chunk Boundary Exploitation Patterns
|
|
640
|
+
* Detects cross-chunk injection vulnerabilities
|
|
641
|
+
*/
|
|
642
|
+
const CHUNK_INJECTION_PATTERNS = [
|
|
643
|
+
// User content chunked without per-chunk validation
|
|
644
|
+
{
|
|
645
|
+
name: 'User content chunked without validation',
|
|
646
|
+
pattern: /(?:splitter|textSplitter|chunker)\.(?:split|createDocuments|chunk)[\s\S]{0,50}(?:user|upload|req)[\s\S]{0,100}(?:vectorStore|index)\.(?:add|upsert)(?![\s\S]{0,50}(?:sanitize|validate|filter))/gis,
|
|
647
|
+
riskType: 'chunk_injection',
|
|
648
|
+
baseSeverity: 'medium',
|
|
649
|
+
description: 'User content split and embedded without per-chunk validation. Injection could span chunks.',
|
|
650
|
+
suggestedFix: 'Validate each chunk before embedding: chunks.map(c => sanitizeChunk(c))',
|
|
651
|
+
},
|
|
652
|
+
// Context joined without separators
|
|
653
|
+
{
|
|
654
|
+
name: 'Context chunks joined without separators',
|
|
655
|
+
pattern: /\.map\s*\([^)]*(?:pageContent|content|text)[^)]*\)\.join\s*\(\s*['"]['"]\s*\)/gi,
|
|
656
|
+
riskType: 'chunk_injection',
|
|
657
|
+
baseSeverity: 'low',
|
|
658
|
+
description: 'Retrieved chunks joined without separators. Adjacent chunk content could be misinterpreted.',
|
|
659
|
+
suggestedFix: 'Use clear separators: chunks.map(c => c.content).join("\\n---\\n")',
|
|
660
|
+
},
|
|
661
|
+
// Chunk metadata from user input
|
|
662
|
+
{
|
|
663
|
+
name: 'Chunk metadata from user input',
|
|
664
|
+
pattern: /(?:vectorStore|index)\.(?:add|upsert)[\s\S]{0,100}metadata\s*:\s*(?:user|req\.|input\.|body\.)/gi,
|
|
665
|
+
riskType: 'chunk_injection',
|
|
666
|
+
baseSeverity: 'medium',
|
|
667
|
+
description: 'Chunk metadata derived from user input. Could inject malicious metadata for filtering.',
|
|
668
|
+
suggestedFix: 'Generate metadata server-side. Validate any user-provided metadata fields.',
|
|
669
|
+
},
|
|
670
|
+
// No chunk size limits
|
|
671
|
+
{
|
|
672
|
+
name: 'Chunking without size validation',
|
|
673
|
+
pattern: /(?:splitter|textSplitter)\.(?:split|createDocuments)\s*\(\s*(?:content|text|document)(?![\s\S]{0,50}(?:maxChunkSize|chunkSize|maxLength))/gi,
|
|
674
|
+
riskType: 'chunk_injection',
|
|
675
|
+
baseSeverity: 'low',
|
|
676
|
+
description: 'Text splitting without explicit size limits. Very long inputs could cause issues.',
|
|
677
|
+
suggestedFix: 'Configure chunk size limits: new TextSplitter({ chunkSize: 1000, chunkOverlap: 200 })',
|
|
678
|
+
},
|
|
679
|
+
// Overlapping chunks with user content
|
|
680
|
+
{
|
|
681
|
+
name: 'Large chunk overlap with user content',
|
|
682
|
+
pattern: /(?:chunkOverlap|overlap)\s*[:=]\s*(?:\d{3,}|[a-zA-Z])[\s\S]{0,100}(?:user|upload)/gi,
|
|
683
|
+
riskType: 'chunk_injection',
|
|
684
|
+
baseSeverity: 'low',
|
|
685
|
+
description: 'Large chunk overlap configured. User-injected content could appear in multiple chunks.',
|
|
686
|
+
suggestedFix: 'Use reasonable overlap (10-20% of chunk size). Validate user content before chunking.',
|
|
687
|
+
},
|
|
688
|
+
];
|
|
689
|
+
// ============================================================================
|
|
690
|
+
// Main Detection Function
|
|
691
|
+
// ============================================================================
|
|
692
|
+
/**
|
|
693
|
+
* Map risk type to vulnerability category
|
|
694
|
+
*/
|
|
695
|
+
function mapRiskTypeToCategory(riskType) {
|
|
696
|
+
switch (riskType) {
|
|
697
|
+
case 'corpus_poisoning':
|
|
698
|
+
return 'ai_rag_corpus_poisoning';
|
|
699
|
+
case 'pii_leakage':
|
|
700
|
+
return 'ai_rag_pii_leakage';
|
|
701
|
+
case 'query_injection':
|
|
702
|
+
return 'ai_rag_query_injection';
|
|
703
|
+
case 'embedding_poisoning':
|
|
704
|
+
return 'ai_rag_embedding_poisoning';
|
|
705
|
+
case 'chunk_injection':
|
|
706
|
+
return 'ai_rag_chunk_injection';
|
|
707
|
+
default:
|
|
708
|
+
return 'ai_rag_exfiltration';
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
/**
|
|
712
|
+
* Main detection function for RAG data safety issues
|
|
713
|
+
*/
|
|
714
|
+
function detectRAGSafetyIssues(content, filePath, options) {
|
|
715
|
+
const vulnerabilities = [];
|
|
716
|
+
// Skip non-applicable files
|
|
717
|
+
if ((0, file_classifier_1.isScannerOrFixtureFile)(filePath))
|
|
718
|
+
return vulnerabilities;
|
|
719
|
+
if ((0, file_classifier_1.isDocumentationFile)(filePath))
|
|
720
|
+
return vulnerabilities;
|
|
721
|
+
// Only scan files in RAG context
|
|
722
|
+
if (!isRAGContextFile(filePath, content)) {
|
|
723
|
+
return vulnerabilities;
|
|
724
|
+
}
|
|
725
|
+
const lines = options?.parsed?.lines ?? content.split('\n');
|
|
726
|
+
const isTestFile = (0, file_classifier_1.isTestOrMockFile)(filePath);
|
|
727
|
+
const isExample = (0, file_classifier_1.isExampleDirectory)(filePath);
|
|
728
|
+
const isLibrary = (0, file_classifier_1.isLibraryCode)(filePath);
|
|
729
|
+
const hasAuth = hasAuthenticationInContext(content);
|
|
730
|
+
// Process all pattern categories
|
|
731
|
+
const allPatterns = [
|
|
732
|
+
...UNSCOPED_RETRIEVAL_PATTERNS,
|
|
733
|
+
...CONTEXT_EXPOSURE_PATTERNS,
|
|
734
|
+
...CONTEXT_LOGGING_PATTERNS,
|
|
735
|
+
// AI Detection Roadmap Phase 1
|
|
736
|
+
...CORPUS_POISONING_PATTERNS,
|
|
737
|
+
...PII_LEAKAGE_PATTERNS,
|
|
738
|
+
// Phase 1 Enhancement Backlog
|
|
739
|
+
...QUERY_INJECTION_PATTERNS,
|
|
740
|
+
...EMBEDDING_POISONING_PATTERNS,
|
|
741
|
+
...CHUNK_INJECTION_PATTERNS,
|
|
742
|
+
// Phase 6: Cross-tenant detection
|
|
743
|
+
...CROSS_TENANT_PATTERNS,
|
|
744
|
+
];
|
|
745
|
+
for (const pattern of allPatterns) {
|
|
746
|
+
const regex = new RegExp(pattern.pattern.source, pattern.pattern.flags);
|
|
747
|
+
let match;
|
|
748
|
+
while ((match = regex.exec(content)) !== null) {
|
|
749
|
+
const lineNumber = content.substring(0, match.index).split('\n').length;
|
|
750
|
+
const lineContent = lines[lineNumber - 1]?.trim() || '';
|
|
751
|
+
// Skip comments
|
|
752
|
+
if ((0, file_classifier_1.isComment)(lineContent))
|
|
753
|
+
continue;
|
|
754
|
+
// Skip generic query patterns (req.query, searchParams, etc.)
|
|
755
|
+
if (isGenericQueryPattern(lineContent))
|
|
756
|
+
continue;
|
|
757
|
+
// Get surrounding context for analysis
|
|
758
|
+
const context = getSurroundingContext(content, lineNumber - 1, 25);
|
|
759
|
+
// Calculate severity based on context
|
|
760
|
+
let severity = pattern.baseSeverity;
|
|
761
|
+
let description = pattern.description;
|
|
762
|
+
const notes = [];
|
|
763
|
+
// Apply context-aware severity adjustments
|
|
764
|
+
if (pattern.riskType === 'unscoped_retrieval') {
|
|
765
|
+
// Check for access control in surrounding context
|
|
766
|
+
if (hasAccessControlScoping(context)) {
|
|
767
|
+
severity = 'info';
|
|
768
|
+
notes.push('Access control scoping detected nearby');
|
|
769
|
+
}
|
|
770
|
+
else if (!hasAuth) {
|
|
771
|
+
// No auth at all - higher risk
|
|
772
|
+
if (severity === 'medium')
|
|
773
|
+
severity = 'high';
|
|
774
|
+
notes.push('No authentication detected in this file');
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
if (pattern.riskType === 'context_exposure') {
|
|
778
|
+
// Check if response is filtered
|
|
779
|
+
if (hasResponseFiltering(context)) {
|
|
780
|
+
severity = 'info';
|
|
781
|
+
notes.push('Response filtering detected');
|
|
782
|
+
}
|
|
783
|
+
else if (!hasAuth) {
|
|
784
|
+
// Unauthenticated endpoint exposing context - higher risk
|
|
785
|
+
if (severity === 'medium')
|
|
786
|
+
severity = 'high';
|
|
787
|
+
notes.push('Endpoint may be unauthenticated');
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
// Corpus poisoning - check for sanitization
|
|
791
|
+
if (pattern.riskType === 'corpus_poisoning') {
|
|
792
|
+
// Check for content sanitization in context
|
|
793
|
+
if (/sanitize|validate|filter|clean|strip/i.test(context)) {
|
|
794
|
+
severity = 'info';
|
|
795
|
+
notes.push('Content sanitization detected nearby');
|
|
796
|
+
}
|
|
797
|
+
// Check for content classification/scanning
|
|
798
|
+
if (/classify|scan|detect|check.*injection/i.test(context)) {
|
|
799
|
+
severity = 'info';
|
|
800
|
+
notes.push('Content scanning detected');
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
// PII leakage - critical data types remain high severity
|
|
804
|
+
if (pattern.riskType === 'pii_leakage') {
|
|
805
|
+
// Check for PII redaction/masking
|
|
806
|
+
if (/redact|mask|anonymize|deidentify|tokenize/i.test(context)) {
|
|
807
|
+
severity = 'info';
|
|
808
|
+
notes.push('PII redaction detected');
|
|
809
|
+
}
|
|
810
|
+
// SSN, CVV, and PHI patterns remain critical regardless of context
|
|
811
|
+
if (/ssn|cvv|patient/i.test(pattern.name.toLowerCase())) {
|
|
812
|
+
// Keep severity high/critical for these
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
// Query injection - check for input validation
|
|
816
|
+
if (pattern.riskType === 'query_injection') {
|
|
817
|
+
// Check for input validation/sanitization
|
|
818
|
+
if (/sanitize|validate|clean|escape|zod|schema\.parse|safeParse/i.test(context)) {
|
|
819
|
+
severity = 'low';
|
|
820
|
+
notes.push('Input validation detected nearby');
|
|
821
|
+
}
|
|
822
|
+
// Check for query length/bounds validation
|
|
823
|
+
if (/maxLength|minLength|\.length\s*[<>]|slice\s*\(\s*0/i.test(context)) {
|
|
824
|
+
if (severity === 'high')
|
|
825
|
+
severity = 'medium';
|
|
826
|
+
notes.push('Length validation detected');
|
|
827
|
+
}
|
|
828
|
+
// Check for rate limiting
|
|
829
|
+
if (/rateLimit|throttle|limiter/i.test(context)) {
|
|
830
|
+
if (severity === 'high')
|
|
831
|
+
severity = 'medium';
|
|
832
|
+
notes.push('Rate limiting detected');
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
// Embedding poisoning - check for content validation
|
|
836
|
+
if (pattern.riskType === 'embedding_poisoning') {
|
|
837
|
+
// Check for content sanitization
|
|
838
|
+
if (/sanitize|validate|filter|clean|strip|scan/i.test(context)) {
|
|
839
|
+
severity = 'low';
|
|
840
|
+
notes.push('Content validation detected nearby');
|
|
841
|
+
}
|
|
842
|
+
// Check for content classification
|
|
843
|
+
if (/classify|moderation|detect.*injection|contentFilter/i.test(context)) {
|
|
844
|
+
severity = 'info';
|
|
845
|
+
notes.push('Content classification detected');
|
|
846
|
+
}
|
|
847
|
+
// Check for similarity threshold
|
|
848
|
+
if (/threshold|scoreThreshold|minScore|score\s*>/i.test(context)) {
|
|
849
|
+
if (severity === 'medium')
|
|
850
|
+
severity = 'low';
|
|
851
|
+
notes.push('Similarity threshold configured');
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
// Chunk injection - check for chunk validation
|
|
855
|
+
if (pattern.riskType === 'chunk_injection') {
|
|
856
|
+
// Check for per-chunk validation
|
|
857
|
+
if (/chunks?\.map\s*\([^)]*sanitize|validate.*chunk|chunk.*validate/i.test(context)) {
|
|
858
|
+
severity = 'info';
|
|
859
|
+
notes.push('Chunk validation detected');
|
|
860
|
+
}
|
|
861
|
+
// Check for separator usage
|
|
862
|
+
if (/separator|delimiter|join\s*\(\s*['"][^'"]{2,}['"]\s*\)/i.test(context)) {
|
|
863
|
+
if (severity === 'low')
|
|
864
|
+
severity = 'info';
|
|
865
|
+
notes.push('Chunk separators detected');
|
|
866
|
+
}
|
|
867
|
+
// Check for metadata sanitization
|
|
868
|
+
if (/metadata\s*[:=]\s*\{[^}]*(?:id|type|source)[^}]*\}/i.test(context)) {
|
|
869
|
+
if (severity === 'medium')
|
|
870
|
+
severity = 'low';
|
|
871
|
+
notes.push('Server-generated metadata pattern');
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
// Downgrade test files
|
|
875
|
+
if (isTestFile) {
|
|
876
|
+
severity = 'info';
|
|
877
|
+
notes.push('in test file');
|
|
878
|
+
}
|
|
879
|
+
// Downgrade example/demo directories
|
|
880
|
+
if (isExample && severity !== 'info') {
|
|
881
|
+
severity = 'info';
|
|
882
|
+
notes.push('in example/demo directory');
|
|
883
|
+
}
|
|
884
|
+
// Downgrade library code - base classes are intentionally generic
|
|
885
|
+
if (isLibrary && severity !== 'info') {
|
|
886
|
+
severity = 'info';
|
|
887
|
+
notes.push('library code - consumers add access controls');
|
|
888
|
+
}
|
|
889
|
+
// Build final description
|
|
890
|
+
if (notes.length > 0) {
|
|
891
|
+
description += ` (${notes.join('; ')})`;
|
|
892
|
+
}
|
|
893
|
+
vulnerabilities.push({
|
|
894
|
+
id: `ai-rag-${filePath}-${lineNumber}-${pattern.name.replace(/\s+/g, '-')}`,
|
|
895
|
+
filePath,
|
|
896
|
+
lineNumber,
|
|
897
|
+
lineContent,
|
|
898
|
+
severity,
|
|
899
|
+
category: mapRiskTypeToCategory(pattern.riskType),
|
|
900
|
+
title: pattern.name,
|
|
901
|
+
description,
|
|
902
|
+
suggestedFix: pattern.suggestedFix,
|
|
903
|
+
confidence: severity === 'info' ? 'low' : 'medium',
|
|
904
|
+
layer: 2,
|
|
905
|
+
source: 'ai_code',
|
|
906
|
+
requiresAIValidation: severity !== 'info' && pattern.riskType !== 'context_logging',
|
|
907
|
+
baseConfidence: BASE_CONFIDENCE,
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
return vulnerabilities;
|
|
912
|
+
}
|
|
913
|
+
//# sourceMappingURL=rag-safety.js.map
|