@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,186 @@
1
+ /**
2
+ * Layer 2: Risky Import/Package Analysis
3
+ * Detects imports of packages known to have security concerns or deprecated
4
+ */
5
+
6
+ import type { Vulnerability, VulnerabilitySeverity } from '../types'
7
+
8
+ interface RiskyPackage {
9
+ name: string
10
+ pattern: RegExp
11
+ severity: VulnerabilitySeverity
12
+ description: string
13
+ suggestedFix: string
14
+ }
15
+
16
+ const RISKY_PACKAGES: RiskyPackage[] = [
17
+ // Known vulnerable or deprecated packages
18
+ {
19
+ name: 'request (deprecated)',
20
+ pattern: /require\s*\(\s*['"]request['"]\s*\)|from\s+['"]request['"]/gi,
21
+ severity: 'medium',
22
+ description: 'The "request" package is deprecated and no longer maintained',
23
+ suggestedFix: 'Migrate to fetch, axios, or node-fetch',
24
+ },
25
+ {
26
+ name: 'node-uuid (deprecated)',
27
+ pattern: /require\s*\(\s*['"]node-uuid['"]\s*\)|from\s+['"]node-uuid['"]/gi,
28
+ severity: 'low',
29
+ description: 'node-uuid is deprecated in favor of uuid package',
30
+ suggestedFix: 'Use the "uuid" package instead',
31
+ },
32
+
33
+ // Packages with known security issues
34
+ {
35
+ name: 'lodash (full import)',
36
+ pattern: /require\s*\(\s*['"]lodash['"]\s*\)|import\s+\*?\s*(?:as\s+)?\w+\s+from\s+['"]lodash['"]/gi,
37
+ severity: 'low',
38
+ description: 'Full lodash import increases bundle size and attack surface',
39
+ suggestedFix: 'Import specific functions: import get from "lodash/get"',
40
+ },
41
+ {
42
+ name: 'moment.js (deprecated)',
43
+ pattern: /require\s*\(\s*['"]moment['"]\s*\)|from\s+['"]moment['"]/gi,
44
+ severity: 'low',
45
+ description: 'Moment.js is in maintenance mode, consider alternatives',
46
+ suggestedFix: 'Use date-fns, dayjs, or native Intl APIs',
47
+ },
48
+
49
+ // Security-focused sandbox packages - info only (these are used for security, not risky)
50
+ {
51
+ name: 'vm2 (sandbox)',
52
+ pattern: /require\s*\(\s*['"]vm2['"]\s*\)|from\s+['"]vm2['"]/gi,
53
+ severity: 'info',
54
+ description: 'vm2 is a sandboxing library. While it has had sandbox escape vulnerabilities historically, using it is generally safer than running untrusted code directly. Keep vm2 updated.',
55
+ suggestedFix: 'Keep vm2 updated to the latest version. For maximum isolation, consider isolated-vm or running in a separate process.',
56
+ },
57
+ {
58
+ name: 'serialize-javascript (RCE risk)',
59
+ pattern: /require\s*\(\s*['"]serialize-javascript['"]\s*\)|from\s+['"]serialize-javascript['"]/gi,
60
+ severity: 'medium',
61
+ description: 'serialize-javascript can be dangerous if output is not properly handled',
62
+ suggestedFix: 'Ensure serialized output is not directly executed or use JSON.stringify',
63
+ },
64
+
65
+ // Crypto-related risky imports
66
+ {
67
+ name: 'crypto-js (outdated patterns)',
68
+ pattern: /require\s*\(\s*['"]crypto-js['"]\s*\)|from\s+['"]crypto-js['"]/gi,
69
+ severity: 'low',
70
+ description: 'crypto-js may use outdated crypto patterns',
71
+ suggestedFix: 'Prefer Node.js built-in crypto module or Web Crypto API',
72
+ },
73
+ {
74
+ name: 'bcrypt-nodejs (deprecated)',
75
+ pattern: /require\s*\(\s*['"]bcrypt-nodejs['"]\s*\)|from\s+['"]bcrypt-nodejs['"]/gi,
76
+ severity: 'medium',
77
+ description: 'bcrypt-nodejs is deprecated and unmaintained',
78
+ suggestedFix: 'Use bcrypt or bcryptjs instead',
79
+ },
80
+
81
+ // SQL/Database risky patterns
82
+ {
83
+ name: 'mysql (prefer mysql2)',
84
+ pattern: /require\s*\(\s*['"]mysql['"]\s*\)|from\s+['"]mysql['"]/gi,
85
+ severity: 'low',
86
+ description: 'mysql package is less maintained than mysql2',
87
+ suggestedFix: 'Consider using mysql2 for better security and performance',
88
+ },
89
+
90
+ // Python risky imports
91
+ {
92
+ name: 'pickle (unsafe deserialization)',
93
+ pattern: /^import\s+pickle|^from\s+pickle\s+import/gim,
94
+ severity: 'high',
95
+ description: 'pickle can execute arbitrary code during deserialization',
96
+ suggestedFix: 'Use JSON or other safe serialization formats for untrusted data',
97
+ },
98
+ {
99
+ name: 'yaml unsafe load',
100
+ pattern: /yaml\.load\s*\([^)]*\)(?!.*Loader)/gi,
101
+ severity: 'high',
102
+ description: 'yaml.load without Loader parameter can execute arbitrary code',
103
+ suggestedFix: 'Use yaml.safe_load() or specify Loader=yaml.SafeLoader',
104
+ },
105
+ {
106
+ name: 'subprocess shell=True',
107
+ pattern: /subprocess\.(call|run|Popen|check_output)\s*\([^)]*shell\s*=\s*True/gi,
108
+ severity: 'high',
109
+ description: 'subprocess with shell=True is vulnerable to shell injection',
110
+ suggestedFix: 'Use shell=False and pass arguments as a list',
111
+ },
112
+
113
+ // Telemetry/tracking packages (privacy concern)
114
+ {
115
+ name: 'Analytics package',
116
+ pattern: /require\s*\(\s*['"](analytics|segment|mixpanel|amplitude)['"]\s*\)|from\s+['"](analytics|segment|mixpanel|amplitude)['"]/gi,
117
+ severity: 'low',
118
+ description: 'Analytics package detected - ensure user consent is obtained',
119
+ suggestedFix: 'Implement proper consent mechanisms for user tracking',
120
+ },
121
+
122
+ // Outdated/vulnerable web frameworks
123
+ {
124
+ name: 'express-jwt (CVE history)',
125
+ pattern: /require\s*\(\s*['"]express-jwt['"]\s*\)|from\s+['"]express-jwt['"]/gi,
126
+ severity: 'medium',
127
+ description: 'express-jwt has had security vulnerabilities - ensure latest version',
128
+ suggestedFix: 'Update to latest version and consider jose or jsonwebtoken directly',
129
+ },
130
+
131
+ // Dangerous native modules
132
+ {
133
+ name: 'node-gyp native module',
134
+ pattern: /require\s*\(\s*['"]node-gyp['"]\s*\)|from\s+['"]node-gyp['"]/gi,
135
+ severity: 'low',
136
+ description: 'Native modules can introduce platform-specific vulnerabilities',
137
+ suggestedFix: 'Audit native dependencies and keep them updated',
138
+ },
139
+ ]
140
+
141
+ // Check if line is a comment
142
+ function isComment(line: string): boolean {
143
+ const trimmed = line.trim()
144
+ return (
145
+ trimmed.startsWith('//') ||
146
+ trimmed.startsWith('#') ||
147
+ trimmed.startsWith('*') ||
148
+ trimmed.startsWith('/*')
149
+ )
150
+ }
151
+
152
+ export function detectRiskyImports(
153
+ content: string,
154
+ filePath: string
155
+ ): Vulnerability[] {
156
+ const vulnerabilities: Vulnerability[] = []
157
+ const lines = content.split('\n')
158
+
159
+ lines.forEach((line, index) => {
160
+ // Skip comment lines
161
+ if (isComment(line)) return
162
+
163
+ for (const pkg of RISKY_PACKAGES) {
164
+ const regex = new RegExp(pkg.pattern.source, pkg.pattern.flags)
165
+
166
+ if (regex.test(line)) {
167
+ vulnerabilities.push({
168
+ id: `risky-import-${filePath}-${index + 1}-${pkg.name}`,
169
+ filePath,
170
+ lineNumber: index + 1,
171
+ lineContent: line.trim(),
172
+ severity: pkg.severity,
173
+ category: 'suspicious_package',
174
+ title: `Risky package: ${pkg.name}`,
175
+ description: pkg.description,
176
+ suggestedFix: pkg.suggestedFix,
177
+ confidence: 'high',
178
+ layer: 2,
179
+ })
180
+ break // Only report once per line
181
+ }
182
+ }
183
+ })
184
+
185
+ return vulnerabilities
186
+ }
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Layer 2: Variable Heuristics
3
+ * Identifies variable names associated with sensitive data
4
+ */
5
+
6
+ import type { Vulnerability, SensitiveVariablePattern } from '../types'
7
+
8
+ // Patterns for sensitive variable names
9
+ export const SENSITIVE_VARIABLE_PATTERNS: SensitiveVariablePattern[] = [
10
+ // Password-related
11
+ {
12
+ pattern: /\b(password|passwd|pwd|pass)\s*[=:]/gi,
13
+ severity: 'high',
14
+ description: 'Variable name suggests password storage',
15
+ },
16
+ {
17
+ pattern: /\b(user_?password|admin_?password|db_?password|database_?password)\s*[=:]/gi,
18
+ severity: 'critical',
19
+ description: 'Variable name suggests database/admin password',
20
+ },
21
+ // Token-related
22
+ {
23
+ pattern: /\b(auth_?token|access_?token|refresh_?token|bearer_?token)\s*[=:]/gi,
24
+ severity: 'high',
25
+ description: 'Variable name suggests authentication token',
26
+ },
27
+ {
28
+ pattern: /\b(api_?token|api_?key|apikey)\s*[=:]/gi,
29
+ severity: 'high',
30
+ description: 'Variable name suggests API key/token',
31
+ },
32
+ // Secret-related
33
+ {
34
+ pattern: /\b(secret|secret_?key|private_?key|signing_?key)\s*[=:]/gi,
35
+ severity: 'high',
36
+ description: 'Variable name suggests secret/private key',
37
+ },
38
+ {
39
+ pattern: /\b(client_?secret|app_?secret|jwt_?secret)\s*[=:]/gi,
40
+ severity: 'critical',
41
+ description: 'Variable name suggests application secret',
42
+ },
43
+ // Credential-related
44
+ {
45
+ pattern: /\b(credential|credentials|creds)\s*[=:]/gi,
46
+ severity: 'high',
47
+ description: 'Variable name suggests credentials',
48
+ },
49
+ // Connection strings
50
+ {
51
+ pattern: /\b(connection_?string|conn_?string|database_?url|db_?url)\s*[=:]/gi,
52
+ severity: 'high',
53
+ description: 'Variable name suggests database connection string',
54
+ },
55
+ // Encryption keys
56
+ {
57
+ pattern: /\b(encryption_?key|decrypt_?key|cipher_?key|aes_?key)\s*[=:]/gi,
58
+ severity: 'critical',
59
+ description: 'Variable name suggests encryption key',
60
+ },
61
+ // SSH/Certificate
62
+ {
63
+ pattern: /\b(ssh_?key|private_?key|cert_?key|ssl_?key)\s*[=:]/gi,
64
+ severity: 'critical',
65
+ description: 'Variable name suggests SSH/SSL key',
66
+ },
67
+ ]
68
+
69
+ // Check if the value looks like a placeholder or env var reference
70
+ function isPlaceholderOrEnvRef(line: string): boolean {
71
+ const safePatterns = [
72
+ /[=:]\s*['"]?\s*$/, // Empty value
73
+ /[=:]\s*['"]?xxx/i, // xxx placeholder
74
+ /[=:]\s*['"]?your[-_]/i, // your-xxx placeholder
75
+ /[=:]\s*['"]?<[^>]+>/, // <placeholder>
76
+ /[=:]\s*['"]?\$\{/, // ${VAR} template
77
+ /[=:]\s*['"]?process\.env/, // process.env reference
78
+ /[=:]\s*['"]?env\(/, // env() function
79
+ /[=:]\s*['"]?getenv/i, // getenv function
80
+ /[=:]\s*['"]?os\.environ/, // Python os.environ
81
+ /[=:]\s*['"]?ENV\[/, // Ruby ENV
82
+ /[=:]\s*null\b/i, // null value
83
+ /[=:]\s*undefined\b/, // undefined value
84
+ /[=:]\s*None\b/, // Python None
85
+ /[=:]\s*['"]?TODO/i, // TODO placeholder
86
+ /[=:]\s*['"]?CHANGEME/i, // CHANGEME placeholder
87
+ /[=:]\s*['"]?REPLACE/i, // REPLACE placeholder
88
+ /\?\s*.*\s*:\s*/, // Ternary operator (conditional assignment)
89
+ /\|\|/, // OR fallback (e.g., ENV_VAR || '')
90
+ /\?\?/, // Nullish coalescing
91
+ /[A-Z_]{3,}_(?:KEY|TOKEN|SECRET)/, // References to env var constants
92
+ ]
93
+
94
+ return safePatterns.some(pattern => pattern.test(line))
95
+ }
96
+
97
+ // Check if line is a comment
98
+ function isComment(line: string): boolean {
99
+ const trimmed = line.trim()
100
+ return (
101
+ trimmed.startsWith('//') ||
102
+ trimmed.startsWith('#') ||
103
+ trimmed.startsWith('*') ||
104
+ trimmed.startsWith('/*') ||
105
+ trimmed.startsWith('"""') ||
106
+ trimmed.startsWith("'''") ||
107
+ trimmed.startsWith('<!--')
108
+ )
109
+ }
110
+
111
+ // Check if it's a type definition or interface
112
+ function isTypeDefinition(line: string): boolean {
113
+ return (
114
+ /^\s*(type|interface|class)\s/.test(line) ||
115
+ /:\s*(string|number|boolean|any)\s*[;,}]/.test(line) ||
116
+ /\?\s*:\s*\w+/.test(line)
117
+ )
118
+ }
119
+
120
+ export function detectSensitiveVariables(
121
+ content: string,
122
+ filePath: string
123
+ ): Vulnerability[] {
124
+ const vulnerabilities: Vulnerability[] = []
125
+ const lines = content.split('\n')
126
+
127
+ lines.forEach((line, index) => {
128
+ // Skip comments
129
+ if (isComment(line)) return
130
+
131
+ // Skip type definitions
132
+ if (isTypeDefinition(line)) return
133
+
134
+ // Skip if it's a placeholder/env reference
135
+ if (isPlaceholderOrEnvRef(line)) return
136
+
137
+ for (const pattern of SENSITIVE_VARIABLE_PATTERNS) {
138
+ const regex = new RegExp(pattern.pattern.source, pattern.pattern.flags)
139
+
140
+ if (regex.test(line)) {
141
+ // Extract the actual value to check if it's hardcoded
142
+ const valueMatch = line.match(/[=:]\s*['"]([^'"]+)['"]/i)
143
+
144
+ if (valueMatch && valueMatch[1].length > 3) {
145
+ // Has a non-trivial hardcoded value
146
+ vulnerabilities.push({
147
+ id: `var-${filePath}-${index + 1}`,
148
+ filePath,
149
+ lineNumber: index + 1,
150
+ lineContent: line.trim(),
151
+ severity: pattern.severity,
152
+ category: 'sensitive_variable',
153
+ title: 'Sensitive variable with hardcoded value',
154
+ description: pattern.description + '. The value appears to be hardcoded rather than loaded from environment.',
155
+ suggestedFix: 'Move this sensitive value to an environment variable or secure secrets manager.',
156
+ confidence: 'medium',
157
+ layer: 2,
158
+ })
159
+ }
160
+ break // Only report once per line
161
+ }
162
+ }
163
+ })
164
+
165
+ return vulnerabilities
166
+ }