@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,177 @@
1
+ /**
2
+ * Tier System Integration Test
3
+ *
4
+ * This test validates that the detector tier system correctly filters
5
+ * findings based on scan depth (cheap/validated/deep).
6
+ *
7
+ * Run with: npx tsx src/lib/scanner/__tests__/tier-integration.test.ts
8
+ */
9
+
10
+ import { runLayer1Scan } from '../layer1'
11
+ import { runLayer2Scan } from '../layer2'
12
+ import type { ScanFile, Vulnerability } from '../types'
13
+ import {
14
+ getTierForCategory,
15
+ computeTierStats,
16
+ formatTierStats,
17
+ LAYER1_DETECTOR_TIERS,
18
+ LAYER2_DETECTOR_TIERS,
19
+ } from '../tiers'
20
+
21
+ // Mock files with various vulnerability patterns
22
+ const mockFiles: ScanFile[] = [
23
+ {
24
+ path: 'src/api/auth/route.ts',
25
+ content: `
26
+ // Tier A: Known secret (patterns.ts)
27
+ const API_KEY = "sk-ant-api03-abc123xyz456"
28
+
29
+ // Tier A: Dangerous function (dangerous-functions.ts)
30
+ const result = eval(userInput)
31
+
32
+ // Tier B: High entropy (entropy.ts)
33
+ const token = "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9"
34
+
35
+ // Tier C: Sensitive variable (variables.ts)
36
+ const password = getPassword()
37
+
38
+ // Tier C: Logic gate (logic-gates.ts)
39
+ if (isAdmin || bypassAuth) {
40
+ allowAccess()
41
+ }
42
+ `,
43
+ language: 'typescript',
44
+ size: 500,
45
+ },
46
+ {
47
+ path: 'src/lib/ai/client.ts',
48
+ content: `
49
+ // Tier A: AI execution sink (ai-execution-sinks.ts)
50
+ const code = await openai.chat.completions.create({
51
+ model: "gpt-4",
52
+ messages: [{ role: "user", content: prompt }]
53
+ })
54
+ eval(code.choices[0].message.content)
55
+
56
+ // Tier B: AI fingerprint (ai-fingerprinting.ts)
57
+ function processData(data: any): any {
58
+ return data
59
+ }
60
+
61
+ // Tier A: BYOK pattern (byok-patterns.ts)
62
+ const apiKey = request.headers.get('x-api-key')
63
+ await client.chat({
64
+ apiKey: apiKey,
65
+ messages: []
66
+ })
67
+ `,
68
+ language: 'typescript',
69
+ size: 400,
70
+ },
71
+ ]
72
+
73
+ async function runTest() {
74
+ console.log('='.repeat(60))
75
+ console.log('Tier System Integration Test')
76
+ console.log('='.repeat(60))
77
+
78
+ // Display tier mappings
79
+ console.log('\n📋 Layer 1 Detector Tiers:')
80
+ for (const [detector, tier] of Object.entries(LAYER1_DETECTOR_TIERS)) {
81
+ console.log(` - ${detector}: ${tier}`)
82
+ }
83
+
84
+ console.log('\n📋 Layer 2 Detector Tiers:')
85
+ for (const [detector, tier] of Object.entries(LAYER2_DETECTOR_TIERS)) {
86
+ console.log(` - ${detector}: ${tier}`)
87
+ }
88
+
89
+ // Run Layer 1
90
+ console.log('\n' + '='.repeat(60))
91
+ console.log('Running Layer 1 Scan...')
92
+ console.log('='.repeat(60))
93
+
94
+ const layer1Result = await runLayer1Scan(mockFiles)
95
+ console.log(`\nLayer 1 found ${layer1Result.vulnerabilities.length} vulnerabilities`)
96
+ console.log(`Tier stats: ${formatTierStats(layer1Result.stats.tiers)}`)
97
+
98
+ // Group Layer 1 findings by tier
99
+ const layer1ByTier = groupByTier(layer1Result.vulnerabilities)
100
+ console.log('\nLayer 1 by tier:')
101
+ console.log(` - Core (A): ${layer1ByTier.core.length} findings`)
102
+ console.log(` - AI-Assisted (B): ${layer1ByTier.ai_assisted.length} findings`)
103
+ console.log(` - Experimental (C): ${layer1ByTier.experimental.length} findings`)
104
+
105
+ // Run Layer 2
106
+ console.log('\n' + '='.repeat(60))
107
+ console.log('Running Layer 2 Scan...')
108
+ console.log('='.repeat(60))
109
+
110
+ const layer2Result = await runLayer2Scan(mockFiles)
111
+ console.log(`\nLayer 2 found ${layer2Result.vulnerabilities.length} vulnerabilities`)
112
+ console.log(`Tier stats: ${formatTierStats(layer2Result.stats.tiers)}`)
113
+
114
+ // Group Layer 2 findings by tier
115
+ const layer2ByTier = groupByTier(layer2Result.vulnerabilities)
116
+ console.log('\nLayer 2 by tier:')
117
+ console.log(` - Core (A): ${layer2ByTier.core.length} findings`)
118
+ console.log(` - AI-Assisted (B): ${layer2ByTier.ai_assisted.length} findings`)
119
+ console.log(` - Experimental (C): ${layer2ByTier.experimental.length} findings`)
120
+
121
+ // Print all findings with their tiers
122
+ console.log('\n' + '='.repeat(60))
123
+ console.log('All Findings with Tier Classification')
124
+ console.log('='.repeat(60))
125
+
126
+ const allFindings = [...layer1Result.vulnerabilities, ...layer2Result.vulnerabilities]
127
+ for (const finding of allFindings) {
128
+ const tier = getTierForCategory(finding.category, finding.layer)
129
+ console.log(`\n[${tier.toUpperCase()}] ${finding.title}`)
130
+ console.log(` Category: ${finding.category}`)
131
+ console.log(` Layer: ${finding.layer}`)
132
+ console.log(` Severity: ${finding.severity}`)
133
+ console.log(` File: ${finding.filePath}:${finding.lineNumber}`)
134
+ }
135
+
136
+ // Summary
137
+ console.log('\n' + '='.repeat(60))
138
+ console.log('Scan Depth Behavior Summary')
139
+ console.log('='.repeat(60))
140
+
141
+ const totalStats = computeTierStats(
142
+ allFindings.map(v => ({ category: v.category, layer: v.layer }))
143
+ )
144
+
145
+ console.log(`\nTotal findings: ${allFindings.length}`)
146
+ console.log(` ${formatTierStats(totalStats)}`)
147
+
148
+ console.log('\nBehavior by scan depth:')
149
+ console.log(` • cheap: Would surface ${totalStats.core} findings (Tier A only)`)
150
+ console.log(` • validated: Would surface ${totalStats.core} + up to ${totalStats.ai_assisted} (after AI validation)`)
151
+ console.log(` • deep: Same as validated + Layer 3 semantic analysis`)
152
+ console.log(` • hidden: ${totalStats.experimental} findings never surfaced (Tier C)`)
153
+
154
+ console.log('\n✅ Test completed successfully!')
155
+ }
156
+
157
+ function groupByTier(vulnerabilities: Vulnerability[]): {
158
+ core: Vulnerability[]
159
+ ai_assisted: Vulnerability[]
160
+ experimental: Vulnerability[]
161
+ } {
162
+ const result = { core: [], ai_assisted: [], experimental: [] } as {
163
+ core: Vulnerability[]
164
+ ai_assisted: Vulnerability[]
165
+ experimental: Vulnerability[]
166
+ }
167
+
168
+ for (const vuln of vulnerabilities) {
169
+ const tier = getTierForCategory(vuln.category, vuln.layer)
170
+ result[tier].push(vuln)
171
+ }
172
+
173
+ return result
174
+ }
175
+
176
+ // Run the test
177
+ runTest().catch(console.error)
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Shared types for the security benchmark test suite
3
+ */
4
+
5
+ import type { ScanFile, Vulnerability, VulnerabilityCategory, VulnerabilitySeverity } from '../../types'
6
+
7
+ /**
8
+ * A test fixture containing a file to scan and expected results
9
+ */
10
+ export interface TestFixture {
11
+ /** Descriptive name for the test */
12
+ name: string
13
+ /** The file to scan */
14
+ file: ScanFile
15
+ /** Whether findings are expected (true positive test) or not (false negative test) */
16
+ expectFindings: boolean
17
+ /** Categories expected to be found (for true positive tests) */
18
+ expectedCategories?: VulnerabilityCategory[]
19
+ /** Description of what this test validates */
20
+ description?: string
21
+ /**
22
+ * For false negative tests: Allow specific low-severity findings
23
+ * Some edge cases may generate info findings (e.g., test files with eval())
24
+ * By default, false negative tests fail on medium+ severity
25
+ */
26
+ allowedInfoFindings?: {
27
+ category: VulnerabilityCategory
28
+ maxCount: number
29
+ reason: string
30
+ }[]
31
+ }
32
+
33
+ /**
34
+ * Result from running a single test
35
+ */
36
+ export interface TestResult {
37
+ name: string
38
+ file: ScanFile
39
+ layer1Findings: Vulnerability[]
40
+ layer2Findings: Vulnerability[]
41
+ expectedCategories: VulnerabilityCategory[]
42
+ unexpectedCategories: VulnerabilityCategory[]
43
+ passed: boolean
44
+ failureReason?: string
45
+ /** Findings that were unexpected but acceptable (info severity) */
46
+ acceptableInfoFindings?: Vulnerability[]
47
+ /** Findings that caused the test to fail (medium+) */
48
+ problematicFindings?: Vulnerability[]
49
+ }
50
+
51
+ /**
52
+ * A group of related test fixtures
53
+ */
54
+ export interface TestGroup {
55
+ /** Name of the test group (e.g., "Hardcoded Secrets") */
56
+ name: string
57
+ /** Tier classification */
58
+ tier: 'A' | 'B' | 'C'
59
+ /** Layer this test group primarily targets */
60
+ layer: 1 | 2
61
+ /** Description of the test group */
62
+ description: string
63
+ /** True positive test fixtures */
64
+ truePositives: TestFixture[]
65
+ /** False negative test fixtures (should NOT flag) */
66
+ falseNegatives: TestFixture[]
67
+ }
68
+
69
+ /**
70
+ * Detector performance metrics
71
+ */
72
+ export interface DetectorMetrics {
73
+ /** Detector/category name */
74
+ name: string
75
+ /** True positives detected */
76
+ truePositives: number
77
+ /** False positives (unexpected findings on safe code) */
78
+ falsePositives: number
79
+ /** False negatives (missed detections) */
80
+ falseNegatives: number
81
+ /** Precision: TP / (TP + FP) */
82
+ precision: number
83
+ /** Recall: TP / (TP + FN) */
84
+ recall: number
85
+ }
86
+
87
+ /**
88
+ * Severity distribution metrics
89
+ */
90
+ export interface SeverityMetrics {
91
+ critical: number
92
+ high: number
93
+ medium: number
94
+ low: number
95
+ info: number
96
+ }
97
+
98
+ /**
99
+ * Detailed benchmark metrics
100
+ */
101
+ export interface BenchmarkMetrics {
102
+ /** Overall detection statistics */
103
+ detection: {
104
+ totalVulnerabilitiesDetected: number
105
+ truePositiveDetections: number
106
+ falsePositiveDetections: number
107
+ missedVulnerabilities: number
108
+ }
109
+ /** Performance by detector/category */
110
+ byDetector: DetectorMetrics[]
111
+ /** Severity distribution of all findings */
112
+ severityDistribution: SeverityMetrics
113
+ /** Severity distribution of false positives */
114
+ falsePositiveSeverity: SeverityMetrics
115
+ /** Coverage statistics */
116
+ coverage: {
117
+ totalCategories: number
118
+ categoriesTested: number
119
+ coveragePercent: number
120
+ untestedCategories: string[]
121
+ }
122
+ /** Tier statistics */
123
+ byTier: {
124
+ tierA: { tested: number; passed: number }
125
+ tierB: { tested: number; passed: number }
126
+ tierC: { tested: number; passed: number }
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Summary of benchmark results
132
+ */
133
+ export interface BenchmarkSummary {
134
+ truePositivePassed: number
135
+ truePositiveFailed: number
136
+ falseNegativePassed: number
137
+ falseNegativeFailed: number
138
+ totalTests: number
139
+ passedTests: number
140
+ passRate: number
141
+ results: TestResult[]
142
+ /** Detailed performance metrics */
143
+ metrics: BenchmarkMetrics
144
+ }