@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,654 @@
1
+ "use strict";
2
+ /**
3
+ * Layer 2: AI Code Fingerprinting
4
+ * Detects patterns commonly found in AI-generated code that may indicate security risks
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.detectAIFingerprints = detectAIFingerprints;
8
+ const context_helpers_1 = require("../utils/context-helpers");
9
+ const AI_FINGERPRINTS = [
10
+ // ==================== Placeholder/TODO patterns - downgraded ====================
11
+ {
12
+ name: 'AI placeholder comment',
13
+ pattern: /\/\/\s*(TODO|FIXME|XXX|HACK):\s*(implement|add|replace|update|fix)\s+(this|here|later|authentication|validation|error handling)/gi,
14
+ severity: 'low', // Downgraded from medium - often harmless or addressed
15
+ description: 'AI-generated placeholder that may indicate incomplete implementation',
16
+ suggestedFix: 'Complete the implementation before deploying',
17
+ confidence: 'low', // Downgraded
18
+ },
19
+ {
20
+ name: 'Placeholder implementation',
21
+ // More specific: only match "placeholder implementation/code/function" not just "placeholder" in any context
22
+ pattern: /\/\/\s*placeholder\s+(implementation|code|function|method|logic|here)|\/\/\s*stub\s+(implementation|code|function|method)|\/\/\s*mock\s+implementation|\/\/\s*temporary\s+(implementation|code|fix|hack|workaround)/gi,
23
+ severity: 'low', // Downgraded from medium
24
+ description: 'Placeholder code that should be replaced with real implementation',
25
+ suggestedFix: 'Replace placeholder with actual implementation',
26
+ confidence: 'low', // Downgraded
27
+ },
28
+ // ==================== Overly permissive patterns ====================
29
+ {
30
+ name: 'AI catch-all error handler',
31
+ pattern: /catch\s*\([^)]*\)\s*\{\s*(console\.(log|error)|\/\/\s*handle)/gi,
32
+ severity: 'info', // Downgraded from low - this is standard practice
33
+ description: 'Generic error handling pattern - consider more specific handling',
34
+ suggestedFix: 'Add specific error handling based on error types',
35
+ confidence: 'low', // Downgraded
36
+ },
37
+ {
38
+ name: 'AI permissive CORS',
39
+ pattern: /cors\s*\(\s*\)|Access-Control-Allow-Origin['": ]*\*/gi,
40
+ severity: 'medium', // Downgraded from high - often intentional in dev
41
+ description: 'Overly permissive CORS configuration - verify if intentional',
42
+ suggestedFix: 'Restrict CORS to specific trusted origins in production',
43
+ confidence: 'medium', // Downgraded
44
+ },
45
+ // NOTE: 'any' type detection is now handled by detectSmartAnyUsage() function below
46
+ // This prevents overwhelming noise from internal utility 'any' usage
47
+ // ==================== Incomplete security patterns - heavily downgraded ====================
48
+ {
49
+ name: 'AI incomplete validation',
50
+ pattern: /if\s*\(\s*!?\s*(input|data|value|body|params)\s*\)\s*\{?\s*(return|throw)/gi,
51
+ severity: 'info', // Downgraded from low - this is often fine
52
+ description: 'Basic existence check - consider adding type validation if needed',
53
+ suggestedFix: 'Add comprehensive input validation with type and format checks',
54
+ confidence: 'low',
55
+ },
56
+ // NOTE: Removed 'AI basic auth check' pattern entirely - too many false positives
57
+ // Basic auth checks like if (!user) return are correct and common
58
+ // ==================== AI-specific comment patterns - suppressed (style only) ====================
59
+ // NOTE: Removed 'AI explanatory comment' pattern - verbose comments are style, not security
60
+ // NOTE: Removed 'AI step-by-step comment' pattern - step comments are style, not security
61
+ // ==================== Dangerous AI patterns ====================
62
+ {
63
+ name: 'AI hardcoded secret pattern',
64
+ pattern: /const\s+(API_KEY|SECRET|PASSWORD|TOKEN)\s*=\s*['"][^'"]+['"]/gi,
65
+ severity: 'critical',
66
+ description: 'Hardcoded secret - common mistake in AI-generated code',
67
+ suggestedFix: 'Move secrets to environment variables',
68
+ confidence: 'high',
69
+ },
70
+ {
71
+ name: 'AI example credentials',
72
+ pattern: /(admin|test|demo|example|sample|your)[_-]?(password|secret|key|token)\s*[=:]\s*['"][^'"]+['"]/gi,
73
+ severity: 'high',
74
+ description: 'Example/placeholder credentials that should be replaced',
75
+ suggestedFix: 'Replace example credentials with proper secret management',
76
+ confidence: 'high',
77
+ },
78
+ // NOTE: localhost/example URL detection moved to special handling below
79
+ // to allow context-aware skipping for config/example files
80
+ // ==================== AI code smell patterns - heavily downgraded ====================
81
+ {
82
+ name: 'AI console.log debugging',
83
+ pattern: /console\.log\s*\(\s*['"]?(debug|testing|here|check|log|data|result|response)/gi,
84
+ severity: 'info', // Downgraded from low - debug logs are common in dev
85
+ description: 'Debug logging that could be removed before production',
86
+ suggestedFix: 'Consider removing debug console.log statements or use proper logging',
87
+ confidence: 'low', // Downgraded
88
+ },
89
+ // NOTE: Removed 'AI magic number' pattern - magic numbers are style, not security
90
+ {
91
+ name: 'AI empty function body',
92
+ pattern: /function\s+\w+\s*\([^)]*\)\s*\{\s*(\/\/.*)?(\n\s*)?\}|=>\s*\{\s*(\/\/.*)?(\n\s*)?\}/gi,
93
+ severity: 'low', // Downgraded from medium
94
+ description: 'Empty function body - may be incomplete implementation',
95
+ suggestedFix: 'Implement the function or remove if not needed',
96
+ confidence: 'low', // Downgraded
97
+ },
98
+ // ==================== AI boilerplate patterns - heavily downgraded ====================
99
+ {
100
+ name: 'AI boilerplate error message',
101
+ pattern: /['"]Something went wrong['"]|['"]An error occurred['"]|['"]Error processing request['"]/gi,
102
+ severity: 'info', // Downgraded from low - generic messages are acceptable
103
+ description: 'Generic error message - consider more specific information',
104
+ suggestedFix: 'Replace with specific, actionable error messages',
105
+ confidence: 'low', // Downgraded
106
+ },
107
+ // NOTE: Removed 'AI success message' pattern - success messages are style, not security
108
+ // ==================== AI security bypass patterns - moderated ====================
109
+ {
110
+ name: 'AI disabled security for testing',
111
+ pattern: /\/\/\s*(disable|skip|bypass|ignore)\s*(for\s+)?(testing|development|now|temporarily)/gi,
112
+ severity: 'medium', // Downgraded from high - often intentional in dev
113
+ description: 'Security may be disabled for testing - verify production config',
114
+ suggestedFix: 'Remove testing bypasses and implement proper security',
115
+ confidence: 'medium', // Downgraded
116
+ },
117
+ {
118
+ name: 'AI TODO security',
119
+ pattern: /\/\/\s*TODO:\s*(add|implement|fix)\s*(security|auth|validation|sanitization)/gi,
120
+ severity: 'low', // Downgraded from high - often outdated or already addressed
121
+ description: 'Security feature marked as TODO - verify if addressed',
122
+ suggestedFix: 'Implement the security feature or remove if already done',
123
+ confidence: 'low', // Downgraded
124
+ },
125
+ ];
126
+ /**
127
+ * Check if 'any' usage is a safe/common ORM pattern that should be ignored
128
+ */
129
+ function isSafeORMPattern(line) {
130
+ const safePatterns = [
131
+ // Dexie/IndexedDB patterns
132
+ /\.equals\s*\(\s*null\s+as\s+any/i,
133
+ /\.equals\s*\(\s*\d+\s+as\s+any/i,
134
+ /\.equals\s*\(\s*['"`][^'"`]*['"`]\s+as\s+any/i,
135
+ /\.where\s*\(\s*.*as\s+any\s*\)/i,
136
+ /\.filter\s*\(\s*.*as\s+any\s*\)/i,
137
+ // Prisma patterns
138
+ /prisma\.\w+\.findMany/i,
139
+ /prisma\.\w+\.findFirst/i,
140
+ /prisma\.\w+\.findUnique/i,
141
+ // Supabase patterns
142
+ /supabase\.from\s*\(/i,
143
+ // Internal array maps over DB records (not untrusted input)
144
+ /\.map\s*\(\s*\(\s*\w+\s*:\s*any\s*\)\s*=>/i,
145
+ /\.filter\s*\(\s*\(\s*\w+\s*:\s*any\s*\)\s*=>/i,
146
+ /\.forEach\s*\(\s*\(\s*\w+\s*:\s*any\s*\)\s*=>/i,
147
+ /\.reduce\s*\(\s*\(\s*\w+\s*,\s*\w+\s*:\s*any\s*\)\s*=>/i,
148
+ // Type coercion for internal data
149
+ /\[\s*\d+\s*\]\s+as\s+any/, // Array index access
150
+ /\.data\s+as\s+any/i, // .data as any (common ORM pattern)
151
+ /\.result\s+as\s+any/i, // .result as any
152
+ /\.rows?\s+as\s+any/i, // .row or .rows as any
153
+ /\.records?\s+as\s+any/i, // .record or .records as any
154
+ ];
155
+ return safePatterns.some(p => p.test(line));
156
+ }
157
+ /**
158
+ * Check if 'any' usage is in a browser API event handler (safe pattern)
159
+ * These APIs often have incomplete TypeScript typings and require 'any' as a workaround
160
+ */
161
+ function isBrowserAPIEventHandler(line, filePath) {
162
+ // Skip if this is likely a server-side file
163
+ if (/\/(api|server|backend|lib\/supabase)\//i.test(filePath)) {
164
+ return false;
165
+ }
166
+ const browserAPIPatterns = [
167
+ // Web Speech API (SpeechRecognition)
168
+ /\.onresult\s*=\s*\(?.*:\s*any/i,
169
+ /\.onerror\s*=\s*\(?.*:\s*any/i,
170
+ /\.onend\s*=\s*\(?.*:\s*any/i,
171
+ /\.onstart\s*=\s*\(?.*:\s*any/i,
172
+ /\.onaudiostart\s*=\s*\(?.*:\s*any/i,
173
+ /\.onaudioend\s*=\s*\(?.*:\s*any/i,
174
+ /\.onspeechstart\s*=\s*\(?.*:\s*any/i,
175
+ /\.onspeechend\s*=\s*\(?.*:\s*any/i,
176
+ /speechRecognition/i,
177
+ /SpeechRecognition/i,
178
+ /webkitSpeechRecognition/i,
179
+ // MediaRecorder / Media APIs
180
+ /\.ondataavailable\s*=\s*\(?.*:\s*any/i,
181
+ /\.onstop\s*=\s*\(?.*:\s*any/i,
182
+ /\.onpause\s*=\s*\(?.*:\s*any/i,
183
+ /\.onresume\s*=\s*\(?.*:\s*any/i,
184
+ /mediaRecorder/i,
185
+ /MediaRecorder/i,
186
+ /MediaStream/i,
187
+ /getUserMedia/i,
188
+ // WebSocket events
189
+ /\.onopen\s*=\s*\(?.*:\s*any/i,
190
+ /\.onclose\s*=\s*\(?.*:\s*any/i,
191
+ /\.onmessage\s*=\s*\(?.*:\s*any/i,
192
+ /webSocket/i,
193
+ /WebSocket/i,
194
+ // WebRTC / PeerConnection
195
+ /\.onicecandidate\s*=\s*\(?.*:\s*any/i,
196
+ /\.ontrack\s*=\s*\(?.*:\s*any/i,
197
+ /\.onnegotiationneeded\s*=\s*\(?.*:\s*any/i,
198
+ /RTCPeerConnection/i,
199
+ /peerConnection/i,
200
+ // Generic browser event handlers with common event names
201
+ /\.(on[a-z]+)\s*=\s*\(\s*(?:event|e|evt)\s*:\s*any\s*\)\s*=>/i,
202
+ /addEventListener\s*\([^,]+,\s*\([^:]+:\s*any\)/i,
203
+ // React/UI library event handler patterns (Tiptap, ProseMirror, etc.)
204
+ /onStart\s*:\s*\(?.*:\s*any/i,
205
+ /onUpdate\s*:\s*\(?.*:\s*any/i,
206
+ /onTransaction\s*:\s*\(?.*:\s*any/i,
207
+ /onSelectionChange\s*:\s*\(?.*:\s*any/i,
208
+ /onBlur\s*:\s*\(?.*:\s*any/i,
209
+ /onFocus\s*:\s*\(?.*:\s*any/i,
210
+ /props\s*:\s*any/i, // Third-party library props (common workaround)
211
+ // Intersection Observer, Resize Observer, etc.
212
+ /IntersectionObserver/i,
213
+ /ResizeObserver/i,
214
+ /MutationObserver/i,
215
+ ];
216
+ return browserAPIPatterns.some(p => p.test(line));
217
+ }
218
+ /**
219
+ * Check if 'any' usage is on untrusted external input
220
+ */
221
+ function isUntrustedInputContext(line) {
222
+ const untrustedPatterns = [
223
+ // Request body/params parsing
224
+ /await\s+request\.json\s*\(\s*\)\s*as\s+any/i,
225
+ /req\.body\s+as\s+any/i,
226
+ /request\.body\s+as\s+any/i,
227
+ /req\.params\s+as\s+any/i,
228
+ /req\.query\s+as\s+any/i,
229
+ /event\.body\s+as\s+any/i,
230
+ // External API responses (if not validated)
231
+ /fetch\s*\([^)]+\).*as\s+any/i,
232
+ /axios\.[^)]+\).*as\s+any/i,
233
+ // Direct parameter typing without validation
234
+ /\(\s*\w+\s*:\s*any\s*\)\s*=>\s*\{/, // Arrow function with any param (if in API context)
235
+ ];
236
+ return untrustedPatterns.some(p => p.test(line));
237
+ }
238
+ /**
239
+ * Categorize TypeScript 'any' usage by security context
240
+ * Returns sorted list by priority (highest risk first)
241
+ */
242
+ function categorizeAnyUsage(lines, filePath) {
243
+ const usages = [];
244
+ const isAPIFile = /api|route|handler|controller|endpoint/.test(filePath.toLowerCase());
245
+ const isDBFile = /repository|model|database|query|prisma|supabase|dexie|db/.test(filePath.toLowerCase());
246
+ const isAuthFile = /auth|login|session|token|password|credential/.test(filePath.toLowerCase());
247
+ lines.forEach((line, idx) => {
248
+ // Skip if line doesn't contain 'any' type
249
+ if (!/:\s*any\b|<any>|as any/.test(line))
250
+ return;
251
+ // Skip comments
252
+ const trimmed = line.trim();
253
+ if (trimmed.startsWith('//') ||
254
+ trimmed.startsWith('/*') ||
255
+ trimmed.startsWith('*')) {
256
+ return;
257
+ }
258
+ // Skip safe ORM/database patterns (Dexie, Prisma, Supabase, internal array maps)
259
+ if (isSafeORMPattern(line)) {
260
+ return;
261
+ }
262
+ // Skip browser API event handlers (SpeechRecognition, MediaRecorder, WebSocket, etc.)
263
+ // These APIs often have incomplete TypeScript typings and 'any' is a legitimate workaround
264
+ if (isBrowserAPIEventHandler(line, filePath)) {
265
+ return;
266
+ }
267
+ let context = 'internal_util';
268
+ let priority = 1;
269
+ // Check if this is untrusted input (highest priority)
270
+ if (isUntrustedInputContext(line)) {
271
+ context = 'api_boundary';
272
+ priority = 10;
273
+ }
274
+ // API boundary detection - only if actually on untrusted data
275
+ else if (isAPIFile && /\b(req|request)\.(body|params|query|json)\b/.test(line)) {
276
+ context = 'api_boundary';
277
+ priority = 10;
278
+ }
279
+ // Auth handler detection (high priority for auth bypass)
280
+ else if (isAuthFile && /\b(password|token|session|auth|verify|jwt|credential)\b/i.test(line)) {
281
+ context = 'auth_handler';
282
+ priority = 9;
283
+ }
284
+ // Database layer - only flag if it's SQL string interpolation, not ORM methods
285
+ else if (isDBFile && /\.(execute|query|raw)\s*\(/i.test(line)) {
286
+ context = 'database_layer';
287
+ priority = 8;
288
+ }
289
+ // Type definitions (lowest priority - often unavoidable)
290
+ else if (/\btype\s+\w+|interface\s+\w+|declare\s+/.test(line)) {
291
+ context = 'type_definition';
292
+ priority = 1;
293
+ }
294
+ // Internal utilities / array operations on DB results (low priority, skip entirely for now)
295
+ else if (isDBFile || /\.map\s*\(|\.filter\s*\(|\.forEach\s*\(|\.reduce\s*\(/.test(line)) {
296
+ // Skip internal array operations - they're operating on already-fetched data
297
+ return;
298
+ }
299
+ // Other internal utilities
300
+ else {
301
+ context = 'internal_util';
302
+ priority = 3;
303
+ }
304
+ usages.push({
305
+ lineNumber: idx + 1,
306
+ lineContent: line.trim(),
307
+ context,
308
+ priority
309
+ });
310
+ });
311
+ // Sort by priority (highest first)
312
+ return usages.sort((a, b) => b.priority - a.priority);
313
+ }
314
+ /**
315
+ * Detect TypeScript 'any' usage at security boundaries ONLY
316
+ * Returns vulnerabilities for high-priority 'any' usage, capped at top 5 per file
317
+ */
318
+ function detectSmartAnyUsage(lines, filePath) {
319
+ const vulnerabilities = [];
320
+ // Only scan TypeScript files
321
+ if (!/\.(ts|tsx)$/.test(filePath)) {
322
+ return vulnerabilities;
323
+ }
324
+ // Categorize all 'any' usages by context
325
+ const anyUsageByContext = categorizeAnyUsage(lines, filePath);
326
+ // Only report high-priority 'any' usages (security boundaries)
327
+ const priorityAny = anyUsageByContext.filter(usage => usage.context === 'api_boundary' ||
328
+ usage.context === 'database_layer' ||
329
+ usage.context === 'auth_handler');
330
+ // Cap reporting to top 5 per file to avoid overwhelming reports
331
+ const cappedAny = priorityAny.slice(0, 5);
332
+ if (cappedAny.length === 0) {
333
+ return vulnerabilities;
334
+ }
335
+ // If there are many 'any' usages, create a grouped finding
336
+ if (cappedAny.length >= 3) {
337
+ // Create single grouped vulnerability
338
+ const contexts = [...new Set(cappedAny.map(a => a.context))];
339
+ const contextDescriptions = contexts.map(ctx => {
340
+ const count = cappedAny.filter(a => a.context === ctx).length;
341
+ const names = {
342
+ 'api_boundary': 'API request/response handlers',
343
+ 'database_layer': 'Database queries',
344
+ 'auth_handler': 'Authentication logic'
345
+ };
346
+ return `${count}x in ${names[ctx] || ctx}`;
347
+ });
348
+ vulnerabilities.push({
349
+ id: `ai-fingerprint-any-${filePath}`,
350
+ filePath,
351
+ lineNumber: cappedAny[0].lineNumber,
352
+ lineContent: `Multiple TypeScript 'any' usages at security boundaries`,
353
+ severity: 'low',
354
+ category: 'ai_pattern',
355
+ title: `[AI Pattern] TypeScript 'any' at security boundaries (${cappedAny.length} instances)`,
356
+ description: `Found ${cappedAny.length} 'any' types at critical security boundaries: ${contextDescriptions.join(', ')}. ` +
357
+ `Lines: ${cappedAny.map(a => a.lineNumber).join(', ')}. ` +
358
+ `Consider using explicit types for type safety and to prevent type confusion vulnerabilities.`,
359
+ suggestedFix: 'Replace "any" with explicit types. For request handlers use typed schemas (Zod, Yup). For database queries use typed ORM models.',
360
+ confidence: 'medium',
361
+ layer: 2,
362
+ });
363
+ }
364
+ else {
365
+ // Report individual findings for 1-2 high-priority 'any' usages
366
+ for (const usage of cappedAny) {
367
+ const contextNames = {
368
+ 'api_boundary': 'API request/response handler',
369
+ 'database_layer': 'Database query',
370
+ 'auth_handler': 'Authentication logic'
371
+ };
372
+ vulnerabilities.push({
373
+ id: `ai-fingerprint-any-${filePath}-${usage.lineNumber}`,
374
+ filePath,
375
+ lineNumber: usage.lineNumber,
376
+ lineContent: usage.lineContent,
377
+ severity: 'low',
378
+ category: 'ai_pattern',
379
+ title: `[AI Pattern] TypeScript 'any' in ${contextNames[usage.context] || usage.context}`,
380
+ description: `Using 'any' type at a security boundary bypasses type checking and can lead to type confusion vulnerabilities. ` +
381
+ `This is especially risky in ${contextNames[usage.context] || usage.context}.`,
382
+ suggestedFix: 'Replace "any" with an explicit type. Use typed request schemas, ORM models, or interface definitions.',
383
+ confidence: 'medium',
384
+ layer: 2,
385
+ });
386
+ }
387
+ }
388
+ return vulnerabilities;
389
+ }
390
+ /**
391
+ * Detect managed AI endpoints without rate limiting (cost abuse risk)
392
+ * Finds routes using provider env keys without rate limiting protection
393
+ */
394
+ function detectManagedAICostAbuse(content, filePath, lines) {
395
+ const vulnerabilities = [];
396
+ // Only check actual API route files, not utility/handler files
397
+ const isActualRouteFile = /\/(route|page)\.(ts|js|tsx|jsx)$/i.test(filePath) ||
398
+ /\/(api|routes?)\/.*\/index\.(ts|js)$/i.test(filePath);
399
+ // Files named as handlers, helpers, utils, fixtures etc. are NOT actual routes
400
+ const isUtilityFile = /(handler|helper|util|mock|test|fixture|safe|example|config)/i.test(filePath);
401
+ if (!isActualRouteFile || isUtilityFile)
402
+ return vulnerabilities;
403
+ // Check if file uses managed provider keys (from environment)
404
+ const managedKeyPatterns = [
405
+ /process\.env\.OPENAI_API_KEY/i,
406
+ /process\.env\.ANTHROPIC_API_KEY/i,
407
+ /process\.env\.\w*_(API_KEY|SECRET_KEY)/i,
408
+ /import\.meta\.env\.OPENAI/i,
409
+ /import\.meta\.env\.ANTHROPIC/i,
410
+ ];
411
+ const usesManagedKey = managedKeyPatterns.some(p => p.test(content));
412
+ if (!usesManagedKey)
413
+ return vulnerabilities;
414
+ // Skip if this is a config check (checking if key exists) rather than actual API usage
415
+ // Pattern: if (!process.env.OPENAI_API_KEY) or if (process.env.OPENAI_API_KEY === undefined)
416
+ const isConfigCheck = /if\s*\(\s*!?\s*process\.env\.\w*_API_KEY\s*[=!]|!process\.env\.\w*_API_KEY/i.test(content);
417
+ const hasActualAPICall = /\.chat\.completions|\.messages\.create|\.complete\(|anthropic\.\w+\(/i.test(content);
418
+ // If it's just a config check without actual API calls, skip
419
+ if (isConfigCheck && !hasActualAPICall)
420
+ return vulnerabilities;
421
+ // Check for rate limiting patterns nearby
422
+ const rateLimitPatterns = [
423
+ /rateLimit/i,
424
+ /rateLimiter/i,
425
+ /limiter/i,
426
+ /throttle/i,
427
+ /upstash.*ratelimit/i,
428
+ /redis.*limit/i,
429
+ /bucket/i,
430
+ /token.*bucket/i,
431
+ /sliding.*window/i,
432
+ /@upstash\/ratelimit/i,
433
+ /rate-limiter-flexible/i,
434
+ ];
435
+ const hasRateLimiting = rateLimitPatterns.some(p => p.test(content));
436
+ // Check for auth patterns - expanded to catch more middleware patterns
437
+ const authPatterns = [
438
+ /getServerSession/i,
439
+ /auth\(\)/i,
440
+ /auth\.protect/i,
441
+ /currentUser/i,
442
+ /getCurrentUser/i,
443
+ /getCurrentUserId/i,
444
+ /requireAuth/i,
445
+ /verifyToken/i,
446
+ /session\.user/i,
447
+ /authorization/i,
448
+ /withAuth/i,
449
+ /isAuthenticated/i,
450
+ /checkAuth/i,
451
+ /validateSession/i,
452
+ /clerk/i, // Clerk auth
453
+ /supabase.*auth/i, // Supabase auth
454
+ /nextauth/i, // NextAuth
455
+ /authMiddleware/i,
456
+ /protectedRoute/i,
457
+ /requireSession/i,
458
+ /userId.*=.*auth/i, // userId from auth
459
+ /user\.id/i, // Accessing user.id implies auth
460
+ ];
461
+ const hasAuth = authPatterns.some(p => p.test(content));
462
+ // Check if route is likely protected by middleware (file path based)
463
+ const isLikelyMiddlewareProtected = /\/api\/(protected|private|admin|user|account|dashboard)\//i.test(filePath) ||
464
+ /\/\(authenticated\)\//i.test(filePath) || // Next.js route groups
465
+ /\/\(protected\)\//i.test(filePath) ||
466
+ /\/\(auth\)\//i.test(filePath);
467
+ // Determine severity based on auth + rate limiting
468
+ if (!hasRateLimiting) {
469
+ // Find the line with the env key usage
470
+ let keyLine = 1;
471
+ for (let i = 0; i < lines.length; i++) {
472
+ if (managedKeyPatterns.some(p => p.test(lines[i]))) {
473
+ keyLine = i + 1;
474
+ break;
475
+ }
476
+ }
477
+ // If route is authenticated (inline or via middleware), this is just operational concern
478
+ if (hasAuth || isLikelyMiddlewareProtected) {
479
+ // Authenticated route without rate limiting - operational concern, not security vuln
480
+ vulnerabilities.push({
481
+ id: `ai-cost-abuse-${filePath}`,
482
+ filePath,
483
+ lineNumber: keyLine,
484
+ lineContent: lines[keyLine - 1]?.trim() || 'process.env.*_API_KEY',
485
+ severity: 'info',
486
+ category: 'ai_pattern',
487
+ title: 'Managed AI endpoint without rate limiting (authenticated)',
488
+ description: 'This authenticated API route uses a managed AI provider key but lacks rate limiting. Authenticated users could potentially abuse the endpoint. This is an operational concern, not a security vulnerability.',
489
+ suggestedFix: 'Consider adding per-user rate limiting (e.g., @upstash/ratelimit) to prevent cost abuse by authenticated users.',
490
+ confidence: 'low',
491
+ layer: 2,
492
+ });
493
+ }
494
+ else {
495
+ // Unauthenticated route - higher risk
496
+ vulnerabilities.push({
497
+ id: `ai-cost-abuse-${filePath}`,
498
+ filePath,
499
+ lineNumber: keyLine,
500
+ lineContent: lines[keyLine - 1]?.trim() || 'process.env.*_API_KEY',
501
+ severity: 'medium',
502
+ category: 'ai_pattern',
503
+ title: 'Managed AI endpoint without authentication or rate limiting',
504
+ description: 'This API route uses a managed AI provider key without apparent authentication or rate limiting. This could allow unauthenticated cost abuse.',
505
+ suggestedFix: 'Add authentication or rate limiting (e.g., @upstash/ratelimit, rate-limiter-flexible) to prevent cost abuse.',
506
+ confidence: 'medium',
507
+ layer: 2,
508
+ });
509
+ }
510
+ }
511
+ return vulnerabilities;
512
+ }
513
+ /**
514
+ * Check if line contains clearly placeholder credential values
515
+ */
516
+ function isPlaceholderCredential(line) {
517
+ const placeholderPatterns = [
518
+ /your[-_]?api[-_]?key/i,
519
+ /your[-_]?secret/i,
520
+ /your[-_]?password/i,
521
+ /replace[-_]?with/i,
522
+ /example[-_]?key/i,
523
+ /sample[-_]?key/i,
524
+ /demo[-_]?key/i,
525
+ /test[-_]?key/i,
526
+ /fake[-_]?key/i,
527
+ /mock[-_]?key/i,
528
+ /placeholder/i,
529
+ /<.*>/, // <YOUR_KEY>
530
+ /\[.*\]/, // [API_KEY]
531
+ /xxx+/i,
532
+ ];
533
+ return placeholderPatterns.some(p => p.test(line));
534
+ }
535
+ /**
536
+ * Check if file path indicates a config/settings file
537
+ */
538
+ function isConfigFile(filePath) {
539
+ const lowerPath = filePath.toLowerCase();
540
+ return /config|settings|constants|urls|endpoints|env/i.test(lowerPath);
541
+ }
542
+ function detectAIFingerprints(content, filePath) {
543
+ const vulnerabilities = [];
544
+ const lines = content.split('\n');
545
+ // Skip example/demo files entirely - they contain placeholder code by design
546
+ if ((0, context_helpers_1.isExampleFile)(filePath)) {
547
+ return vulnerabilities;
548
+ }
549
+ const isTestFile = (0, context_helpers_1.isTestOrMockFile)(filePath);
550
+ const isConfigOrSettings = isConfigFile(filePath);
551
+ // First, run smart 'any' detection (TypeScript files only, context-aware)
552
+ const anyVulns = detectSmartAnyUsage(lines, filePath);
553
+ vulnerabilities.push(...anyVulns);
554
+ // Detect managed AI cost abuse risk
555
+ const costAbuseVulns = detectManagedAICostAbuse(content, filePath, lines);
556
+ vulnerabilities.push(...costAbuseVulns);
557
+ // Track AI pattern density for file-level assessment
558
+ let aiPatternCount = 0;
559
+ lines.forEach((line, index) => {
560
+ for (const fingerprint of AI_FINGERPRINTS) {
561
+ const regex = new RegExp(fingerprint.pattern.source, fingerprint.pattern.flags);
562
+ if (regex.test(line)) {
563
+ // Skip placeholder/example credentials for the "AI example credentials" pattern
564
+ if (fingerprint.name === 'AI example credentials') {
565
+ if (isPlaceholderCredential(line) || (0, context_helpers_1.isPlaceholderValue)('', line) || isTestFile) {
566
+ continue; // Skip this pattern, check others
567
+ }
568
+ }
569
+ aiPatternCount++;
570
+ // Downgrade severity for test files
571
+ let severity = fingerprint.severity;
572
+ let confidence = fingerprint.confidence;
573
+ if (isTestFile) {
574
+ if (severity === 'critical')
575
+ severity = 'medium';
576
+ else if (severity === 'high')
577
+ severity = 'low';
578
+ else
579
+ severity = 'info';
580
+ confidence = 'low';
581
+ }
582
+ vulnerabilities.push({
583
+ id: `ai-fingerprint-${filePath}-${index + 1}-${fingerprint.name}`,
584
+ filePath,
585
+ lineNumber: index + 1,
586
+ lineContent: line.trim(),
587
+ severity,
588
+ category: 'ai_pattern',
589
+ title: `[AI Pattern] ${fingerprint.name}`,
590
+ description: fingerprint.description + (isTestFile ? ' (in test file)' : ''),
591
+ suggestedFix: fingerprint.suggestedFix,
592
+ confidence,
593
+ layer: 2,
594
+ });
595
+ break; // Only report once per line
596
+ }
597
+ }
598
+ });
599
+ // Context-aware localhost/example URL detection
600
+ // Skip for config files and test files (they legitimately contain example URLs)
601
+ if (!isConfigOrSettings && !isTestFile) {
602
+ const localhostPattern = /['"]https?:\/\/(localhost|127\.0\.0\.1|example\.com|your-domain|api\.example)[^'"]*['"]/gi;
603
+ lines.forEach((line, index) => {
604
+ if (localhostPattern.test(line)) {
605
+ // Reset regex state
606
+ localhostPattern.lastIndex = 0;
607
+ // Skip if it's a comment
608
+ const trimmed = line.trim();
609
+ if (trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('*')) {
610
+ return;
611
+ }
612
+ // Skip if it looks like env var fallback (process.env.X || "http://localhost")
613
+ if (/process\.env\.\w+\s*\|\|\s*['"]/.test(line)) {
614
+ return;
615
+ }
616
+ vulnerabilities.push({
617
+ id: `ai-fingerprint-${filePath}-${index + 1}-localhost-url`,
618
+ filePath,
619
+ lineNumber: index + 1,
620
+ lineContent: line.trim(),
621
+ severity: 'medium',
622
+ category: 'ai_pattern',
623
+ title: '[AI Pattern] AI localhost/example URL',
624
+ description: 'Placeholder URL that should be replaced with actual endpoint',
625
+ suggestedFix: 'Replace with actual production URL from environment variable',
626
+ confidence: 'high',
627
+ layer: 2,
628
+ });
629
+ aiPatternCount++;
630
+ }
631
+ });
632
+ }
633
+ // If file has high density of AI patterns, add a summary finding
634
+ const lineCount = lines.length;
635
+ const aiDensity = aiPatternCount / Math.max(lineCount, 1);
636
+ // Raised threshold to 10% and require high-severity patterns to reduce noise
637
+ if (aiDensity > 0.10 && aiPatternCount >= 5) {
638
+ vulnerabilities.push({
639
+ id: `ai-fingerprint-${filePath}-summary`,
640
+ filePath,
641
+ lineNumber: 1,
642
+ lineContent: `File contains ${aiPatternCount} AI-generated code patterns`,
643
+ severity: 'medium',
644
+ category: 'ai_pattern',
645
+ title: '[AI Pattern] High AI-generated code density',
646
+ description: `This file shows ${aiPatternCount} patterns commonly found in AI-generated code. Consider a thorough security review.`,
647
+ suggestedFix: 'Review this file carefully for security issues, incomplete implementations, and placeholder code',
648
+ confidence: 'medium',
649
+ layer: 2,
650
+ });
651
+ }
652
+ return vulnerabilities;
653
+ }
654
+ //# sourceMappingURL=ai-fingerprinting.js.map