@oculum/scanner 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/dist/formatters/cli-terminal.d.ts +27 -0
  2. package/dist/formatters/cli-terminal.d.ts.map +1 -0
  3. package/dist/formatters/cli-terminal.js +412 -0
  4. package/dist/formatters/cli-terminal.js.map +1 -0
  5. package/dist/formatters/github-comment.d.ts +41 -0
  6. package/dist/formatters/github-comment.d.ts.map +1 -0
  7. package/dist/formatters/github-comment.js +306 -0
  8. package/dist/formatters/github-comment.js.map +1 -0
  9. package/dist/formatters/grouping.d.ts +52 -0
  10. package/dist/formatters/grouping.d.ts.map +1 -0
  11. package/dist/formatters/grouping.js +152 -0
  12. package/dist/formatters/grouping.js.map +1 -0
  13. package/dist/formatters/index.d.ts +9 -0
  14. package/dist/formatters/index.d.ts.map +1 -0
  15. package/dist/formatters/index.js +35 -0
  16. package/dist/formatters/index.js.map +1 -0
  17. package/dist/formatters/vscode-diagnostic.d.ts +103 -0
  18. package/dist/formatters/vscode-diagnostic.d.ts.map +1 -0
  19. package/dist/formatters/vscode-diagnostic.js +151 -0
  20. package/dist/formatters/vscode-diagnostic.js.map +1 -0
  21. package/dist/index.d.ts +52 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +648 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/layer1/comments.d.ts +8 -0
  26. package/dist/layer1/comments.d.ts.map +1 -0
  27. package/dist/layer1/comments.js +203 -0
  28. package/dist/layer1/comments.js.map +1 -0
  29. package/dist/layer1/config-audit.d.ts +8 -0
  30. package/dist/layer1/config-audit.d.ts.map +1 -0
  31. package/dist/layer1/config-audit.js +252 -0
  32. package/dist/layer1/config-audit.js.map +1 -0
  33. package/dist/layer1/entropy.d.ts +8 -0
  34. package/dist/layer1/entropy.d.ts.map +1 -0
  35. package/dist/layer1/entropy.js +500 -0
  36. package/dist/layer1/entropy.js.map +1 -0
  37. package/dist/layer1/file-flags.d.ts +7 -0
  38. package/dist/layer1/file-flags.d.ts.map +1 -0
  39. package/dist/layer1/file-flags.js +112 -0
  40. package/dist/layer1/file-flags.js.map +1 -0
  41. package/dist/layer1/index.d.ts +36 -0
  42. package/dist/layer1/index.d.ts.map +1 -0
  43. package/dist/layer1/index.js +132 -0
  44. package/dist/layer1/index.js.map +1 -0
  45. package/dist/layer1/patterns.d.ts +8 -0
  46. package/dist/layer1/patterns.d.ts.map +1 -0
  47. package/dist/layer1/patterns.js +482 -0
  48. package/dist/layer1/patterns.js.map +1 -0
  49. package/dist/layer1/urls.d.ts +8 -0
  50. package/dist/layer1/urls.d.ts.map +1 -0
  51. package/dist/layer1/urls.js +296 -0
  52. package/dist/layer1/urls.js.map +1 -0
  53. package/dist/layer1/weak-crypto.d.ts +7 -0
  54. package/dist/layer1/weak-crypto.d.ts.map +1 -0
  55. package/dist/layer1/weak-crypto.js +291 -0
  56. package/dist/layer1/weak-crypto.js.map +1 -0
  57. package/dist/layer2/ai-agent-tools.d.ts +19 -0
  58. package/dist/layer2/ai-agent-tools.d.ts.map +1 -0
  59. package/dist/layer2/ai-agent-tools.js +528 -0
  60. package/dist/layer2/ai-agent-tools.js.map +1 -0
  61. package/dist/layer2/ai-endpoint-protection.d.ts +36 -0
  62. package/dist/layer2/ai-endpoint-protection.d.ts.map +1 -0
  63. package/dist/layer2/ai-endpoint-protection.js +332 -0
  64. package/dist/layer2/ai-endpoint-protection.js.map +1 -0
  65. package/dist/layer2/ai-execution-sinks.d.ts +18 -0
  66. package/dist/layer2/ai-execution-sinks.d.ts.map +1 -0
  67. package/dist/layer2/ai-execution-sinks.js +496 -0
  68. package/dist/layer2/ai-execution-sinks.js.map +1 -0
  69. package/dist/layer2/ai-fingerprinting.d.ts +7 -0
  70. package/dist/layer2/ai-fingerprinting.d.ts.map +1 -0
  71. package/dist/layer2/ai-fingerprinting.js +654 -0
  72. package/dist/layer2/ai-fingerprinting.js.map +1 -0
  73. package/dist/layer2/ai-prompt-hygiene.d.ts +19 -0
  74. package/dist/layer2/ai-prompt-hygiene.d.ts.map +1 -0
  75. package/dist/layer2/ai-prompt-hygiene.js +356 -0
  76. package/dist/layer2/ai-prompt-hygiene.js.map +1 -0
  77. package/dist/layer2/ai-rag-safety.d.ts +21 -0
  78. package/dist/layer2/ai-rag-safety.d.ts.map +1 -0
  79. package/dist/layer2/ai-rag-safety.js +459 -0
  80. package/dist/layer2/ai-rag-safety.js.map +1 -0
  81. package/dist/layer2/ai-schema-validation.d.ts +25 -0
  82. package/dist/layer2/ai-schema-validation.d.ts.map +1 -0
  83. package/dist/layer2/ai-schema-validation.js +375 -0
  84. package/dist/layer2/ai-schema-validation.js.map +1 -0
  85. package/dist/layer2/auth-antipatterns.d.ts +20 -0
  86. package/dist/layer2/auth-antipatterns.d.ts.map +1 -0
  87. package/dist/layer2/auth-antipatterns.js +333 -0
  88. package/dist/layer2/auth-antipatterns.js.map +1 -0
  89. package/dist/layer2/byok-patterns.d.ts +12 -0
  90. package/dist/layer2/byok-patterns.d.ts.map +1 -0
  91. package/dist/layer2/byok-patterns.js +299 -0
  92. package/dist/layer2/byok-patterns.js.map +1 -0
  93. package/dist/layer2/dangerous-functions.d.ts +7 -0
  94. package/dist/layer2/dangerous-functions.d.ts.map +1 -0
  95. package/dist/layer2/dangerous-functions.js +1375 -0
  96. package/dist/layer2/dangerous-functions.js.map +1 -0
  97. package/dist/layer2/data-exposure.d.ts +16 -0
  98. package/dist/layer2/data-exposure.d.ts.map +1 -0
  99. package/dist/layer2/data-exposure.js +279 -0
  100. package/dist/layer2/data-exposure.js.map +1 -0
  101. package/dist/layer2/framework-checks.d.ts +7 -0
  102. package/dist/layer2/framework-checks.d.ts.map +1 -0
  103. package/dist/layer2/framework-checks.js +388 -0
  104. package/dist/layer2/framework-checks.js.map +1 -0
  105. package/dist/layer2/index.d.ts +58 -0
  106. package/dist/layer2/index.d.ts.map +1 -0
  107. package/dist/layer2/index.js +380 -0
  108. package/dist/layer2/index.js.map +1 -0
  109. package/dist/layer2/logic-gates.d.ts +7 -0
  110. package/dist/layer2/logic-gates.d.ts.map +1 -0
  111. package/dist/layer2/logic-gates.js +182 -0
  112. package/dist/layer2/logic-gates.js.map +1 -0
  113. package/dist/layer2/risky-imports.d.ts +7 -0
  114. package/dist/layer2/risky-imports.d.ts.map +1 -0
  115. package/dist/layer2/risky-imports.js +161 -0
  116. package/dist/layer2/risky-imports.js.map +1 -0
  117. package/dist/layer2/variables.d.ts +8 -0
  118. package/dist/layer2/variables.d.ts.map +1 -0
  119. package/dist/layer2/variables.js +152 -0
  120. package/dist/layer2/variables.js.map +1 -0
  121. package/dist/layer3/anthropic.d.ts +83 -0
  122. package/dist/layer3/anthropic.d.ts.map +1 -0
  123. package/dist/layer3/anthropic.js +1745 -0
  124. package/dist/layer3/anthropic.js.map +1 -0
  125. package/dist/layer3/index.d.ts +24 -0
  126. package/dist/layer3/index.d.ts.map +1 -0
  127. package/dist/layer3/index.js +119 -0
  128. package/dist/layer3/index.js.map +1 -0
  129. package/dist/layer3/openai.d.ts +25 -0
  130. package/dist/layer3/openai.d.ts.map +1 -0
  131. package/dist/layer3/openai.js +238 -0
  132. package/dist/layer3/openai.js.map +1 -0
  133. package/dist/layer3/package-check.d.ts +63 -0
  134. package/dist/layer3/package-check.d.ts.map +1 -0
  135. package/dist/layer3/package-check.js +508 -0
  136. package/dist/layer3/package-check.js.map +1 -0
  137. package/dist/modes/incremental.d.ts +66 -0
  138. package/dist/modes/incremental.d.ts.map +1 -0
  139. package/dist/modes/incremental.js +200 -0
  140. package/dist/modes/incremental.js.map +1 -0
  141. package/dist/tiers.d.ts +125 -0
  142. package/dist/tiers.d.ts.map +1 -0
  143. package/dist/tiers.js +234 -0
  144. package/dist/tiers.js.map +1 -0
  145. package/dist/types.d.ts +175 -0
  146. package/dist/types.d.ts.map +1 -0
  147. package/dist/types.js +50 -0
  148. package/dist/types.js.map +1 -0
  149. package/dist/utils/auth-helper-detector.d.ts +56 -0
  150. package/dist/utils/auth-helper-detector.d.ts.map +1 -0
  151. package/dist/utils/auth-helper-detector.js +360 -0
  152. package/dist/utils/auth-helper-detector.js.map +1 -0
  153. package/dist/utils/context-helpers.d.ts +96 -0
  154. package/dist/utils/context-helpers.d.ts.map +1 -0
  155. package/dist/utils/context-helpers.js +493 -0
  156. package/dist/utils/context-helpers.js.map +1 -0
  157. package/dist/utils/diff-detector.d.ts +53 -0
  158. package/dist/utils/diff-detector.d.ts.map +1 -0
  159. package/dist/utils/diff-detector.js +104 -0
  160. package/dist/utils/diff-detector.js.map +1 -0
  161. package/dist/utils/diff-parser.d.ts +80 -0
  162. package/dist/utils/diff-parser.d.ts.map +1 -0
  163. package/dist/utils/diff-parser.js +202 -0
  164. package/dist/utils/diff-parser.js.map +1 -0
  165. package/dist/utils/imported-auth-detector.d.ts +37 -0
  166. package/dist/utils/imported-auth-detector.d.ts.map +1 -0
  167. package/dist/utils/imported-auth-detector.js +251 -0
  168. package/dist/utils/imported-auth-detector.js.map +1 -0
  169. package/dist/utils/middleware-detector.d.ts +55 -0
  170. package/dist/utils/middleware-detector.d.ts.map +1 -0
  171. package/dist/utils/middleware-detector.js +260 -0
  172. package/dist/utils/middleware-detector.js.map +1 -0
  173. package/dist/utils/oauth-flow-detector.d.ts +41 -0
  174. package/dist/utils/oauth-flow-detector.d.ts.map +1 -0
  175. package/dist/utils/oauth-flow-detector.js +202 -0
  176. package/dist/utils/oauth-flow-detector.js.map +1 -0
  177. package/dist/utils/path-exclusions.d.ts +55 -0
  178. package/dist/utils/path-exclusions.d.ts.map +1 -0
  179. package/dist/utils/path-exclusions.js +222 -0
  180. package/dist/utils/path-exclusions.js.map +1 -0
  181. package/dist/utils/project-context-builder.d.ts +119 -0
  182. package/dist/utils/project-context-builder.d.ts.map +1 -0
  183. package/dist/utils/project-context-builder.js +534 -0
  184. package/dist/utils/project-context-builder.js.map +1 -0
  185. package/dist/utils/registry-clients.d.ts +93 -0
  186. package/dist/utils/registry-clients.d.ts.map +1 -0
  187. package/dist/utils/registry-clients.js +273 -0
  188. package/dist/utils/registry-clients.js.map +1 -0
  189. package/dist/utils/trpc-analyzer.d.ts +78 -0
  190. package/dist/utils/trpc-analyzer.d.ts.map +1 -0
  191. package/dist/utils/trpc-analyzer.js +297 -0
  192. package/dist/utils/trpc-analyzer.js.map +1 -0
  193. package/package.json +45 -0
  194. package/src/__tests__/benchmark/fixtures/false-positives.ts +227 -0
  195. package/src/__tests__/benchmark/fixtures/index.ts +68 -0
  196. package/src/__tests__/benchmark/fixtures/layer1/config-audit.ts +364 -0
  197. package/src/__tests__/benchmark/fixtures/layer1/hardcoded-secrets.ts +173 -0
  198. package/src/__tests__/benchmark/fixtures/layer1/high-entropy.ts +234 -0
  199. package/src/__tests__/benchmark/fixtures/layer1/index.ts +31 -0
  200. package/src/__tests__/benchmark/fixtures/layer1/sensitive-urls.ts +90 -0
  201. package/src/__tests__/benchmark/fixtures/layer1/weak-crypto.ts +197 -0
  202. package/src/__tests__/benchmark/fixtures/layer2/ai-agent-tools.ts +170 -0
  203. package/src/__tests__/benchmark/fixtures/layer2/ai-endpoint-protection.ts +418 -0
  204. package/src/__tests__/benchmark/fixtures/layer2/ai-execution-sinks.ts +189 -0
  205. package/src/__tests__/benchmark/fixtures/layer2/ai-fingerprinting.ts +316 -0
  206. package/src/__tests__/benchmark/fixtures/layer2/ai-prompt-hygiene.ts +178 -0
  207. package/src/__tests__/benchmark/fixtures/layer2/ai-rag-safety.ts +184 -0
  208. package/src/__tests__/benchmark/fixtures/layer2/ai-schema-validation.ts +434 -0
  209. package/src/__tests__/benchmark/fixtures/layer2/auth-antipatterns.ts +159 -0
  210. package/src/__tests__/benchmark/fixtures/layer2/byok-patterns.ts +112 -0
  211. package/src/__tests__/benchmark/fixtures/layer2/dangerous-functions.ts +246 -0
  212. package/src/__tests__/benchmark/fixtures/layer2/data-exposure.ts +168 -0
  213. package/src/__tests__/benchmark/fixtures/layer2/framework-checks.ts +346 -0
  214. package/src/__tests__/benchmark/fixtures/layer2/index.ts +67 -0
  215. package/src/__tests__/benchmark/fixtures/layer2/injection-vulnerabilities.ts +239 -0
  216. package/src/__tests__/benchmark/fixtures/layer2/logic-gates.ts +246 -0
  217. package/src/__tests__/benchmark/fixtures/layer2/risky-imports.ts +231 -0
  218. package/src/__tests__/benchmark/fixtures/layer2/variables.ts +167 -0
  219. package/src/__tests__/benchmark/index.ts +29 -0
  220. package/src/__tests__/benchmark/run-benchmark.ts +144 -0
  221. package/src/__tests__/benchmark/run-depth-validation.ts +206 -0
  222. package/src/__tests__/benchmark/run-real-world-test.ts +243 -0
  223. package/src/__tests__/benchmark/security-benchmark-script.ts +1737 -0
  224. package/src/__tests__/benchmark/tier-integration-script.ts +177 -0
  225. package/src/__tests__/benchmark/types.ts +144 -0
  226. package/src/__tests__/benchmark/utils/test-runner.ts +475 -0
  227. package/src/__tests__/regression/known-false-positives.test.ts +467 -0
  228. package/src/__tests__/snapshots/__snapshots__/scan-depth.test.ts.snap +178 -0
  229. package/src/__tests__/snapshots/scan-depth.test.ts +258 -0
  230. package/src/__tests__/validation/analyze-results.ts +542 -0
  231. package/src/__tests__/validation/extract-for-triage.ts +146 -0
  232. package/src/__tests__/validation/fp-deep-analysis.ts +327 -0
  233. package/src/__tests__/validation/run-validation.ts +364 -0
  234. package/src/__tests__/validation/triage-template.md +132 -0
  235. package/src/formatters/cli-terminal.ts +446 -0
  236. package/src/formatters/github-comment.ts +382 -0
  237. package/src/formatters/grouping.ts +190 -0
  238. package/src/formatters/index.ts +47 -0
  239. package/src/formatters/vscode-diagnostic.ts +243 -0
  240. package/src/index.ts +823 -0
  241. package/src/layer1/comments.ts +218 -0
  242. package/src/layer1/config-audit.ts +289 -0
  243. package/src/layer1/entropy.ts +583 -0
  244. package/src/layer1/file-flags.ts +127 -0
  245. package/src/layer1/index.ts +181 -0
  246. package/src/layer1/patterns.ts +516 -0
  247. package/src/layer1/urls.ts +334 -0
  248. package/src/layer1/weak-crypto.ts +328 -0
  249. package/src/layer2/ai-agent-tools.ts +601 -0
  250. package/src/layer2/ai-endpoint-protection.ts +387 -0
  251. package/src/layer2/ai-execution-sinks.ts +580 -0
  252. package/src/layer2/ai-fingerprinting.ts +758 -0
  253. package/src/layer2/ai-prompt-hygiene.ts +411 -0
  254. package/src/layer2/ai-rag-safety.ts +511 -0
  255. package/src/layer2/ai-schema-validation.ts +421 -0
  256. package/src/layer2/auth-antipatterns.ts +394 -0
  257. package/src/layer2/byok-patterns.ts +336 -0
  258. package/src/layer2/dangerous-functions.ts +1563 -0
  259. package/src/layer2/data-exposure.ts +315 -0
  260. package/src/layer2/framework-checks.ts +433 -0
  261. package/src/layer2/index.ts +473 -0
  262. package/src/layer2/logic-gates.ts +206 -0
  263. package/src/layer2/risky-imports.ts +186 -0
  264. package/src/layer2/variables.ts +166 -0
  265. package/src/layer3/anthropic.ts +2030 -0
  266. package/src/layer3/index.ts +130 -0
  267. package/src/layer3/package-check.ts +604 -0
  268. package/src/modes/incremental.ts +293 -0
  269. package/src/tiers.ts +318 -0
  270. package/src/types.ts +284 -0
  271. package/src/utils/auth-helper-detector.ts +443 -0
  272. package/src/utils/context-helpers.ts +535 -0
  273. package/src/utils/diff-detector.ts +135 -0
  274. package/src/utils/diff-parser.ts +272 -0
  275. package/src/utils/imported-auth-detector.ts +320 -0
  276. package/src/utils/middleware-detector.ts +333 -0
  277. package/src/utils/oauth-flow-detector.ts +246 -0
  278. package/src/utils/path-exclusions.ts +266 -0
  279. package/src/utils/project-context-builder.ts +707 -0
  280. package/src/utils/registry-clients.ts +351 -0
  281. package/src/utils/trpc-analyzer.ts +382 -0
@@ -0,0 +1,459 @@
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 context_helpers_1 = require("../utils/context-helpers");
16
+ // ============================================================================
17
+ // Context Detection
18
+ // ============================================================================
19
+ /**
20
+ * Check if file uses client-side fuzzy search libraries (not vector stores)
21
+ * These are safe local search implementations, not cross-tenant data access risks
22
+ */
23
+ function isClientSideFuzzySearch(content) {
24
+ const fuzzySearchPatterns = [
25
+ // Fuse.js - client-side fuzzy search
26
+ /import.*from\s+['"]fuse\.js['"]/i,
27
+ /require\s*\(\s*['"]fuse\.js['"]\s*\)/i,
28
+ /new\s+Fuse\s*\(/i,
29
+ // Other client-side search libraries
30
+ /import.*from\s+['"]flexsearch['"]/i,
31
+ /import.*from\s+['"]lunr['"]/i,
32
+ /import.*from\s+['"]minisearch['"]/i,
33
+ /import.*from\s+['"]fuzzysort['"]/i,
34
+ /import.*from\s+['"]match-sorter['"]/i,
35
+ ];
36
+ return fuzzySearchPatterns.some(p => p.test(content));
37
+ }
38
+ /**
39
+ * Check if a line contains a generic query pattern that is NOT a vector store query
40
+ * These are common web framework patterns that should not be flagged as RAG issues
41
+ */
42
+ function isGenericQueryPattern(lineContent) {
43
+ const genericQueryPatterns = [
44
+ // Express/Hono/Koa query params
45
+ /req\.query\s*\(/i,
46
+ /c\.req\.query\s*\(/i,
47
+ /ctx\.query\s*\(/i,
48
+ /request\.query\s*\(/i,
49
+ // URL search params
50
+ /searchParams\.get\s*\(/i,
51
+ /url\.searchParams/i,
52
+ /URLSearchParams/i,
53
+ // Query string parsing
54
+ /querystring\.parse/i,
55
+ /qs\.parse/i,
56
+ // Database query builders (not vector stores)
57
+ /\.query\s*\(\s*['"`]SELECT/i,
58
+ /\.query\s*\(\s*['"`]INSERT/i,
59
+ /\.query\s*\(\s*['"`]UPDATE/i,
60
+ /\.query\s*\(\s*['"`]DELETE/i,
61
+ // GraphQL queries
62
+ /graphql.*query/i,
63
+ /useQuery\s*\(/i,
64
+ /useLazyQuery\s*\(/i,
65
+ // tRPC/React Query
66
+ /trpc\.\w+\.\w+\.query/i,
67
+ /\.useQuery\s*\(/i,
68
+ // Prisma/Drizzle queries
69
+ /prisma\.\w+\.findMany/i,
70
+ /db\.query\./i,
71
+ // Generic method chaining that isn't vector search
72
+ /\.query\s*\(\s*\)/i, // Empty query call
73
+ ];
74
+ return genericQueryPatterns.some(p => p.test(lineContent));
75
+ }
76
+ /**
77
+ * Check if file has vector store imports (required for RAG detection)
78
+ */
79
+ function hasVectorStoreImport(content) {
80
+ const vectorStoreImports = [
81
+ /from\s+['"]pinecone/i,
82
+ /from\s+['"]@pinecone-database/i,
83
+ /from\s+['"]weaviate/i,
84
+ /from\s+['"]chromadb/i,
85
+ /from\s+['"]@qdrant/i,
86
+ /from\s+['"]qdrant/i,
87
+ /from\s+['"]@langchain\/vectorstores/i,
88
+ /from\s+['"]langchain\/vectorstores/i,
89
+ /from\s+['"]faiss/i,
90
+ /from\s+['"]milvus/i,
91
+ /from\s+['"]@supabase.*vector/i,
92
+ /pgvector/i,
93
+ /VectorStore/i,
94
+ /Embeddings/i,
95
+ ];
96
+ return vectorStoreImports.some(p => p.test(content));
97
+ }
98
+ /**
99
+ * Check if a file is in a RAG/retrieval context based on path and content
100
+ */
101
+ function isRAGContextFile(filePath, content) {
102
+ // Skip client-side fuzzy search libraries - these are NOT vector stores
103
+ if (isClientSideFuzzySearch(content)) {
104
+ return false;
105
+ }
106
+ // Must have vector store imports to be considered RAG context
107
+ if (!hasVectorStoreImport(content)) {
108
+ return false;
109
+ }
110
+ // File path indicators of RAG code
111
+ const ragPathPatterns = [
112
+ /\/(rag|retrieval|retriever|embedding|vector|knowledge)\//i,
113
+ /\/(search|index|indexer|embeddings?)\//i,
114
+ /(rag|retriever|embedding|vector|knowledge).*\.(ts|js|tsx|jsx|py)$/i,
115
+ /(search|retrieval|indexer).*\.(ts|js|tsx|jsx|py)$/i,
116
+ ];
117
+ if (ragPathPatterns.some(p => p.test(filePath))) {
118
+ return true;
119
+ }
120
+ // Content patterns suggesting RAG usage - must be actual vector store clients
121
+ const ragContentPatterns = [
122
+ // Vector store patterns - specific to actual vector DBs
123
+ /VectorStore|Embeddings?|Retriever/i,
124
+ /similaritySearch|query_engine|retriever/i,
125
+ /vectorStore|embeddingModel|documentLoader/i,
126
+ // Framework imports - actual vector store SDKs
127
+ /from\s+['"](?:langchain|llama[-_]?index|@pinecone|@qdrant|chromadb|weaviate)/i,
128
+ /import.*(?:Pinecone|Chroma|Weaviate|Qdrant|Milvus|PGVector)/i,
129
+ // Vercel AI SDK RAG
130
+ /VercelKVVectorStore|SupabaseVectorStore|createEmbedding/i,
131
+ // Query patterns - but NOT generic .search() which could be Fuse.js
132
+ /\.retrieve\(|\.query\(/i,
133
+ /sourceDocuments|retrievedDocs|retrievedChunks/i,
134
+ // Supabase vector search
135
+ /\.rpc\s*\(\s*['"`]match_documents/i,
136
+ /pgvector|embedding.*vector/i,
137
+ ];
138
+ return ragContentPatterns.some(p => p.test(content));
139
+ }
140
+ /**
141
+ * Check if line/context has access control scoping
142
+ */
143
+ function hasAccessControlScoping(context) {
144
+ const accessPatterns = [
145
+ // User/tenant scoping
146
+ /userId|user_id|user\.id|currentUser/i,
147
+ /tenantId|tenant_id|tenant\.id|orgId|org_id|workspaceId/i,
148
+ // Filter parameters
149
+ /filter\s*[:=]\s*\{[^}]*(?:user|tenant|org)/i,
150
+ /where\s*[:=].*(?:user|tenant|org)/i,
151
+ /metadata\s*[:=].*(?:user|tenant|org)/i,
152
+ /namespace\s*[:=]/i,
153
+ // Access check functions
154
+ /checkAccess|verifyPermission|canRead|canAccess|hasAccess/i,
155
+ /getAuthorized|filterByUser|filterByTenant/i,
156
+ ];
157
+ return accessPatterns.some(p => p.test(context));
158
+ }
159
+ /**
160
+ * Check if response is filtered/processed before return
161
+ */
162
+ function hasResponseFiltering(context) {
163
+ const filterPatterns = [
164
+ // Content filtering
165
+ /\.map\s*\([^)]*\.(title|name|id|metadata)\)/i,
166
+ /\.filter\s*\(/i,
167
+ /sanitize|redact|mask|strip/i,
168
+ // Only returning specific fields
169
+ /return\s*\{[^}]*(?:id|title|summary)[^}]*\}(?![^}]*content)/i,
170
+ ];
171
+ return filterPatterns.some(p => p.test(context));
172
+ }
173
+ /**
174
+ * Check if there's authentication in the route/function
175
+ */
176
+ function hasAuthenticationInContext(content) {
177
+ const authPatterns = [
178
+ /getSession|getCurrentUser|getServerSession/i,
179
+ /auth\(\)|requireAuth|verifyToken/i,
180
+ /req\.user|request\.user|context\.user/i,
181
+ /isAuthenticated|checkAuth|withAuth/i,
182
+ /Authorization.*Bearer/i,
183
+ /userId|user\.id|currentUserId/i,
184
+ ];
185
+ return authPatterns.some(p => p.test(content));
186
+ }
187
+ /**
188
+ * Get surrounding context lines
189
+ */
190
+ function getSurroundingContext(content, lineIndex, windowSize = 25) {
191
+ const lines = content.split('\n');
192
+ const start = Math.max(0, lineIndex - windowSize);
193
+ const end = Math.min(lines.length, lineIndex + windowSize);
194
+ return lines.slice(start, end).join('\n');
195
+ }
196
+ /**
197
+ * Unscoped retrieval query patterns
198
+ * Detects vector store queries without user/tenant filtering
199
+ */
200
+ const UNSCOPED_RETRIEVAL_PATTERNS = [
201
+ // Generic vector store queries
202
+ {
203
+ name: 'Unscoped vector store query',
204
+ pattern: /\.(?:query|search|similaritySearch|retrieve)\s*\(\s*(?:["'`][^"'`]+["'`]|[a-zA-Z_]\w*)\s*\)/gi,
205
+ riskType: 'unscoped_retrieval',
206
+ baseSeverity: 'high',
207
+ description: 'Vector store query without user/tenant scoping. Retrieved documents may belong to other users, enabling cross-tenant data access.',
208
+ suggestedFix: 'Add filter/metadata parameter to scope queries: .query(query, { filter: { userId: currentUser.id } })',
209
+ },
210
+ // LangChain retriever invoke
211
+ {
212
+ name: 'LangChain retriever without filter',
213
+ pattern: /retriever\.(?:invoke|getRelevantDocuments)\s*\(\s*(?:["'`][^"'`]+["'`]|[a-zA-Z_]\w*)\s*\)/gi,
214
+ riskType: 'unscoped_retrieval',
215
+ baseSeverity: 'high',
216
+ description: 'LangChain retriever invocation without metadata filter. Documents from all users may be retrieved.',
217
+ suggestedFix: 'Use a filtered retriever or add metadata filter: retriever.invoke(query, { filter: { userId } })',
218
+ },
219
+ // LlamaIndex query engine
220
+ {
221
+ name: 'LlamaIndex query engine without filter',
222
+ pattern: /query_engine\.query\s*\(\s*["'`][^"'`]+["'`]\s*\)/gi,
223
+ riskType: 'unscoped_retrieval',
224
+ baseSeverity: 'high',
225
+ description: 'LlamaIndex query without node postprocessors or filters. All indexed documents are searchable.',
226
+ suggestedFix: 'Add node_postprocessors to filter by user/tenant metadata before retrieval.',
227
+ },
228
+ // Pinecone query
229
+ {
230
+ name: 'Pinecone query without metadata filter',
231
+ pattern: /\.query\s*\(\s*\{[^}]*(?:vector|topK)[^}]*\}\s*\)/gi,
232
+ riskType: 'unscoped_retrieval',
233
+ baseSeverity: 'medium',
234
+ description: 'Pinecone query may lack metadata filtering. Verify namespace or filter is set.',
235
+ suggestedFix: 'Add filter parameter: .query({ vector, topK, filter: { userId: { $eq: currentUserId } } })',
236
+ },
237
+ // Chroma query
238
+ {
239
+ name: 'Chroma collection query',
240
+ pattern: /collection\.query\s*\(\s*\{[^}]*query_texts[^}]*\}\s*\)/gi,
241
+ riskType: 'unscoped_retrieval',
242
+ baseSeverity: 'medium',
243
+ description: 'ChromaDB query without where filter. All documents in collection are searchable.',
244
+ suggestedFix: 'Add where parameter: collection.query({ query_texts, where: { userId: currentUserId } })',
245
+ },
246
+ // Weaviate search
247
+ {
248
+ name: 'Weaviate search without filter',
249
+ pattern: /\.nearText\s*\([^)]+\)\.(?:do|withLimit)/gi,
250
+ riskType: 'unscoped_retrieval',
251
+ baseSeverity: 'medium',
252
+ description: 'Weaviate nearText search without where filter. Results may include other users\' data.',
253
+ suggestedFix: 'Add .withWhere() to filter by user: .nearText({...}).withWhere({ path: ["userId"], operator: "Equal", valueString: userId })',
254
+ },
255
+ // Supabase vector search
256
+ {
257
+ name: 'Supabase vector search without RLS',
258
+ pattern: /\.rpc\s*\(\s*['"`]match_documents['"`]/gi,
259
+ riskType: 'unscoped_retrieval',
260
+ baseSeverity: 'medium',
261
+ description: 'Supabase vector search function called. Ensure RLS policies filter by user.',
262
+ suggestedFix: 'Verify Row Level Security (RLS) is enabled and filters documents by authenticated user.',
263
+ },
264
+ ];
265
+ /**
266
+ * Raw context exposure patterns
267
+ * Detects retrieved documents being returned directly to clients
268
+ */
269
+ const CONTEXT_EXPOSURE_PATTERNS = [
270
+ // Returning sourceDocuments in response
271
+ {
272
+ name: 'Source documents in API response',
273
+ pattern: /(?:res\.json|NextResponse\.json|return)\s*\([^)]*(?:sourceDocuments|retrievedDocs|documents|chunks)/gi,
274
+ riskType: 'context_exposure',
275
+ baseSeverity: 'medium',
276
+ description: 'Raw retrieved documents returned in API response. Source content may leak sensitive information from the knowledge base.',
277
+ suggestedFix: 'Return only synthesized response or document IDs/titles. If source attribution needed, filter to metadata only.',
278
+ },
279
+ // Spreading documents into response
280
+ {
281
+ name: 'Retrieved context spread in response',
282
+ pattern: /(?:res\.json|return)\s*\(\s*\{[^}]*\.\.\.(?:docs|documents|chunks|sourceDocuments|context)/gi,
283
+ riskType: 'context_exposure',
284
+ baseSeverity: 'medium',
285
+ description: 'Retrieved document objects spread into response. Full document content may be exposed.',
286
+ suggestedFix: 'Extract and return only safe fields: { sources: docs.map(d => ({ id: d.id, title: d.title })) }',
287
+ },
288
+ // Returning raw context in response object
289
+ {
290
+ name: 'Raw retrieval context in response',
291
+ pattern: /return\s*\{[^}]*(?:context|retrievedContext|ragContext)\s*:/gi,
292
+ riskType: 'context_exposure',
293
+ baseSeverity: 'low',
294
+ description: 'Retrieved context included in response object. Review what data is actually exposed.',
295
+ suggestedFix: 'Ensure context field contains only safe, summarized content - not raw document text.',
296
+ },
297
+ // WebSocket/stream context exposure
298
+ {
299
+ name: 'Context in streaming response',
300
+ pattern: /(?:socket|ws|stream)\.(?:send|emit|write)\s*\([^)]*(?:sourceDocuments|context|chunks)/gi,
301
+ riskType: 'context_exposure',
302
+ baseSeverity: 'medium',
303
+ description: 'Retrieved context sent via streaming/WebSocket. Clients receive raw source data.',
304
+ suggestedFix: 'Stream only AI-generated text. Send source attribution separately with filtered metadata.',
305
+ },
306
+ ];
307
+ /**
308
+ * Context logging patterns
309
+ * Detects logging of retrieved documents or prompts with context
310
+ */
311
+ const CONTEXT_LOGGING_PATTERNS = [
312
+ // Logging retrieved documents
313
+ {
314
+ name: 'Retrieved documents logged',
315
+ pattern: /(?:console|logger)\.\w+\s*\([^)]*(?:retrievedDocs|sourceDocuments|documents|chunks)/gi,
316
+ riskType: 'context_logging',
317
+ baseSeverity: 'info',
318
+ description: 'Retrieved documents logged. If logs are accessible, sensitive document content may be exposed.',
319
+ suggestedFix: 'Log document IDs/titles only: console.log("Retrieved:", docs.map(d => d.id))',
320
+ },
321
+ // Logging full prompt with context
322
+ {
323
+ name: 'Full prompt with context logged',
324
+ pattern: /(?:console|logger)\.\w+\s*\([^)]*(?:fullPrompt|promptWithContext|augmentedPrompt)/gi,
325
+ riskType: 'context_logging',
326
+ baseSeverity: 'low',
327
+ description: 'Full prompt (including retrieved context) logged. May expose sensitive document content in logs.',
328
+ suggestedFix: 'Log prompt length/metadata only. Avoid logging full prompt content in production.',
329
+ },
330
+ // Debug logging of RAG context
331
+ {
332
+ name: 'RAG context debug logging',
333
+ pattern: /(?:console\.(?:debug|log)|logger\.debug)\s*\([^)]*(?:context|ragContext|retrievalContext)/gi,
334
+ riskType: 'context_logging',
335
+ baseSeverity: 'info',
336
+ description: 'RAG context logged for debugging. Ensure debug logging is disabled in production.',
337
+ suggestedFix: 'Use conditional logging: if (process.env.NODE_ENV !== "production") console.debug(...)',
338
+ },
339
+ // Storing prompts with context
340
+ {
341
+ name: 'Prompt with context persisted',
342
+ pattern: /(?:\.create|\.insert|\.save)\s*\([^)]*(?:fullPrompt|promptWithContext|augmentedPrompt)/gi,
343
+ riskType: 'context_logging',
344
+ baseSeverity: 'medium',
345
+ description: 'Full prompt with retrieved context being persisted. May store sensitive document content.',
346
+ suggestedFix: 'Store user query and response separately. Do not persist raw retrieved context.',
347
+ },
348
+ ];
349
+ // ============================================================================
350
+ // Main Detection Function
351
+ // ============================================================================
352
+ /**
353
+ * Main detection function for RAG data safety issues
354
+ */
355
+ function detectRAGSafetyIssues(content, filePath) {
356
+ const vulnerabilities = [];
357
+ // Skip non-applicable files
358
+ if ((0, context_helpers_1.isScannerOrFixtureFile)(filePath))
359
+ return vulnerabilities;
360
+ if ((0, context_helpers_1.isDocumentationFile)(filePath))
361
+ return vulnerabilities;
362
+ // Only scan files in RAG context
363
+ if (!isRAGContextFile(filePath, content)) {
364
+ return vulnerabilities;
365
+ }
366
+ const lines = content.split('\n');
367
+ const isTestFile = (0, context_helpers_1.isTestOrMockFile)(filePath);
368
+ const isExample = (0, context_helpers_1.isExampleDirectory)(filePath);
369
+ const isLibrary = (0, context_helpers_1.isLibraryCode)(filePath);
370
+ const hasAuth = hasAuthenticationInContext(content);
371
+ // Process all pattern categories
372
+ const allPatterns = [
373
+ ...UNSCOPED_RETRIEVAL_PATTERNS,
374
+ ...CONTEXT_EXPOSURE_PATTERNS,
375
+ ...CONTEXT_LOGGING_PATTERNS,
376
+ ];
377
+ for (const pattern of allPatterns) {
378
+ const regex = new RegExp(pattern.pattern.source, pattern.pattern.flags);
379
+ let match;
380
+ while ((match = regex.exec(content)) !== null) {
381
+ const lineNumber = content.substring(0, match.index).split('\n').length;
382
+ const lineContent = lines[lineNumber - 1]?.trim() || '';
383
+ // Skip comments
384
+ if ((0, context_helpers_1.isComment)(lineContent))
385
+ continue;
386
+ // Skip generic query patterns (req.query, searchParams, etc.)
387
+ if (isGenericQueryPattern(lineContent))
388
+ continue;
389
+ // Get surrounding context for analysis
390
+ const context = getSurroundingContext(content, lineNumber - 1, 25);
391
+ // Calculate severity based on context
392
+ let severity = pattern.baseSeverity;
393
+ let description = pattern.description;
394
+ const notes = [];
395
+ // Apply context-aware severity adjustments
396
+ if (pattern.riskType === 'unscoped_retrieval') {
397
+ // Check for access control in surrounding context
398
+ if (hasAccessControlScoping(context)) {
399
+ severity = 'info';
400
+ notes.push('Access control scoping detected nearby');
401
+ }
402
+ else if (!hasAuth) {
403
+ // No auth at all - higher risk
404
+ if (severity === 'medium')
405
+ severity = 'high';
406
+ notes.push('No authentication detected in this file');
407
+ }
408
+ }
409
+ if (pattern.riskType === 'context_exposure') {
410
+ // Check if response is filtered
411
+ if (hasResponseFiltering(context)) {
412
+ severity = 'info';
413
+ notes.push('Response filtering detected');
414
+ }
415
+ else if (!hasAuth) {
416
+ // Unauthenticated endpoint exposing context - higher risk
417
+ if (severity === 'medium')
418
+ severity = 'high';
419
+ notes.push('Endpoint may be unauthenticated');
420
+ }
421
+ }
422
+ // Downgrade test files
423
+ if (isTestFile) {
424
+ severity = 'info';
425
+ notes.push('in test file');
426
+ }
427
+ // Downgrade example/demo directories
428
+ if (isExample && severity !== 'info') {
429
+ severity = 'info';
430
+ notes.push('in example/demo directory');
431
+ }
432
+ // Downgrade library code - base classes are intentionally generic
433
+ if (isLibrary && severity !== 'info') {
434
+ severity = 'info';
435
+ notes.push('library code - consumers add access controls');
436
+ }
437
+ // Build final description
438
+ if (notes.length > 0) {
439
+ description += ` (${notes.join('; ')})`;
440
+ }
441
+ vulnerabilities.push({
442
+ id: `ai-rag-${filePath}-${lineNumber}-${pattern.name.replace(/\s+/g, '-')}`,
443
+ filePath,
444
+ lineNumber,
445
+ lineContent,
446
+ severity,
447
+ category: 'ai_rag_exfiltration',
448
+ title: pattern.name,
449
+ description,
450
+ suggestedFix: pattern.suggestedFix,
451
+ confidence: severity === 'info' ? 'low' : 'medium',
452
+ layer: 2,
453
+ requiresAIValidation: severity !== 'info' && pattern.riskType !== 'context_logging',
454
+ });
455
+ }
456
+ }
457
+ return vulnerabilities;
458
+ }
459
+ //# sourceMappingURL=ai-rag-safety.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-rag-safety.js","sourceRoot":"","sources":["../../src/layer2/ai-rag-safety.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;AA8XH,sDAoHC;AAGQ,4CAAgB;AAlfzB,8DAOiC;AAEjC,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E;;;GAGG;AACH,SAAS,uBAAuB,CAAC,OAAe;IAC9C,MAAM,mBAAmB,GAAG;QAC1B,qCAAqC;QACrC,kCAAkC;QAClC,uCAAuC;QACvC,kBAAkB;QAClB,qCAAqC;QACrC,oCAAoC;QACpC,8BAA8B;QAC9B,oCAAoC;QACpC,mCAAmC;QACnC,sCAAsC;KACvC,CAAA;IACD,OAAO,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;AACvD,CAAC;AAED;;;GAGG;AACH,SAAS,qBAAqB,CAAC,WAAmB;IAChD,MAAM,oBAAoB,GAAG;QAC3B,gCAAgC;QAChC,kBAAkB;QAClB,qBAAqB;QACrB,kBAAkB;QAClB,sBAAsB;QACtB,oBAAoB;QACpB,yBAAyB;QACzB,oBAAoB;QACpB,kBAAkB;QAClB,uBAAuB;QACvB,qBAAqB;QACrB,YAAY;QACZ,8CAA8C;QAC9C,6BAA6B;QAC7B,6BAA6B;QAC7B,6BAA6B;QAC7B,6BAA6B;QAC7B,kBAAkB;QAClB,iBAAiB;QACjB,gBAAgB;QAChB,oBAAoB;QACpB,mBAAmB;QACnB,wBAAwB;QACxB,kBAAkB;QAClB,yBAAyB;QACzB,wBAAwB;QACxB,cAAc;QACd,mDAAmD;QACnD,oBAAoB,EAAG,mBAAmB;KAC3C,CAAA;IACD,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAA;AAC5D,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,OAAe;IAC3C,MAAM,kBAAkB,GAAG;QACzB,sBAAsB;QACtB,gCAAgC;QAChC,sBAAsB;QACtB,sBAAsB;QACtB,qBAAqB;QACrB,oBAAoB;QACpB,sCAAsC;QACtC,qCAAqC;QACrC,mBAAmB;QACnB,oBAAoB;QACpB,+BAA+B;QAC/B,WAAW;QACX,cAAc;QACd,aAAa;KACd,CAAA;IACD,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;AACtD,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,QAAgB,EAAE,OAAe;IACzD,wEAAwE;IACxE,IAAI,uBAAuB,CAAC,OAAO,CAAC,EAAE,CAAC;QACrC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,8DAA8D;IAC9D,IAAI,CAAC,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;QACnC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,mCAAmC;IACnC,MAAM,eAAe,GAAG;QACtB,2DAA2D;QAC3D,yCAAyC;QACzC,oEAAoE;QACpE,oDAAoD;KACrD,CAAA;IAED,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QAChD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,8EAA8E;IAC9E,MAAM,kBAAkB,GAAG;QACzB,wDAAwD;QACxD,oCAAoC;QACpC,0CAA0C;QAC1C,4CAA4C;QAC5C,+CAA+C;QAC/C,+EAA+E;QAC/E,8DAA8D;QAC9D,oBAAoB;QACpB,0DAA0D;QAC1D,oEAAoE;QACpE,yBAAyB;QACzB,gDAAgD;QAChD,yBAAyB;QACzB,oCAAoC;QACpC,6BAA6B;KAC9B,CAAA;IAED,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;AACtD,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAAC,OAAe;IAC9C,MAAM,cAAc,GAAG;QACrB,sBAAsB;QACtB,sCAAsC;QACtC,yDAAyD;QACzD,oBAAoB;QACpB,6CAA6C;QAC7C,oCAAoC;QACpC,uCAAuC;QACvC,mBAAmB;QACnB,yBAAyB;QACzB,2DAA2D;QAC3D,4CAA4C;KAC7C,CAAA;IACD,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;AAClD,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,OAAe;IAC3C,MAAM,cAAc,GAAG;QACrB,oBAAoB;QACpB,8CAA8C;QAC9C,gBAAgB;QAChB,6BAA6B;QAC7B,iCAAiC;QACjC,8DAA8D;KAC/D,CAAA;IACD,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;AAClD,CAAC;AAED;;GAEG;AACH,SAAS,0BAA0B,CAAC,OAAe;IACjD,MAAM,YAAY,GAAG;QACnB,6CAA6C;QAC7C,mCAAmC;QACnC,wCAAwC;QACxC,qCAAqC;QACrC,wBAAwB;QACxB,gCAAgC;KACjC,CAAA;IACD,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;AAChD,CAAC;AAED;;GAEG;AACH,SAAS,qBAAqB,CAAC,OAAe,EAAE,SAAiB,EAAE,aAAqB,EAAE;IACxF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,UAAU,CAAC,CAAA;IACjD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,UAAU,CAAC,CAAA;IAC1D,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAC3C,CAAC;AAeD;;;GAGG;AACH,MAAM,2BAA2B,GAAuB;IACtD,+BAA+B;IAC/B;QACE,IAAI,EAAE,6BAA6B;QACnC,OAAO,EAAE,+FAA+F;QACxG,QAAQ,EAAE,oBAAoB;QAC9B,YAAY,EAAE,MAAM;QACpB,WAAW,EAAE,mIAAmI;QAChJ,YAAY,EAAE,uGAAuG;KACtH;IACD,6BAA6B;IAC7B;QACE,IAAI,EAAE,oCAAoC;QAC1C,OAAO,EAAE,6FAA6F;QACtG,QAAQ,EAAE,oBAAoB;QAC9B,YAAY,EAAE,MAAM;QACpB,WAAW,EAAE,oGAAoG;QACjH,YAAY,EAAE,kGAAkG;KACjH;IACD,0BAA0B;IAC1B;QACE,IAAI,EAAE,wCAAwC;QAC9C,OAAO,EAAE,qDAAqD;QAC9D,QAAQ,EAAE,oBAAoB;QAC9B,YAAY,EAAE,MAAM;QACpB,WAAW,EAAE,gGAAgG;QAC7G,YAAY,EAAE,6EAA6E;KAC5F;IACD,iBAAiB;IACjB;QACE,IAAI,EAAE,wCAAwC;QAC9C,OAAO,EAAE,qDAAqD;QAC9D,QAAQ,EAAE,oBAAoB;QAC9B,YAAY,EAAE,QAAQ;QACtB,WAAW,EAAE,gFAAgF;QAC7F,YAAY,EAAE,4FAA4F;KAC3G;IACD,eAAe;IACf;QACE,IAAI,EAAE,yBAAyB;QAC/B,OAAO,EAAE,2DAA2D;QACpE,QAAQ,EAAE,oBAAoB;QAC9B,YAAY,EAAE,QAAQ;QACtB,WAAW,EAAE,kFAAkF;QAC/F,YAAY,EAAE,0FAA0F;KACzG;IACD,kBAAkB;IAClB;QACE,IAAI,EAAE,gCAAgC;QACtC,OAAO,EAAE,4CAA4C;QACrD,QAAQ,EAAE,oBAAoB;QAC9B,YAAY,EAAE,QAAQ;QACtB,WAAW,EAAE,wFAAwF;QACrG,YAAY,EAAE,8HAA8H;KAC7I;IACD,yBAAyB;IACzB;QACE,IAAI,EAAE,oCAAoC;QAC1C,OAAO,EAAE,0CAA0C;QACnD,QAAQ,EAAE,oBAAoB;QAC9B,YAAY,EAAE,QAAQ;QACtB,WAAW,EAAE,6EAA6E;QAC1F,YAAY,EAAE,yFAAyF;KACxG;CACF,CAAA;AAED;;;GAGG;AACH,MAAM,yBAAyB,GAAuB;IACpD,wCAAwC;IACxC;QACE,IAAI,EAAE,kCAAkC;QACxC,OAAO,EAAE,uGAAuG;QAChH,QAAQ,EAAE,kBAAkB;QAC5B,YAAY,EAAE,QAAQ;QACtB,WAAW,EAAE,0HAA0H;QACvI,YAAY,EAAE,iHAAiH;KAChI;IACD,oCAAoC;IACpC;QACE,IAAI,EAAE,sCAAsC;QAC5C,OAAO,EAAE,8FAA8F;QACvG,QAAQ,EAAE,kBAAkB;QAC5B,YAAY,EAAE,QAAQ;QACtB,WAAW,EAAE,wFAAwF;QACrG,YAAY,EAAE,iGAAiG;KAChH;IACD,2CAA2C;IAC3C;QACE,IAAI,EAAE,mCAAmC;QACzC,OAAO,EAAE,+DAA+D;QACxE,QAAQ,EAAE,kBAAkB;QAC5B,YAAY,EAAE,KAAK;QACnB,WAAW,EAAE,sFAAsF;QACnG,YAAY,EAAE,sFAAsF;KACrG;IACD,oCAAoC;IACpC;QACE,IAAI,EAAE,+BAA+B;QACrC,OAAO,EAAE,yFAAyF;QAClG,QAAQ,EAAE,kBAAkB;QAC5B,YAAY,EAAE,QAAQ;QACtB,WAAW,EAAE,kFAAkF;QAC/F,YAAY,EAAE,2FAA2F;KAC1G;CACF,CAAA;AAED;;;GAGG;AACH,MAAM,wBAAwB,GAAuB;IACnD,8BAA8B;IAC9B;QACE,IAAI,EAAE,4BAA4B;QAClC,OAAO,EAAE,uFAAuF;QAChG,QAAQ,EAAE,iBAAiB;QAC3B,YAAY,EAAE,MAAM;QACpB,WAAW,EAAE,gGAAgG;QAC7G,YAAY,EAAE,8EAA8E;KAC7F;IACD,mCAAmC;IACnC;QACE,IAAI,EAAE,iCAAiC;QACvC,OAAO,EAAE,qFAAqF;QAC9F,QAAQ,EAAE,iBAAiB;QAC3B,YAAY,EAAE,KAAK;QACnB,WAAW,EAAE,kGAAkG;QAC/G,YAAY,EAAE,mFAAmF;KAClG;IACD,+BAA+B;IAC/B;QACE,IAAI,EAAE,2BAA2B;QACjC,OAAO,EAAE,6FAA6F;QACtG,QAAQ,EAAE,iBAAiB;QAC3B,YAAY,EAAE,MAAM;QACpB,WAAW,EAAE,mFAAmF;QAChG,YAAY,EAAE,wFAAwF;KACvG;IACD,+BAA+B;IAC/B;QACE,IAAI,EAAE,+BAA+B;QACrC,OAAO,EAAE,0FAA0F;QACnG,QAAQ,EAAE,iBAAiB;QAC3B,YAAY,EAAE,QAAQ;QACtB,WAAW,EAAE,2FAA2F;QACxG,YAAY,EAAE,iFAAiF;KAChG;CACF,CAAA;AAED,+EAA+E;AAC/E,0BAA0B;AAC1B,+EAA+E;AAE/E;;GAEG;AACH,SAAgB,qBAAqB,CACnC,OAAe,EACf,QAAgB;IAEhB,MAAM,eAAe,GAAoB,EAAE,CAAA;IAE3C,4BAA4B;IAC5B,IAAI,IAAA,wCAAsB,EAAC,QAAQ,CAAC;QAAE,OAAO,eAAe,CAAA;IAC5D,IAAI,IAAA,qCAAmB,EAAC,QAAQ,CAAC;QAAE,OAAO,eAAe,CAAA;IAEzD,iCAAiC;IACjC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,CAAC;QACzC,OAAO,eAAe,CAAA;IACxB,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,UAAU,GAAG,IAAA,kCAAgB,EAAC,QAAQ,CAAC,CAAA;IAC7C,MAAM,SAAS,GAAG,IAAA,oCAAkB,EAAC,QAAQ,CAAC,CAAA;IAC9C,MAAM,SAAS,GAAG,IAAA,+BAAa,EAAC,QAAQ,CAAC,CAAA;IACzC,MAAM,OAAO,GAAG,0BAA0B,CAAC,OAAO,CAAC,CAAA;IAEnD,iCAAiC;IACjC,MAAM,WAAW,GAAuB;QACtC,GAAG,2BAA2B;QAC9B,GAAG,yBAAyB;QAC5B,GAAG,wBAAwB;KAC5B,CAAA;IAED,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QACvE,IAAI,KAAK,CAAA;QAET,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC9C,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAA;YACvE,MAAM,WAAW,GAAG,KAAK,CAAC,UAAU,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;YAEvD,gBAAgB;YAChB,IAAI,IAAA,2BAAS,EAAC,WAAW,CAAC;gBAAE,SAAQ;YAEpC,8DAA8D;YAC9D,IAAI,qBAAqB,CAAC,WAAW,CAAC;gBAAE,SAAQ;YAEhD,uCAAuC;YACvC,MAAM,OAAO,GAAG,qBAAqB,CAAC,OAAO,EAAE,UAAU,GAAG,CAAC,EAAE,EAAE,CAAC,CAAA;YAElE,sCAAsC;YACtC,IAAI,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAA;YACnC,IAAI,WAAW,GAAG,OAAO,CAAC,WAAW,CAAA;YACrC,MAAM,KAAK,GAAa,EAAE,CAAA;YAE1B,2CAA2C;YAC3C,IAAI,OAAO,CAAC,QAAQ,KAAK,oBAAoB,EAAE,CAAC;gBAC9C,kDAAkD;gBAClD,IAAI,uBAAuB,CAAC,OAAO,CAAC,EAAE,CAAC;oBACrC,QAAQ,GAAG,MAAM,CAAA;oBACjB,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAA;gBACtD,CAAC;qBAAM,IAAI,CAAC,OAAO,EAAE,CAAC;oBACpB,+BAA+B;oBAC/B,IAAI,QAAQ,KAAK,QAAQ;wBAAE,QAAQ,GAAG,MAAM,CAAA;oBAC5C,KAAK,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAA;gBACvD,CAAC;YACH,CAAC;YAED,IAAI,OAAO,CAAC,QAAQ,KAAK,kBAAkB,EAAE,CAAC;gBAC5C,gCAAgC;gBAChC,IAAI,oBAAoB,CAAC,OAAO,CAAC,EAAE,CAAC;oBAClC,QAAQ,GAAG,MAAM,CAAA;oBACjB,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAA;gBAC3C,CAAC;qBAAM,IAAI,CAAC,OAAO,EAAE,CAAC;oBACpB,0DAA0D;oBAC1D,IAAI,QAAQ,KAAK,QAAQ;wBAAE,QAAQ,GAAG,MAAM,CAAA;oBAC5C,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAA;gBAC/C,CAAC;YACH,CAAC;YAED,uBAAuB;YACvB,IAAI,UAAU,EAAE,CAAC;gBACf,QAAQ,GAAG,MAAM,CAAA;gBACjB,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAA;YAC5B,CAAC;YAED,qCAAqC;YACrC,IAAI,SAAS,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;gBACrC,QAAQ,GAAG,MAAM,CAAA;gBACjB,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAA;YACzC,CAAC;YAED,kEAAkE;YAClE,IAAI,SAAS,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;gBACrC,QAAQ,GAAG,MAAM,CAAA;gBACjB,KAAK,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAA;YAC5D,CAAC;YAED,0BAA0B;YAC1B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrB,WAAW,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAA;YACzC,CAAC;YAED,eAAe,CAAC,IAAI,CAAC;gBACnB,EAAE,EAAE,UAAU,QAAQ,IAAI,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE;gBAC3E,QAAQ;gBACR,UAAU;gBACV,WAAW;gBACX,QAAQ;gBACR,QAAQ,EAAE,qBAAqB;gBAC/B,KAAK,EAAE,OAAO,CAAC,IAAI;gBACnB,WAAW;gBACX,YAAY,EAAE,OAAO,CAAC,YAAY;gBAClC,UAAU,EAAE,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ;gBAClD,KAAK,EAAE,CAAC;gBACR,oBAAoB,EAAE,QAAQ,KAAK,MAAM,IAAI,OAAO,CAAC,QAAQ,KAAK,iBAAiB;aACpF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,eAAe,CAAA;AACxB,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Layer 2: AI Schema/Tooling Validation Detection
3
+ * Detects missing or weak validation of AI-generated structured outputs
4
+ *
5
+ * Covers:
6
+ * - M5.3: Schema/tooling mismatch
7
+ * - Unvalidated JSON parsing of AI outputs
8
+ * - Weak schema patterns (any, permissive)
9
+ * - Tool invocation parameters not validated
10
+ */
11
+ import type { Vulnerability } from '../types';
12
+ /**
13
+ * Check if file is in an AI/LLM context
14
+ */
15
+ declare function isAIContextFile(filePath: string, content: string): boolean;
16
+ /**
17
+ * Check if there's schema validation in the context
18
+ */
19
+ declare function hasSchemaValidation(context: string): boolean;
20
+ /**
21
+ * Main detection function for AI schema/tooling validation issues
22
+ */
23
+ export declare function detectAISchemaValidation(content: string, filePath: string): Vulnerability[];
24
+ export { isAIContextFile, hasSchemaValidation };
25
+ //# sourceMappingURL=ai-schema-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-schema-validation.d.ts","sourceRoot":"","sources":["../../src/layer2/ai-schema-validation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAyB,MAAM,UAAU,CAAA;AAYpE;;GAEG;AACH,iBAAS,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAsBnE;AAED;;GAEG;AACH,iBAAS,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAyBrD;AA+ND;;GAEG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,aAAa,EAAE,CA8GjB;AAGD,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,CAAA"}