@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,346 @@
1
+ /**
2
+ * Framework-Specific Checks Test Fixtures
3
+ * Tests for detecting framework-specific security issues
4
+ */
5
+
6
+ import type { TestGroup } from '../../types'
7
+
8
+ export const frameworkChecksTests: TestGroup = {
9
+ name: 'Framework-Specific Security',
10
+ tier: 'C',
11
+ layer: 2,
12
+ description: 'Detection of framework-specific security issues (Next.js, Express, React, Django, Flask)',
13
+
14
+ truePositives: [
15
+ {
16
+ name: 'Next.js Security Issues',
17
+ expectFindings: true,
18
+ expectedCategories: ['insecure_config'],
19
+ description: 'Next.js specific security issues that MUST be detected',
20
+ file: {
21
+ path: 'src/app/api/data/route.ts',
22
+ content: `
23
+ import { NextResponse } from 'next/server'
24
+ import { redirect, revalidatePath } from 'next/navigation'
25
+
26
+ // Next.js API route handler without auth check - MEDIUM
27
+ export default async function handler(req: any, res: any) {
28
+ const data = await fetchSensitiveData()
29
+ return res.json(data)
30
+ }
31
+
32
+ // Server action publicly accessible - MEDIUM
33
+ 'use server';
34
+ export async function submitForm(data: FormData) {
35
+ await db.insert(data)
36
+ }
37
+
38
+ // revalidatePath with user input - HIGH
39
+ export async function updateCache(request: Request) {
40
+ const { path } = await request.json()
41
+ revalidatePath(request.url)
42
+ revalidatePath(params.path)
43
+ }
44
+
45
+ // redirect with user input - HIGH
46
+ export async function handleLogin(searchParams: { redirect: string }) {
47
+ redirect(searchParams.redirect)
48
+ redirect(url.pathname)
49
+ redirect(request.nextUrl.pathname)
50
+ }
51
+
52
+ // getServerSideProps without auth - LOW
53
+ export async function getServerSideProps(context: any) {
54
+ const data = await fetchData()
55
+ return { props: { data } }
56
+ }
57
+
58
+ // unstable_cache without tags
59
+ import { unstable_cache } from 'next/cache'
60
+ const getCachedData = unstable_cache(async () => {
61
+ return fetchData()
62
+ })
63
+ `,
64
+ language: 'typescript',
65
+ size: 900,
66
+ },
67
+ },
68
+ {
69
+ name: 'Express Security Issues',
70
+ expectFindings: true,
71
+ expectedCategories: ['insecure_config'],
72
+ description: 'Express specific security issues that MUST be detected',
73
+ file: {
74
+ path: 'src/server/app.ts',
75
+ content: `
76
+ import express from 'express'
77
+ import cors from 'cors'
78
+ import bodyParser from 'body-parser'
79
+
80
+ const app = express()
81
+
82
+ // Express without helmet - MEDIUM
83
+ const server = express()
84
+ // No helmet middleware added
85
+
86
+ // CORS allow all origins - HIGH
87
+ app.use(cors({
88
+ origin: '*',
89
+ credentials: true,
90
+ }))
91
+
92
+ // Body parser without limit - LOW
93
+ app.use(bodyParser.json())
94
+ app.use(bodyParser.urlencoded())
95
+
96
+ // Trust proxy without verification - MEDIUM
97
+ app.set('trust proxy', true)
98
+
99
+ // Error handler exposes stack - HIGH
100
+ app.use((err, req, res, next) => {
101
+ res.json({
102
+ error: err.message,
103
+ stack: err.stack, // Stack trace exposed!
104
+ })
105
+ })
106
+
107
+ // Another stack exposure pattern
108
+ app.get('/error', (req, res) => {
109
+ try {
110
+ throw new Error('Oops')
111
+ } catch (err) {
112
+ res.send({ stack: err.stack })
113
+ }
114
+ })
115
+ `,
116
+ language: 'typescript',
117
+ size: 700,
118
+ },
119
+ },
120
+ {
121
+ name: 'React Security Issues',
122
+ expectFindings: true,
123
+ expectedCategories: ['insecure_config'],
124
+ description: 'React specific security issues that MUST be detected',
125
+ file: {
126
+ path: 'src/components/Form.tsx',
127
+ content: `
128
+ import { useState, useEffect } from 'react'
129
+
130
+ // useEffect with async (memory leak) - LOW
131
+ function Component() {
132
+ useEffect(async () => {
133
+ const data = await fetchData()
134
+ setData(data)
135
+ }, [])
136
+
137
+ // State with sensitive data - MEDIUM
138
+ const [password, setPassword] = useState('initial-password')
139
+ const [secret, setSecret] = useState('')
140
+ const [token, setToken] = useState('')
141
+ const [apiKey, setApiKey] = useState('')
142
+ const [api_key, setApiKey2] = useState('')
143
+
144
+ // href javascript: XSS - HIGH
145
+ return (
146
+ <div>
147
+ <a href="javascript:alert('xss')">Click me</a>
148
+ <a href='javascript:void(0)'>Another</a>
149
+ </div>
150
+ )
151
+ }
152
+
153
+ // Uncontrolled input with sensitive defaultValue - MEDIUM
154
+ function LoginForm({ savedPassword }) {
155
+ return (
156
+ <input
157
+ type="password"
158
+ defaultValue={password}
159
+ />
160
+ )
161
+ }
162
+
163
+ function TokenForm({ savedToken }) {
164
+ return <input defaultValue={token} />
165
+ }
166
+ `,
167
+ language: 'typescript',
168
+ size: 750,
169
+ },
170
+ },
171
+ {
172
+ name: 'Django/Flask Security Issues',
173
+ expectFindings: true,
174
+ expectedCategories: ['insecure_config'],
175
+ description: 'Python framework security issues that MUST be detected',
176
+ file: {
177
+ path: 'src/settings.py',
178
+ content: `
179
+ from django.conf import settings
180
+
181
+ # Django DEBUG in production - CRITICAL
182
+ DEBUG = True
183
+
184
+ # ALLOWED_HOSTS wildcard - HIGH
185
+ ALLOWED_HOSTS = ['*']
186
+
187
+ # Django SECRET_KEY hardcoded - CRITICAL
188
+ SECRET_KEY = 'django-insecure-abc123def456ghi789jkl'
189
+
190
+ # ========== Flask patterns ==========
191
+
192
+ from flask import Flask
193
+
194
+ app = Flask(__name__)
195
+
196
+ # Flask debug mode - CRITICAL
197
+ app.run(debug=True, host='0.0.0.0')
198
+
199
+ # Flask secret key hardcoded - CRITICAL
200
+ app.secret_key = 'super-secret-flask-key'
201
+ `,
202
+ language: 'python',
203
+ size: 500,
204
+ },
205
+ },
206
+ ],
207
+
208
+ falseNegatives: [
209
+ {
210
+ name: 'Framework Checks - False Negatives',
211
+ expectFindings: false,
212
+ description: 'Safe framework patterns that should NOT be flagged',
213
+ allowedInfoFindings: [
214
+ {
215
+ category: 'insecure_config',
216
+ maxCount: 2,
217
+ reason: 'Some framework patterns may still generate low-severity findings',
218
+ },
219
+ {
220
+ category: 'ai_pattern',
221
+ maxCount: 2,
222
+ reason: 'Framework patterns may trigger AI detection',
223
+ },
224
+ {
225
+ category: 'data_exposure',
226
+ maxCount: 2,
227
+ reason: 'Error handling patterns may trigger data exposure detection',
228
+ },
229
+ {
230
+ category: 'sensitive_url',
231
+ maxCount: 2,
232
+ reason: 'URLs in CORS config may trigger URL detection',
233
+ },
234
+ ],
235
+ file: {
236
+ path: 'src/config/server-config.ts',
237
+ content: `
238
+ // Server configuration with proper defaults - SAFE
239
+ export const serverConfig = {
240
+ port: process.env.PORT || 3000,
241
+ host: process.env.HOST || 'localhost',
242
+ bodyLimit: '100kb',
243
+ }
244
+ `,
245
+ language: 'typescript',
246
+ size: 150,
247
+ },
248
+ },
249
+ {
250
+ name: 'Safe Python Framework Patterns',
251
+ expectFindings: false,
252
+ description: 'Safe Django/Flask patterns that should NOT be flagged',
253
+ allowedInfoFindings: [
254
+ {
255
+ category: 'insecure_config',
256
+ maxCount: 2,
257
+ reason: 'Environment checks may still generate low-severity findings',
258
+ },
259
+ {
260
+ category: 'sensitive_variable',
261
+ maxCount: 2,
262
+ reason: 'Variable names like SECRET_KEY may trigger sensitive variable detection',
263
+ },
264
+ ],
265
+ file: {
266
+ path: 'src/safe_settings.py',
267
+ content: `
268
+ import os
269
+ from django.conf import settings
270
+
271
+ # DEBUG from environment - SAFE
272
+ DEBUG = os.environ.get('DEBUG', 'False') == 'True'
273
+
274
+ # ALLOWED_HOSTS from environment - SAFE
275
+ ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')
276
+
277
+ # SECRET_KEY from environment - SAFE
278
+ SECRET_KEY = os.environ.get('SECRET_KEY')
279
+ SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
280
+
281
+ # ========== Safe Flask patterns ==========
282
+
283
+ from flask import Flask
284
+
285
+ app = Flask(__name__)
286
+
287
+ # Debug from environment - SAFE
288
+ app.run(debug=os.environ.get('FLASK_DEBUG') == 'true')
289
+
290
+ # Secret key from environment - SAFE
291
+ app.secret_key = os.environ.get('SECRET_KEY')
292
+ app.config['SECRET_KEY'] = os.getenv('FLASK_SECRET')
293
+ `,
294
+ language: 'python',
295
+ size: 500,
296
+ },
297
+ },
298
+ {
299
+ name: 'Safe React Patterns',
300
+ expectFindings: false,
301
+ description: 'Safe React patterns that should NOT be flagged',
302
+ allowedInfoFindings: [
303
+ {
304
+ category: 'insecure_config',
305
+ maxCount: 1,
306
+ reason: 'Some patterns may generate info findings',
307
+ },
308
+ {
309
+ category: 'sensitive_url',
310
+ maxCount: 2,
311
+ reason: 'URLs in href may trigger URL detection',
312
+ },
313
+ {
314
+ category: 'sensitive_variable',
315
+ maxCount: 2,
316
+ reason: 'Variable names like password may trigger sensitive variable detection',
317
+ },
318
+ ],
319
+ file: {
320
+ path: 'src/components/SafeForm.tsx',
321
+ content: `
322
+ import { useState, useEffect } from 'react'
323
+
324
+ // Proper useEffect with async - SAFE
325
+ function Component() {
326
+ useEffect(() => {
327
+ loadData()
328
+ }, [])
329
+
330
+ // Non-sensitive state - SAFE
331
+ const [name, setName] = useState('')
332
+
333
+ return (
334
+ <div>
335
+ <a href="/dashboard">Dashboard</a>
336
+ <button onClick={handleClick}>Click</button>
337
+ </div>
338
+ )
339
+ }
340
+ `,
341
+ language: 'typescript',
342
+ size: 300,
343
+ },
344
+ },
345
+ ],
346
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Layer 2 Test Fixtures Index
3
+ * Exports all Layer 2 (Structural Scan) test fixtures
4
+ */
5
+
6
+ export { dangerousFunctionsTests } from './dangerous-functions'
7
+ export { byokTests } from './byok-patterns'
8
+ export { aiExecutionSinksTests } from './ai-execution-sinks'
9
+ export { aiAgentToolsTests } from './ai-agent-tools'
10
+ export { authAntipatternsTests } from './auth-antipatterns'
11
+ export { aiPromptHygieneTests } from './ai-prompt-hygiene'
12
+ export { dataExposureTests } from './data-exposure'
13
+ export { injectionTests } from './injection-vulnerabilities'
14
+ // M5: New AI-era detector fixtures
15
+ export { aiRagSafetyTests } from './ai-rag-safety'
16
+ export { aiEndpointProtectionTests } from './ai-endpoint-protection'
17
+ export { aiSchemaValidationTests } from './ai-schema-validation'
18
+ // M6: New Layer 2 fixtures (5 untested detectors)
19
+ export { aiFingerprintingTests } from './ai-fingerprinting'
20
+ export { logicGatesTests } from './logic-gates'
21
+ export { sensitiveVariablesTests } from './variables'
22
+ export { riskyImportsTests } from './risky-imports'
23
+ export { frameworkChecksTests } from './framework-checks'
24
+
25
+ import type { TestGroup } from '../../types'
26
+ import { dangerousFunctionsTests } from './dangerous-functions'
27
+ import { byokTests } from './byok-patterns'
28
+ import { aiExecutionSinksTests } from './ai-execution-sinks'
29
+ import { aiAgentToolsTests } from './ai-agent-tools'
30
+ import { authAntipatternsTests } from './auth-antipatterns'
31
+ import { aiPromptHygieneTests } from './ai-prompt-hygiene'
32
+ import { dataExposureTests } from './data-exposure'
33
+ import { injectionTests } from './injection-vulnerabilities'
34
+ // M5: New AI-era detector fixtures
35
+ import { aiRagSafetyTests } from './ai-rag-safety'
36
+ import { aiEndpointProtectionTests } from './ai-endpoint-protection'
37
+ import { aiSchemaValidationTests } from './ai-schema-validation'
38
+ // M6: New Layer 2 fixtures (5 untested detectors)
39
+ import { aiFingerprintingTests } from './ai-fingerprinting'
40
+ import { logicGatesTests } from './logic-gates'
41
+ import { sensitiveVariablesTests } from './variables'
42
+ import { riskyImportsTests } from './risky-imports'
43
+ import { frameworkChecksTests } from './framework-checks'
44
+
45
+ /**
46
+ * All Layer 2 test groups
47
+ */
48
+ export const layer2TestGroups: TestGroup[] = [
49
+ dangerousFunctionsTests,
50
+ byokTests,
51
+ aiExecutionSinksTests,
52
+ aiAgentToolsTests,
53
+ authAntipatternsTests,
54
+ aiPromptHygieneTests,
55
+ dataExposureTests,
56
+ injectionTests,
57
+ // M5: New AI-era detectors
58
+ aiRagSafetyTests,
59
+ aiEndpointProtectionTests,
60
+ aiSchemaValidationTests,
61
+ // M6: New Layer 2 fixtures (5 untested detectors)
62
+ aiFingerprintingTests,
63
+ logicGatesTests,
64
+ sensitiveVariablesTests,
65
+ riskyImportsTests,
66
+ frameworkChecksTests,
67
+ ]
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Injection Vulnerabilities Test Fixtures
3
+ * Comprehensive tests for SQL injection, XSS, command injection, and template injection
4
+ */
5
+
6
+ import type { TestGroup } from '../../types'
7
+
8
+ export const injectionTests: TestGroup = {
9
+ name: 'Injection Vulnerabilities',
10
+ tier: 'A',
11
+ layer: 2,
12
+ description: 'Comprehensive detection of SQL injection, XSS, command injection, and template injection',
13
+
14
+ truePositives: [
15
+ {
16
+ name: 'SQL Injection - Various Patterns',
17
+ expectFindings: true,
18
+ expectedCategories: ['dangerous_function'],
19
+ description: 'Various SQL injection patterns across different frameworks',
20
+ file: {
21
+ path: 'src/api/sql-injection.ts',
22
+ content: `
23
+ // Basic string concatenation
24
+ export async function getUserByName(name: string) {
25
+ return db.query("SELECT * FROM users WHERE name = '" + name + "'")
26
+ }
27
+
28
+ // Template literal injection
29
+ export async function searchProducts(term: string) {
30
+ return db.query(\`SELECT * FROM products WHERE name LIKE '%\${term}%'\`)
31
+ }
32
+
33
+ // ORDER BY injection (often overlooked)
34
+ export async function getSortedUsers(sortColumn: string) {
35
+ return db.query(\`SELECT * FROM users ORDER BY \${sortColumn}\`)
36
+ }
37
+
38
+ // LIMIT/OFFSET injection
39
+ export async function getPaginatedData(limit: string, offset: string) {
40
+ return db.query(\`SELECT * FROM items LIMIT \${limit} OFFSET \${offset}\`)
41
+ }
42
+
43
+ // IN clause injection
44
+ export async function getUsersByIds(ids: string) {
45
+ return db.query(\`SELECT * FROM users WHERE id IN (\${ids})\`)
46
+ }
47
+
48
+ // Table name injection
49
+ export async function getFromTable(tableName: string, id: string) {
50
+ return db.query(\`SELECT * FROM \${tableName} WHERE id = '\${id}'\`)
51
+ }
52
+
53
+ // Multi-statement injection
54
+ export async function updateAndSelect(userId: string, newName: string) {
55
+ const query = \`UPDATE users SET name = '\${newName}' WHERE id = '\${userId}'; SELECT * FROM users\`
56
+ return db.query(query)
57
+ }
58
+
59
+ // Stored procedure injection
60
+ export async function callProcedure(procName: string, param: string) {
61
+ return db.query(\`CALL \${procName}('\${param}')\`)
62
+ }
63
+ `,
64
+ language: 'typescript',
65
+ size: 1200,
66
+ },
67
+ },
68
+ {
69
+ name: 'XSS - Various Patterns',
70
+ expectFindings: true,
71
+ expectedCategories: ['dangerous_function'],
72
+ description: 'Various XSS patterns in different contexts',
73
+ file: {
74
+ path: 'src/components/xss-vulnerable.tsx',
75
+ content: `
76
+ import React from 'react'
77
+
78
+ // Direct innerHTML assignment
79
+ export function RenderUserHTML({ html }: { html: string }) {
80
+ const divRef = useRef<HTMLDivElement>(null)
81
+ useEffect(() => {
82
+ if (divRef.current) {
83
+ divRef.current.innerHTML = html // XSS!
84
+ }
85
+ }, [html])
86
+ return <div ref={divRef} />
87
+ }
88
+
89
+ // dangerouslySetInnerHTML without sanitization
90
+ export function UserBio({ bioHtml }: { bioHtml: string }) {
91
+ return <div dangerouslySetInnerHTML={{ __html: bioHtml }} />
92
+ }
93
+
94
+ // document.write
95
+ export function InjectScript(content: string) {
96
+ document.write(content) // XSS!
97
+ }
98
+
99
+ // createElement with user content
100
+ export function CreateElement(tagName: string, content: string) {
101
+ const el = document.createElement(tagName)
102
+ el.innerHTML = content // XSS!
103
+ document.body.appendChild(el)
104
+ }
105
+
106
+ // URL-based XSS
107
+ export function RedirectWithMessage(url: string) {
108
+ window.location.href = \`javascript:alert('\${url}')\` // XSS via javascript: URL
109
+ }
110
+
111
+ // Event handler injection
112
+ export function AddHandler(element: HTMLElement, handler: string) {
113
+ element.setAttribute('onclick', handler) // XSS!
114
+ }
115
+
116
+ // SVG injection
117
+ export function RenderSVG({ svgContent }: { svgContent: string }) {
118
+ return <div dangerouslySetInnerHTML={{ __html: svgContent }} />
119
+ }
120
+ `,
121
+ language: 'typescript',
122
+ size: 1100,
123
+ },
124
+ },
125
+ {
126
+ name: 'Command Injection - Various Patterns',
127
+ expectFindings: true,
128
+ expectedCategories: ['dangerous_function'],
129
+ description: 'Command injection patterns in Node.js and shell contexts',
130
+ file: {
131
+ path: 'src/utils/command-injection.ts',
132
+ content: `
133
+ import { exec, execSync, spawn } from 'child_process'
134
+
135
+ // Basic exec with user input
136
+ export function runUserCommand(cmd: string) {
137
+ exec(cmd, (err, stdout) => console.log(stdout))
138
+ }
139
+
140
+ // exec with template literal
141
+ export function processFile(filename: string) {
142
+ exec(\`cat \${filename}\`)
143
+ }
144
+
145
+ // execSync with concatenation
146
+ export function getFileInfo(path: string) {
147
+ return execSync('ls -la ' + path)
148
+ }
149
+
150
+ // Shell option enabled
151
+ export function runWithShell(command: string) {
152
+ spawn(command, { shell: true })
153
+ }
154
+
155
+ // Backtick command substitution vulnerability
156
+ export function generateReport(date: string) {
157
+ exec(\`echo "Report for \${date}" > /tmp/report.txt\`)
158
+ }
159
+
160
+ // Chained commands
161
+ export function chainedCommands(input: string) {
162
+ exec(\`echo \${input} && whoami\`) // User can inject "; rm -rf /"
163
+ }
164
+
165
+ // Environment variable injection
166
+ export function setEnvAndRun(value: string) {
167
+ exec(\`export VAR="\${value}" && ./script.sh\`)
168
+ }
169
+ `,
170
+ language: 'typescript',
171
+ size: 900,
172
+ },
173
+ },
174
+ ],
175
+
176
+ falseNegatives: [
177
+ {
178
+ name: 'Injection - Safe Patterns',
179
+ expectFindings: false,
180
+ description: 'Safe patterns that prevent injection attacks',
181
+ allowedInfoFindings: [
182
+ {
183
+ category: 'dangerous_function',
184
+ maxCount: 5,
185
+ reason: 'SQL with allowlist validation and static commands generate info-level findings',
186
+ },
187
+ ],
188
+ file: {
189
+ path: 'src/api/safe-injection.ts',
190
+ content: `
191
+ import { execFile } from 'child_process'
192
+ import DOMPurify from 'dompurify'
193
+
194
+ // Parameterized SQL - SAFE
195
+ export async function getUserById(id: string) {
196
+ return db.query('SELECT * FROM users WHERE id = $1', [id])
197
+ }
198
+
199
+ // Query builder with escaping - SAFE
200
+ export async function searchProducts(term: string) {
201
+ return knex('products').where('name', 'ilike', \`%\${term}%\`)
202
+ }
203
+
204
+ // ORM - SAFE
205
+ export async function findUser(email: string) {
206
+ return prisma.user.findUnique({ where: { email } })
207
+ }
208
+
209
+ // DOMPurify sanitized HTML - SAFE
210
+ export function SafeHTML({ html }: { html: string }) {
211
+ const clean = DOMPurify.sanitize(html)
212
+ return <div dangerouslySetInnerHTML={{ __html: clean }} />
213
+ }
214
+
215
+ // execFile with array args - SAFE
216
+ export function safeExec(filename: string) {
217
+ execFile('ls', ['-la', filename])
218
+ }
219
+
220
+ // Allowlist validation - SAFE
221
+ export async function getSortedUsers(column: string) {
222
+ const allowed = ['name', 'email', 'created_at']
223
+ if (!allowed.includes(column)) {
224
+ column = 'created_at'
225
+ }
226
+ return db.query(\`SELECT * FROM users ORDER BY \${column}\`)
227
+ }
228
+
229
+ // Static command - SAFE
230
+ export function getVersion() {
231
+ return execSync('node --version')
232
+ }
233
+ `,
234
+ language: 'typescript',
235
+ size: 1000,
236
+ },
237
+ },
238
+ ],
239
+ }