@oculum/scanner 1.0.10 → 1.0.12

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 (520) hide show
  1. package/dist/ai-context/index.d.ts +6 -0
  2. package/dist/ai-context/index.d.ts.map +1 -0
  3. package/dist/ai-context/index.js +13 -0
  4. package/dist/ai-context/index.js.map +1 -0
  5. package/dist/ai-context/manager.d.ts +67 -0
  6. package/dist/ai-context/manager.d.ts.map +1 -0
  7. package/dist/ai-context/manager.js +104 -0
  8. package/dist/ai-context/manager.js.map +1 -0
  9. package/dist/baseline/diff.d.ts +32 -0
  10. package/dist/baseline/diff.d.ts.map +1 -0
  11. package/dist/baseline/diff.js +119 -0
  12. package/dist/baseline/diff.js.map +1 -0
  13. package/dist/baseline/index.d.ts +9 -0
  14. package/dist/baseline/index.d.ts.map +1 -0
  15. package/dist/baseline/index.js +19 -0
  16. package/dist/baseline/index.js.map +1 -0
  17. package/dist/baseline/manager.d.ts +67 -0
  18. package/dist/baseline/manager.d.ts.map +1 -0
  19. package/dist/baseline/manager.js +180 -0
  20. package/dist/baseline/manager.js.map +1 -0
  21. package/dist/baseline/types.d.ts +91 -0
  22. package/dist/baseline/types.d.ts.map +1 -0
  23. package/dist/baseline/types.js +12 -0
  24. package/dist/baseline/types.js.map +1 -0
  25. package/dist/category-filter.d.ts +125 -0
  26. package/dist/category-filter.d.ts.map +1 -0
  27. package/dist/category-filter.js +360 -0
  28. package/dist/category-filter.js.map +1 -0
  29. package/dist/filtering/context-adjustments.d.ts +23 -0
  30. package/dist/filtering/context-adjustments.d.ts.map +1 -0
  31. package/dist/filtering/context-adjustments.js +100 -0
  32. package/dist/filtering/context-adjustments.js.map +1 -0
  33. package/dist/filtering/index.d.ts +3 -0
  34. package/dist/filtering/index.d.ts.map +1 -0
  35. package/dist/filtering/index.js +8 -0
  36. package/dist/filtering/index.js.map +1 -0
  37. package/dist/filtering/pipeline.d.ts +48 -0
  38. package/dist/filtering/pipeline.d.ts.map +1 -0
  39. package/dist/filtering/pipeline.js +76 -0
  40. package/dist/filtering/pipeline.js.map +1 -0
  41. package/dist/formatters/ai-context.d.ts +23 -0
  42. package/dist/formatters/ai-context.d.ts.map +1 -0
  43. package/dist/formatters/ai-context.js +238 -0
  44. package/dist/formatters/ai-context.js.map +1 -0
  45. package/dist/formatters/cli-terminal.d.ts +38 -0
  46. package/dist/formatters/cli-terminal.d.ts.map +1 -1
  47. package/dist/formatters/cli-terminal.js +365 -42
  48. package/dist/formatters/cli-terminal.js.map +1 -1
  49. package/dist/formatters/github-comment.d.ts +2 -2
  50. package/dist/formatters/github-comment.d.ts.map +1 -1
  51. package/dist/formatters/github-comment.js +77 -13
  52. package/dist/formatters/github-comment.js.map +1 -1
  53. package/dist/formatters/ide/claude-code.d.ts +17 -0
  54. package/dist/formatters/ide/claude-code.d.ts.map +1 -0
  55. package/dist/formatters/ide/claude-code.js +94 -0
  56. package/dist/formatters/ide/claude-code.js.map +1 -0
  57. package/dist/formatters/ide/cursor.d.ts +13 -0
  58. package/dist/formatters/ide/cursor.d.ts.map +1 -0
  59. package/dist/formatters/ide/cursor.js +125 -0
  60. package/dist/formatters/ide/cursor.js.map +1 -0
  61. package/dist/formatters/ide/index.d.ts +62 -0
  62. package/dist/formatters/ide/index.d.ts.map +1 -0
  63. package/dist/formatters/ide/index.js +184 -0
  64. package/dist/formatters/ide/index.js.map +1 -0
  65. package/dist/formatters/ide/windsurf.d.ts +13 -0
  66. package/dist/formatters/ide/windsurf.d.ts.map +1 -0
  67. package/dist/formatters/ide/windsurf.js +117 -0
  68. package/dist/formatters/ide/windsurf.js.map +1 -0
  69. package/dist/formatters/index.d.ts +3 -1
  70. package/dist/formatters/index.d.ts.map +1 -1
  71. package/dist/formatters/index.js +20 -1
  72. package/dist/formatters/index.js.map +1 -1
  73. package/dist/index.d.ts +11 -0
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +423 -56
  76. package/dist/index.js.map +1 -1
  77. package/dist/layer1/comments.d.ts +4 -1
  78. package/dist/layer1/comments.d.ts.map +1 -1
  79. package/dist/layer1/comments.js +1 -1
  80. package/dist/layer1/comments.js.map +1 -1
  81. package/dist/layer1/config-audit.d.ts +4 -1
  82. package/dist/layer1/config-audit.d.ts.map +1 -1
  83. package/dist/layer1/config-audit.js +65 -14
  84. package/dist/layer1/config-audit.js.map +1 -1
  85. package/dist/layer1/config-mcp-audit.d.ts +23 -0
  86. package/dist/layer1/config-mcp-audit.d.ts.map +1 -0
  87. package/dist/layer1/config-mcp-audit.js +239 -0
  88. package/dist/layer1/config-mcp-audit.js.map +1 -0
  89. package/dist/layer1/entropy.d.ts +4 -1
  90. package/dist/layer1/entropy.d.ts.map +1 -1
  91. package/dist/layer1/entropy.js +212 -1
  92. package/dist/layer1/entropy.js.map +1 -1
  93. package/dist/layer1/file-flags.d.ts +4 -1
  94. package/dist/layer1/file-flags.d.ts.map +1 -1
  95. package/dist/layer1/file-flags.js +12 -5
  96. package/dist/layer1/file-flags.js.map +1 -1
  97. package/dist/layer1/index.d.ts +1 -0
  98. package/dist/layer1/index.d.ts.map +1 -1
  99. package/dist/layer1/index.js +22 -19
  100. package/dist/layer1/index.js.map +1 -1
  101. package/dist/layer1/patterns.d.ts +4 -1
  102. package/dist/layer1/patterns.d.ts.map +1 -1
  103. package/dist/layer1/patterns.js +34 -4
  104. package/dist/layer1/patterns.js.map +1 -1
  105. package/dist/layer1/urls.d.ts +4 -1
  106. package/dist/layer1/urls.d.ts.map +1 -1
  107. package/dist/layer1/urls.js +162 -14
  108. package/dist/layer1/urls.js.map +1 -1
  109. package/dist/layer1/weak-crypto.d.ts +4 -1
  110. package/dist/layer1/weak-crypto.d.ts.map +1 -1
  111. package/dist/layer1/weak-crypto.js +144 -7
  112. package/dist/layer1/weak-crypto.js.map +1 -1
  113. package/dist/layer2/ai-agent-tools.d.ts +4 -1
  114. package/dist/layer2/ai-agent-tools.d.ts.map +1 -1
  115. package/dist/layer2/ai-agent-tools.js +964 -2
  116. package/dist/layer2/ai-agent-tools.js.map +1 -1
  117. package/dist/layer2/ai-endpoint-protection.d.ts +2 -0
  118. package/dist/layer2/ai-endpoint-protection.d.ts.map +1 -1
  119. package/dist/layer2/ai-endpoint-protection.js +18 -4
  120. package/dist/layer2/ai-endpoint-protection.js.map +1 -1
  121. package/dist/layer2/ai-execution-sinks.d.ts +4 -1
  122. package/dist/layer2/ai-execution-sinks.d.ts.map +1 -1
  123. package/dist/layer2/ai-execution-sinks.js +688 -29
  124. package/dist/layer2/ai-execution-sinks.js.map +1 -1
  125. package/dist/layer2/ai-fingerprinting.d.ts +4 -1
  126. package/dist/layer2/ai-fingerprinting.d.ts.map +1 -1
  127. package/dist/layer2/ai-fingerprinting.js +28 -32
  128. package/dist/layer2/ai-fingerprinting.js.map +1 -1
  129. package/dist/layer2/ai-mcp-security.d.ts +20 -0
  130. package/dist/layer2/ai-mcp-security.d.ts.map +1 -0
  131. package/dist/layer2/ai-mcp-security.js +877 -0
  132. package/dist/layer2/ai-mcp-security.js.map +1 -0
  133. package/dist/layer2/ai-package-hallucination.d.ts +22 -0
  134. package/dist/layer2/ai-package-hallucination.d.ts.map +1 -0
  135. package/dist/layer2/ai-package-hallucination.js +828 -0
  136. package/dist/layer2/ai-package-hallucination.js.map +1 -0
  137. package/dist/layer2/ai-prompt-hygiene.d.ts +4 -1
  138. package/dist/layer2/ai-prompt-hygiene.d.ts.map +1 -1
  139. package/dist/layer2/ai-prompt-hygiene.js +817 -17
  140. package/dist/layer2/ai-prompt-hygiene.js.map +1 -1
  141. package/dist/layer2/ai-rag-safety.d.ts +4 -1
  142. package/dist/layer2/ai-rag-safety.d.ts.map +1 -1
  143. package/dist/layer2/ai-rag-safety.js +454 -3
  144. package/dist/layer2/ai-rag-safety.js.map +1 -1
  145. package/dist/layer2/ai-schema-validation.d.ts +4 -1
  146. package/dist/layer2/ai-schema-validation.d.ts.map +1 -1
  147. package/dist/layer2/ai-schema-validation.js +2 -2
  148. package/dist/layer2/ai-schema-validation.js.map +1 -1
  149. package/dist/layer2/auth-antipatterns.d.ts +2 -0
  150. package/dist/layer2/auth-antipatterns.d.ts.map +1 -1
  151. package/dist/layer2/auth-antipatterns.js +209 -20
  152. package/dist/layer2/auth-antipatterns.js.map +1 -1
  153. package/dist/layer2/byok-patterns.d.ts +4 -1
  154. package/dist/layer2/byok-patterns.d.ts.map +1 -1
  155. package/dist/layer2/byok-patterns.js +5 -2
  156. package/dist/layer2/byok-patterns.js.map +1 -1
  157. package/dist/layer2/dangerous-functions/child-process.d.ts +16 -0
  158. package/dist/layer2/dangerous-functions/child-process.d.ts.map +1 -0
  159. package/dist/layer2/dangerous-functions/child-process.js +74 -0
  160. package/dist/layer2/dangerous-functions/child-process.js.map +1 -0
  161. package/dist/layer2/dangerous-functions/dom-xss.d.ts +34 -0
  162. package/dist/layer2/dangerous-functions/dom-xss.d.ts.map +1 -0
  163. package/dist/layer2/dangerous-functions/dom-xss.js +230 -0
  164. package/dist/layer2/dangerous-functions/dom-xss.js.map +1 -0
  165. package/dist/layer2/dangerous-functions/index.d.ts +16 -0
  166. package/dist/layer2/dangerous-functions/index.d.ts.map +1 -0
  167. package/dist/layer2/dangerous-functions/index.js +1152 -0
  168. package/dist/layer2/dangerous-functions/index.js.map +1 -0
  169. package/dist/layer2/dangerous-functions/json-parse.d.ts +31 -0
  170. package/dist/layer2/dangerous-functions/json-parse.d.ts.map +1 -0
  171. package/dist/layer2/dangerous-functions/json-parse.js +319 -0
  172. package/dist/layer2/dangerous-functions/json-parse.js.map +1 -0
  173. package/dist/layer2/dangerous-functions/math-random.d.ts +111 -0
  174. package/dist/layer2/dangerous-functions/math-random.d.ts.map +1 -0
  175. package/dist/layer2/dangerous-functions/math-random.js +684 -0
  176. package/dist/layer2/dangerous-functions/math-random.js.map +1 -0
  177. package/dist/layer2/dangerous-functions/patterns.d.ts +21 -0
  178. package/dist/layer2/dangerous-functions/patterns.d.ts.map +1 -0
  179. package/dist/layer2/dangerous-functions/patterns.js +163 -0
  180. package/dist/layer2/dangerous-functions/patterns.js.map +1 -0
  181. package/dist/layer2/dangerous-functions/request-validation.d.ts +13 -0
  182. package/dist/layer2/dangerous-functions/request-validation.d.ts.map +1 -0
  183. package/dist/layer2/dangerous-functions/request-validation.js +119 -0
  184. package/dist/layer2/dangerous-functions/request-validation.js.map +1 -0
  185. package/dist/layer2/dangerous-functions/utils/control-flow.d.ts +24 -0
  186. package/dist/layer2/dangerous-functions/utils/control-flow.d.ts.map +1 -0
  187. package/dist/layer2/dangerous-functions/utils/control-flow.js +70 -0
  188. package/dist/layer2/dangerous-functions/utils/control-flow.js.map +1 -0
  189. package/dist/layer2/dangerous-functions/utils/helpers.d.ts +31 -0
  190. package/dist/layer2/dangerous-functions/utils/helpers.d.ts.map +1 -0
  191. package/dist/layer2/dangerous-functions/utils/helpers.js +147 -0
  192. package/dist/layer2/dangerous-functions/utils/helpers.js.map +1 -0
  193. package/dist/layer2/dangerous-functions/utils/index.d.ts +9 -0
  194. package/dist/layer2/dangerous-functions/utils/index.d.ts.map +1 -0
  195. package/dist/layer2/dangerous-functions/utils/index.js +23 -0
  196. package/dist/layer2/dangerous-functions/utils/index.js.map +1 -0
  197. package/dist/layer2/dangerous-functions/utils/schema-validation.d.ts +22 -0
  198. package/dist/layer2/dangerous-functions/utils/schema-validation.d.ts.map +1 -0
  199. package/dist/layer2/dangerous-functions/utils/schema-validation.js +102 -0
  200. package/dist/layer2/dangerous-functions/utils/schema-validation.js.map +1 -0
  201. package/dist/layer2/data-exposure.d.ts +4 -1
  202. package/dist/layer2/data-exposure.d.ts.map +1 -1
  203. package/dist/layer2/data-exposure.js +14 -38
  204. package/dist/layer2/data-exposure.js.map +1 -1
  205. package/dist/layer2/framework-checks.d.ts +4 -1
  206. package/dist/layer2/framework-checks.d.ts.map +1 -1
  207. package/dist/layer2/framework-checks.js +5 -2
  208. package/dist/layer2/framework-checks.js.map +1 -1
  209. package/dist/layer2/index.d.ts +12 -1
  210. package/dist/layer2/index.d.ts.map +1 -1
  211. package/dist/layer2/index.js +110 -45
  212. package/dist/layer2/index.js.map +1 -1
  213. package/dist/layer2/logic-gates.d.ts +4 -1
  214. package/dist/layer2/logic-gates.d.ts.map +1 -1
  215. package/dist/layer2/logic-gates.js +58 -20
  216. package/dist/layer2/logic-gates.js.map +1 -1
  217. package/dist/layer2/model-supply-chain.d.ts +23 -0
  218. package/dist/layer2/model-supply-chain.d.ts.map +1 -0
  219. package/dist/layer2/model-supply-chain.js +444 -0
  220. package/dist/layer2/model-supply-chain.js.map +1 -0
  221. package/dist/layer2/risky-imports.d.ts +4 -1
  222. package/dist/layer2/risky-imports.d.ts.map +1 -1
  223. package/dist/layer2/risky-imports.js +6 -2
  224. package/dist/layer2/risky-imports.js.map +1 -1
  225. package/dist/layer2/variables.d.ts +4 -1
  226. package/dist/layer2/variables.d.ts.map +1 -1
  227. package/dist/layer2/variables.js +6 -2
  228. package/dist/layer2/variables.js.map +1 -1
  229. package/dist/layer3/anthropic/auto-dismiss.d.ts +24 -0
  230. package/dist/layer3/anthropic/auto-dismiss.d.ts.map +1 -0
  231. package/dist/layer3/anthropic/auto-dismiss.js +199 -0
  232. package/dist/layer3/anthropic/auto-dismiss.js.map +1 -0
  233. package/dist/layer3/anthropic/clients.d.ts +44 -0
  234. package/dist/layer3/anthropic/clients.d.ts.map +1 -0
  235. package/dist/layer3/anthropic/clients.js +81 -0
  236. package/dist/layer3/anthropic/clients.js.map +1 -0
  237. package/dist/layer3/anthropic/index.d.ts +41 -0
  238. package/dist/layer3/anthropic/index.d.ts.map +1 -0
  239. package/dist/layer3/anthropic/index.js +141 -0
  240. package/dist/layer3/anthropic/index.js.map +1 -0
  241. package/dist/layer3/anthropic/prompts/index.d.ts +8 -0
  242. package/dist/layer3/anthropic/prompts/index.d.ts.map +1 -0
  243. package/dist/layer3/anthropic/prompts/index.js +14 -0
  244. package/dist/layer3/anthropic/prompts/index.js.map +1 -0
  245. package/dist/layer3/anthropic/prompts/semantic-analysis.d.ts +15 -0
  246. package/dist/layer3/anthropic/prompts/semantic-analysis.d.ts.map +1 -0
  247. package/dist/layer3/anthropic/prompts/semantic-analysis.js +169 -0
  248. package/dist/layer3/anthropic/prompts/semantic-analysis.js.map +1 -0
  249. package/dist/layer3/anthropic/prompts/validation.d.ts +12 -0
  250. package/dist/layer3/anthropic/prompts/validation.d.ts.map +1 -0
  251. package/dist/layer3/anthropic/prompts/validation.js +421 -0
  252. package/dist/layer3/anthropic/prompts/validation.js.map +1 -0
  253. package/dist/layer3/anthropic/providers/anthropic.d.ts +21 -0
  254. package/dist/layer3/anthropic/providers/anthropic.d.ts.map +1 -0
  255. package/dist/layer3/anthropic/providers/anthropic.js +266 -0
  256. package/dist/layer3/anthropic/providers/anthropic.js.map +1 -0
  257. package/dist/layer3/anthropic/providers/index.d.ts +8 -0
  258. package/dist/layer3/anthropic/providers/index.d.ts.map +1 -0
  259. package/dist/layer3/anthropic/providers/index.js +15 -0
  260. package/dist/layer3/anthropic/providers/index.js.map +1 -0
  261. package/dist/layer3/anthropic/providers/openai.d.ts +18 -0
  262. package/dist/layer3/anthropic/providers/openai.d.ts.map +1 -0
  263. package/dist/layer3/anthropic/providers/openai.js +340 -0
  264. package/dist/layer3/anthropic/providers/openai.js.map +1 -0
  265. package/dist/layer3/anthropic/request-builder.d.ts +20 -0
  266. package/dist/layer3/anthropic/request-builder.d.ts.map +1 -0
  267. package/dist/layer3/anthropic/request-builder.js +134 -0
  268. package/dist/layer3/anthropic/request-builder.js.map +1 -0
  269. package/dist/layer3/anthropic/types.d.ts +88 -0
  270. package/dist/layer3/anthropic/types.d.ts.map +1 -0
  271. package/dist/layer3/anthropic/types.js +38 -0
  272. package/dist/layer3/anthropic/types.js.map +1 -0
  273. package/dist/layer3/anthropic/utils/index.d.ts +9 -0
  274. package/dist/layer3/anthropic/utils/index.d.ts.map +1 -0
  275. package/dist/layer3/anthropic/utils/index.js +24 -0
  276. package/dist/layer3/anthropic/utils/index.js.map +1 -0
  277. package/dist/layer3/anthropic/utils/path-helpers.d.ts +21 -0
  278. package/dist/layer3/anthropic/utils/path-helpers.d.ts.map +1 -0
  279. package/dist/layer3/anthropic/utils/path-helpers.js +69 -0
  280. package/dist/layer3/anthropic/utils/path-helpers.js.map +1 -0
  281. package/dist/layer3/anthropic/utils/response-parser.d.ts +40 -0
  282. package/dist/layer3/anthropic/utils/response-parser.d.ts.map +1 -0
  283. package/dist/layer3/anthropic/utils/response-parser.js +285 -0
  284. package/dist/layer3/anthropic/utils/response-parser.js.map +1 -0
  285. package/dist/layer3/anthropic/utils/retry.d.ts +15 -0
  286. package/dist/layer3/anthropic/utils/retry.d.ts.map +1 -0
  287. package/dist/layer3/anthropic/utils/retry.js +62 -0
  288. package/dist/layer3/anthropic/utils/retry.js.map +1 -0
  289. package/dist/layer3/index.d.ts +1 -0
  290. package/dist/layer3/index.d.ts.map +1 -1
  291. package/dist/layer3/index.js +16 -6
  292. package/dist/layer3/index.js.map +1 -1
  293. package/dist/layer3/osv-check.d.ts +75 -0
  294. package/dist/layer3/osv-check.d.ts.map +1 -0
  295. package/dist/layer3/osv-check.js +308 -0
  296. package/dist/layer3/osv-check.js.map +1 -0
  297. package/dist/modes/incremental.js +1 -1
  298. package/dist/rules/framework-fixes.d.ts +48 -0
  299. package/dist/rules/framework-fixes.d.ts.map +1 -0
  300. package/dist/rules/framework-fixes.js +439 -0
  301. package/dist/rules/framework-fixes.js.map +1 -0
  302. package/dist/rules/index.d.ts +8 -0
  303. package/dist/rules/index.d.ts.map +1 -0
  304. package/dist/rules/index.js +18 -0
  305. package/dist/rules/index.js.map +1 -0
  306. package/dist/rules/metadata.d.ts +43 -0
  307. package/dist/rules/metadata.d.ts.map +1 -0
  308. package/dist/rules/metadata.js +734 -0
  309. package/dist/rules/metadata.js.map +1 -0
  310. package/dist/suppression/config-loader.d.ts +74 -0
  311. package/dist/suppression/config-loader.d.ts.map +1 -0
  312. package/dist/suppression/config-loader.js +424 -0
  313. package/dist/suppression/config-loader.js.map +1 -0
  314. package/dist/suppression/hash.d.ts +48 -0
  315. package/dist/suppression/hash.d.ts.map +1 -0
  316. package/dist/suppression/hash.js +88 -0
  317. package/dist/suppression/hash.js.map +1 -0
  318. package/dist/suppression/index.d.ts +11 -0
  319. package/dist/suppression/index.d.ts.map +1 -0
  320. package/dist/suppression/index.js +39 -0
  321. package/dist/suppression/index.js.map +1 -0
  322. package/dist/suppression/inline-parser.d.ts +39 -0
  323. package/dist/suppression/inline-parser.d.ts.map +1 -0
  324. package/dist/suppression/inline-parser.js +218 -0
  325. package/dist/suppression/inline-parser.js.map +1 -0
  326. package/dist/suppression/manager.d.ts +94 -0
  327. package/dist/suppression/manager.d.ts.map +1 -0
  328. package/dist/suppression/manager.js +292 -0
  329. package/dist/suppression/manager.js.map +1 -0
  330. package/dist/suppression/types.d.ts +151 -0
  331. package/dist/suppression/types.d.ts.map +1 -0
  332. package/dist/suppression/types.js +28 -0
  333. package/dist/suppression/types.js.map +1 -0
  334. package/dist/tiers.d.ts +3 -3
  335. package/dist/tiers.d.ts.map +1 -1
  336. package/dist/tiers.js +34 -7
  337. package/dist/tiers.js.map +1 -1
  338. package/dist/types.d.ts +140 -9
  339. package/dist/types.d.ts.map +1 -1
  340. package/dist/types.js +34 -0
  341. package/dist/types.js.map +1 -1
  342. package/dist/utils/code-analysis.d.ts +39 -0
  343. package/dist/utils/code-analysis.d.ts.map +1 -0
  344. package/dist/utils/code-analysis.js +159 -0
  345. package/dist/utils/code-analysis.js.map +1 -0
  346. package/dist/utils/comment-analyzer.d.ts +38 -0
  347. package/dist/utils/comment-analyzer.d.ts.map +1 -0
  348. package/dist/utils/comment-analyzer.js +218 -0
  349. package/dist/utils/comment-analyzer.js.map +1 -0
  350. package/dist/utils/context-helpers.d.ts +112 -1
  351. package/dist/utils/context-helpers.d.ts.map +1 -1
  352. package/dist/utils/context-helpers.js +364 -11
  353. package/dist/utils/context-helpers.js.map +1 -1
  354. package/dist/utils/environment-context.d.ts +76 -0
  355. package/dist/utils/environment-context.d.ts.map +1 -0
  356. package/dist/utils/environment-context.js +271 -0
  357. package/dist/utils/environment-context.js.map +1 -0
  358. package/dist/utils/intent-detector.d.ts +66 -0
  359. package/dist/utils/intent-detector.d.ts.map +1 -0
  360. package/dist/utils/intent-detector.js +282 -0
  361. package/dist/utils/intent-detector.js.map +1 -0
  362. package/dist/utils/parsed-file.d.ts +51 -0
  363. package/dist/utils/parsed-file.d.ts.map +1 -0
  364. package/dist/utils/parsed-file.js +95 -0
  365. package/dist/utils/parsed-file.js.map +1 -0
  366. package/dist/utils/route-hierarchy.d.ts +50 -0
  367. package/dist/utils/route-hierarchy.d.ts.map +1 -0
  368. package/dist/utils/route-hierarchy.js +226 -0
  369. package/dist/utils/route-hierarchy.js.map +1 -0
  370. package/dist/utils/schema-semantics.d.ts +45 -0
  371. package/dist/utils/schema-semantics.d.ts.map +1 -0
  372. package/dist/utils/schema-semantics.js +193 -0
  373. package/dist/utils/schema-semantics.js.map +1 -0
  374. package/package.json +4 -2
  375. package/src/__tests__/benchmark/fixtures/layer1/mcp-config-audit.json +31 -0
  376. package/src/__tests__/benchmark/fixtures/layer2/ai-execution-sinks.ts +1489 -82
  377. package/src/__tests__/benchmark/fixtures/layer2/ai-mcp-security.ts +495 -0
  378. package/src/__tests__/benchmark/fixtures/layer2/ai-package-hallucination.ts +255 -0
  379. package/src/__tests__/benchmark/fixtures/layer2/ai-prompt-hygiene.ts +300 -1
  380. package/src/__tests__/benchmark/fixtures/layer2/ai-rag-safety.ts +139 -0
  381. package/src/__tests__/benchmark/fixtures/layer2/byok-patterns.ts +7 -0
  382. package/src/__tests__/benchmark/fixtures/layer2/data-exposure.ts +63 -0
  383. package/src/__tests__/benchmark/fixtures/layer2/excessive-agency.ts +221 -0
  384. package/src/__tests__/benchmark/fixtures/layer2/index.ts +30 -0
  385. package/src/__tests__/benchmark/fixtures/layer2/model-supply-chain.ts +204 -0
  386. package/src/__tests__/benchmark/fixtures/layer2/phase1-enhancements.ts +157 -0
  387. package/src/__tests__/benchmark/fixtures/layer2/phase5-excessive-agency.ts +580 -0
  388. package/src/__tests__/benchmark/fixtures/layer2/sprint6-ai-enhancements.ts +515 -0
  389. package/src/__tests__/benchmark/run-depth-validation.ts +9 -9
  390. package/src/__tests__/category-filter.test.ts +478 -0
  391. package/src/__tests__/regression/known-false-positives.test.ts +490 -0
  392. package/src/__tests__/snapshots/__snapshots__/anthropic-validation-refactor.test.ts.snap +762 -0
  393. package/src/__tests__/snapshots/__snapshots__/dangerous-functions-refactor.test.ts.snap +503 -0
  394. package/src/__tests__/snapshots/__snapshots__/scan-depth.test.ts.snap +0 -9
  395. package/src/__tests__/snapshots/anthropic-validation-refactor.test.ts +321 -0
  396. package/src/__tests__/snapshots/dangerous-functions-refactor.test.ts +439 -0
  397. package/src/__tests__/validation/run-validation.ts +7 -7
  398. package/src/ai-context/__tests__/manager.test.ts +193 -0
  399. package/src/ai-context/index.ts +15 -0
  400. package/src/ai-context/manager.ts +145 -0
  401. package/src/baseline/__tests__/diff.test.ts +261 -0
  402. package/src/baseline/__tests__/manager.test.ts +225 -0
  403. package/src/baseline/diff.ts +135 -0
  404. package/src/baseline/index.ts +29 -0
  405. package/src/baseline/manager.ts +230 -0
  406. package/src/baseline/types.ts +97 -0
  407. package/src/category-filter.ts +400 -0
  408. package/src/filtering/__tests__/pipeline.test.ts +134 -0
  409. package/src/filtering/context-adjustments.ts +111 -0
  410. package/src/filtering/index.ts +10 -0
  411. package/src/filtering/pipeline.ts +130 -0
  412. package/src/formatters/__tests__/ai-context.test.ts +254 -0
  413. package/src/formatters/ai-context.ts +302 -0
  414. package/src/formatters/cli-terminal.ts +444 -41
  415. package/src/formatters/github-comment.ts +82 -14
  416. package/src/formatters/ide/__tests__/ide.test.ts +319 -0
  417. package/src/formatters/ide/claude-code.ts +110 -0
  418. package/src/formatters/ide/cursor.ts +147 -0
  419. package/src/formatters/ide/index.ts +216 -0
  420. package/src/formatters/ide/windsurf.ts +135 -0
  421. package/src/formatters/index.ts +28 -0
  422. package/src/index.ts +506 -45
  423. package/src/layer1/comments.ts +3 -1
  424. package/src/layer1/config-audit.ts +74 -14
  425. package/src/layer1/config-mcp-audit.ts +278 -0
  426. package/src/layer1/entropy.ts +234 -1
  427. package/src/layer1/file-flags.ts +17 -6
  428. package/src/layer1/index.ts +29 -23
  429. package/src/layer1/patterns.ts +42 -4
  430. package/src/layer1/urls.ts +188 -14
  431. package/src/layer1/weak-crypto.ts +168 -16
  432. package/src/layer2/ai-agent-tools.ts +1043 -2
  433. package/src/layer2/ai-endpoint-protection.ts +19 -4
  434. package/src/layer2/ai-execution-sinks.ts +755 -29
  435. package/src/layer2/ai-fingerprinting.ts +33 -33
  436. package/src/layer2/ai-mcp-security.ts +933 -0
  437. package/src/layer2/ai-package-hallucination.ts +940 -0
  438. package/src/layer2/ai-prompt-hygiene.ts +898 -17
  439. package/src/layer2/ai-rag-safety.ts +467 -5
  440. package/src/layer2/ai-schema-validation.ts +4 -2
  441. package/src/layer2/auth-antipatterns.ts +235 -20
  442. package/src/layer2/byok-patterns.ts +9 -3
  443. package/src/layer2/dangerous-functions/child-process.ts +98 -0
  444. package/src/layer2/dangerous-functions/dom-xss.ts +292 -0
  445. package/src/layer2/dangerous-functions/index.ts +1533 -0
  446. package/src/layer2/dangerous-functions/json-parse.ts +385 -0
  447. package/src/layer2/dangerous-functions/math-random.ts +789 -0
  448. package/src/layer2/dangerous-functions/patterns.ts +176 -0
  449. package/src/layer2/dangerous-functions/request-validation.ts +145 -0
  450. package/src/layer2/dangerous-functions/utils/control-flow.ts +35 -0
  451. package/src/layer2/dangerous-functions/utils/helpers.ts +170 -0
  452. package/src/layer2/dangerous-functions/utils/index.ts +25 -0
  453. package/src/layer2/dangerous-functions/utils/schema-validation.ts +106 -0
  454. package/src/layer2/data-exposure.ts +18 -39
  455. package/src/layer2/framework-checks.ts +9 -2
  456. package/src/layer2/index.ts +124 -43
  457. package/src/layer2/logic-gates.ts +64 -22
  458. package/src/layer2/model-supply-chain.ts +531 -0
  459. package/src/layer2/risky-imports.ts +9 -2
  460. package/src/layer2/variables.ts +9 -2
  461. package/src/layer3/__tests__/osv-check.test.ts +384 -0
  462. package/src/layer3/anthropic/auto-dismiss.ts +223 -0
  463. package/src/layer3/anthropic/clients.ts +84 -0
  464. package/src/layer3/anthropic/index.ts +170 -0
  465. package/src/layer3/anthropic/prompts/index.ts +14 -0
  466. package/src/layer3/anthropic/prompts/semantic-analysis.ts +173 -0
  467. package/src/layer3/anthropic/prompts/validation.ts +419 -0
  468. package/src/layer3/anthropic/providers/anthropic.ts +310 -0
  469. package/src/layer3/anthropic/providers/index.ts +8 -0
  470. package/src/layer3/anthropic/providers/openai.ts +384 -0
  471. package/src/layer3/anthropic/request-builder.ts +150 -0
  472. package/src/layer3/anthropic/types.ts +148 -0
  473. package/src/layer3/anthropic/utils/index.ts +26 -0
  474. package/src/layer3/anthropic/utils/path-helpers.ts +68 -0
  475. package/src/layer3/anthropic/utils/response-parser.ts +322 -0
  476. package/src/layer3/anthropic/utils/retry.ts +75 -0
  477. package/src/layer3/index.ts +18 -5
  478. package/src/layer3/osv-check.ts +420 -0
  479. package/src/modes/incremental.ts +1 -1
  480. package/src/rules/__tests__/framework-fixes.test.ts +689 -0
  481. package/src/rules/__tests__/metadata.test.ts +218 -0
  482. package/src/rules/framework-fixes.ts +470 -0
  483. package/src/rules/index.ts +21 -0
  484. package/src/rules/metadata.ts +831 -0
  485. package/src/suppression/__tests__/config-loader.test.ts +382 -0
  486. package/src/suppression/__tests__/hash.test.ts +166 -0
  487. package/src/suppression/__tests__/inline-parser.test.ts +212 -0
  488. package/src/suppression/__tests__/manager.test.ts +415 -0
  489. package/src/suppression/config-loader.ts +462 -0
  490. package/src/suppression/hash.ts +95 -0
  491. package/src/suppression/index.ts +51 -0
  492. package/src/suppression/inline-parser.ts +273 -0
  493. package/src/suppression/manager.ts +379 -0
  494. package/src/suppression/types.ts +174 -0
  495. package/src/tiers.ts +45 -9
  496. package/src/types.ts +212 -8
  497. package/src/utils/__tests__/code-analysis.test.ts +165 -0
  498. package/src/utils/__tests__/parsed-file.test.ts +124 -0
  499. package/src/utils/code-analysis.ts +179 -0
  500. package/src/utils/comment-analyzer.ts +249 -0
  501. package/src/utils/context-helpers.ts +421 -11
  502. package/src/utils/environment-context.ts +304 -0
  503. package/src/utils/intent-detector.ts +318 -0
  504. package/src/utils/parsed-file.ts +103 -0
  505. package/src/utils/route-hierarchy.ts +250 -0
  506. package/src/utils/schema-semantics.ts +233 -0
  507. package/dist/layer2/dangerous-functions.d.ts +0 -7
  508. package/dist/layer2/dangerous-functions.d.ts.map +0 -1
  509. package/dist/layer2/dangerous-functions.js +0 -1701
  510. package/dist/layer2/dangerous-functions.js.map +0 -1
  511. package/dist/layer3/anthropic.d.ts +0 -87
  512. package/dist/layer3/anthropic.d.ts.map +0 -1
  513. package/dist/layer3/anthropic.js +0 -1948
  514. package/dist/layer3/anthropic.js.map +0 -1
  515. package/dist/layer3/openai.d.ts +0 -25
  516. package/dist/layer3/openai.d.ts.map +0 -1
  517. package/dist/layer3/openai.js +0 -238
  518. package/dist/layer3/openai.js.map +0 -1
  519. package/src/layer2/dangerous-functions.ts +0 -1940
  520. package/src/layer3/anthropic.ts +0 -2257
@@ -9,11 +9,16 @@
9
9
  */
10
10
 
11
11
  import type { Vulnerability, VulnerabilitySeverity } from '../types'
12
+ import type { ParsedFile } from '../utils/parsed-file'
12
13
  import type { MiddlewareAuthConfig } from '../utils/middleware-detector'
13
14
  import { isRouteProtectedByMiddleware, getRoutePathFromFile } from '../utils/middleware-detector'
14
15
  import type { AuthHelper, AuthHelperContext } from '../utils/auth-helper-detector'
15
16
  import { hasAuthHelperCallBefore, isUserIdAlreadyValidated } from '../utils/auth-helper-detector'
16
17
  import type { FileAuthImports } from '../utils/imported-auth-detector'
18
+ import { isScannerOrFixtureFile } from '../utils/context-helpers'
19
+ import { getRouteProtectionContext, isAuthenticatedOnlyComponent } from '../utils/route-hierarchy'
20
+ import { is2FAOrValidation } from '../utils/schema-semantics'
21
+ import { isPasswordErrorCode, hasPasswordValueInError } from '../utils/intent-detector'
17
22
 
18
23
  interface AuthAntiPattern {
19
24
  name: string
@@ -78,13 +83,10 @@ const AUTH_ANTIPATTERNS: AuthAntiPattern[] = [
78
83
  description: 'Session configuration may lack secure flag',
79
84
  suggestedFix: 'Set secure: true for cookies in production',
80
85
  },
81
- {
82
- name: 'Cookie without httpOnly',
83
- pattern: /cookie\s*\(\s*['"][^'"]+['"]\s*,[^)]*(?!httpOnly)[^)]*\)|setCookie\s*\([^)]*(?!httpOnly)/gi,
84
- severity: 'medium',
85
- description: 'Cookie set without httpOnly flag',
86
- suggestedFix: 'Add httpOnly: true to prevent XSS access to cookies',
87
- },
86
+ // NOTE: Cookie httpOnly detection removed - causes false positives
87
+ // Client-side code (document.cookie) cannot set httpOnly - it's a server-only flag
88
+ // Server-side cookie libraries have proper defaults
89
+ // The pattern was triggering on client-side cookie access which is conceptually wrong
88
90
 
89
91
  // Authorization issues
90
92
  // NOTE: We intentionally do NOT flag "if (!user)" or "if (!userId)" patterns as issues
@@ -122,12 +124,17 @@ const AUTH_ANTIPATTERNS: AuthAntiPattern[] = [
122
124
  },
123
125
 
124
126
  // OAuth/Social auth issues
127
+ // NOTE: OAuth detection narrowed significantly to reduce false positives.
128
+ // Previously matched any line containing "oauth" which flagged variable names, imports, etc.
129
+ // Now only matches actual OAuth authorization URL construction.
125
130
  {
126
131
  name: 'OAuth state parameter missing',
127
- pattern: /oauth|authorize\?.*(?!state=)/gi,
132
+ // Only match actual OAuth authorization URL construction without state parameter
133
+ // Must have: authorize endpoint + client_id/redirect_uri but missing state
134
+ pattern: /['"`]https?:\/\/[^'"]*\/(?:oauth|authorize|auth)[^'"]*client_id=[^'"]*(?!.*state=)/gi,
128
135
  severity: 'medium',
129
- description: 'OAuth flow may lack state parameter for CSRF protection',
130
- suggestedFix: 'Include a random state parameter in OAuth requests',
136
+ description: 'OAuth authorization URL may lack state parameter for CSRF protection',
137
+ suggestedFix: 'Include a random state parameter in OAuth authorization requests',
131
138
  },
132
139
 
133
140
  // Password handling issues
@@ -138,13 +145,10 @@ const AUTH_ANTIPATTERNS: AuthAntiPattern[] = [
138
145
  description: 'Password may be logged to console',
139
146
  suggestedFix: 'Never log passwords or sensitive credentials',
140
147
  },
141
- {
142
- name: 'Password in error message',
143
- pattern: /throw\s+new\s+Error\s*\([^)]*password|Error\s*\([^)]*password/gi,
144
- severity: 'high',
145
- description: 'Password may be included in error message',
146
- suggestedFix: 'Never include passwords in error messages',
147
- },
148
+ // NOTE: 'Password in error message' pattern now uses smart intent detection
149
+ // Error CODES like 'SAME_PASSWORD' are not flagged (they're codes, not values)
150
+ // Only actual password values concatenated into errors are flagged
151
+ // This is handled specially in detectAuthAntipatterns() below
148
152
 
149
153
  // Rate limiting
150
154
  {
@@ -183,6 +187,37 @@ function isAuthRelatedFile(filePath: string): boolean {
183
187
  return authKeywords.some(keyword => lowerPath.includes(keyword))
184
188
  }
185
189
 
190
+ /**
191
+ * Check if file is an auth implementation/library file
192
+ * These files ARE the auth system - flagging them for "missing auth" is wrong
193
+ *
194
+ * Examples:
195
+ * - packages/auth/src/handlers.ts
196
+ * - lib/auth/middleware.ts
197
+ * - services/authentication/index.ts
198
+ */
199
+ function isAuthImplementationFile(filePath: string): boolean {
200
+ const authImplPatterns = [
201
+ /\/packages\/auth\//i,
202
+ /\/lib\/auth\//i,
203
+ /\/utils\/auth\//i,
204
+ /\/services\/auth/i,
205
+ /\/authentication\//i,
206
+ /\/auth-provider/i,
207
+ /\/auth-helpers/i,
208
+ /\/auth-utils/i,
209
+ /\/passport-/i, // Passport.js strategy files
210
+ /\/next-auth\//i, // NextAuth config
211
+ /\/lucia\//i, // Lucia auth
212
+ /\/better-auth\//i, // Better Auth
213
+ /\/supabase\/auth/i, // Supabase auth
214
+ /\/clerk\//i, // Clerk auth
215
+ /\/auth0\//i, // Auth0
216
+ /\/keycloak\//i, // Keycloak
217
+ ]
218
+ return authImplPatterns.some(p => p.test(filePath))
219
+ }
220
+
186
221
  // Check if endpoint is a known public endpoint (health checks, webhooks, cron)
187
222
  function isKnownPublicEndpoint(lineContent: string, filePath: string): boolean {
188
223
  const PUBLIC_ENDPOINTS = [
@@ -193,20 +228,60 @@ function isKnownPublicEndpoint(lineContent: string, filePath: string): boolean {
193
228
  /\/live\b/i,
194
229
  /\/ping\b/i,
195
230
  /\/status\b/i,
231
+ /\/_health/i,
196
232
 
197
233
  // Webhooks (receive external calls)
198
234
  /\/webhook\b/i,
199
235
  /\/webhooks\//i,
200
236
  /\/callback\b/i,
237
+ /\/stripe\/webhook/i,
238
+ /\/clerk\/webhook/i,
239
+ /\/svix\//i,
201
240
 
202
241
  // Cron/scheduled tasks
203
242
  /\/cron\//i,
204
243
  /\/scheduled\//i,
205
244
  /\/tasks\//i,
245
+ /\/jobs?\//i,
206
246
 
207
- // Public APIs
247
+ // Public APIs - intentionally unauthenticated
208
248
  /\/public\//i,
249
+ /\/openpage/i, // OpenPage API pattern (intentionally public)
250
+ /\/open-api\//i,
251
+ /\/api\/public\//i,
252
+ /\/api\/v\d+\/public\//i,
209
253
  /\bGET\b.*\/api\/\w+\/\[id\]/i, // Public resource reads with ID param
254
+
255
+ // Auth endpoints (must be public for users to authenticate)
256
+ /\/api\/auth\//i,
257
+ /\/auth\//i,
258
+ /\/login\b/i,
259
+ /\/signup\b/i,
260
+ /\/register\b/i,
261
+ /\/forgot-password/i,
262
+ /\/reset-password/i,
263
+ /\/verify-email/i,
264
+ /\/magic-link/i,
265
+ /\/oauth\//i,
266
+
267
+ // RSS/Atom feeds (typically public)
268
+ /\/feed\b/i,
269
+ /\/rss\b/i,
270
+ /\/atom\b/i,
271
+
272
+ // Sitemap/robots (always public)
273
+ /\/sitemap/i,
274
+ /\/robots/i,
275
+
276
+ // OpenGraph/meta endpoints
277
+ /\/og\//i,
278
+ /\/opengraph/i,
279
+ /\/meta\//i,
280
+
281
+ // Share/embed endpoints
282
+ /\/share\//i,
283
+ /\/embed\//i,
284
+ /\/widget\//i,
210
285
  ]
211
286
 
212
287
  return PUBLIC_ENDPOINTS.some(pattern =>
@@ -243,6 +318,47 @@ function hasAuthCheckNearby(lines: string[], lineIndex: number): boolean {
243
318
  /userApiKey|user_api_key|clientApiKey/i,
244
319
  /req\.body\.(?:apiKey|api_key|openaiKey|anthropicKey)/i,
245
320
  /headers\[['"`]x-(?:openai|api|anthropic)-key['"`]\]/i,
321
+
322
+ // Next.js / React auth patterns (expanded)
323
+ /const\s+session\s*=\s*await\s+auth\s*\(\)/, // const session = await auth()
324
+ /const\s+\{\s*session\s*\}\s*=\s*await\s+auth\s*\(\)/, // const { session } = await auth()
325
+ /if\s*\(\s*!session\?\.user/, // if (!session?.user)
326
+ /if\s*\(\s*!session\s*\)/, // if (!session)
327
+ /session\s*\?\.\s*user/, // session?.user
328
+ /getServerSession\s*\(\s*authOptions/, // getServerSession(authOptions)
329
+ /getServerSession\s*\(\s*req\s*,\s*res/, // getServerSession(req, res, ...)
330
+ /useSession\s*\(\)/, // useSession()
331
+ /signIn\s*\(/, // signIn()
332
+ /signOut\s*\(/, // signOut()
333
+
334
+ // Clerk auth patterns
335
+ /currentUser\s*\(\)/, // currentUser()
336
+ /auth\s*\(\)\s*\.\s*protect/, // auth().protect
337
+ /auth\s*\(\)\s*\.\s*userId/, // auth().userId
338
+ /clerkClient/i,
339
+ /getAuth\s*\(/,
340
+ /ClerkProvider/,
341
+
342
+ // Supabase auth patterns
343
+ /supabase\s*\.\s*auth\s*\.\s*getUser/, // supabase.auth.getUser()
344
+ /supabase\s*\.\s*auth\s*\.\s*getSession/, // supabase.auth.getSession()
345
+ /createServerClient/, // Supabase server client
346
+ /createRouteHandlerClient/,
347
+
348
+ // Lucia auth patterns
349
+ /lucia\s*\.\s*validateSession/,
350
+ /validateRequest/,
351
+
352
+ // Better Auth patterns
353
+ /betterAuth/,
354
+ /auth\.api\./,
355
+
356
+ // Throwing auth helpers (if these are called, route is authenticated)
357
+ /throw\s+new\s+Error\s*\(\s*['"]unauthorized/i,
358
+ /throw\s+new\s+Error\s*\(\s*['"]unauthenticated/i,
359
+ /ChatSDKError\s*\(\s*['"]unauthorized/i,
360
+ /return\s+new\s+Response\s*\(\s*.*401/,
361
+ /return\s+NextResponse\s*\.\s*json\s*\(\s*.*401/,
246
362
  ]
247
363
 
248
364
  return searchWindow.some(line =>
@@ -254,6 +370,7 @@ export interface AuthAntipatternOptions {
254
370
  middlewareConfig?: MiddlewareAuthConfig
255
371
  authHelpers?: AuthHelperContext
256
372
  fileAuthImports?: Map<string, FileAuthImports>
373
+ parsed?: ParsedFile
257
374
  }
258
375
 
259
376
  export function detectAuthAntipatterns(
@@ -261,10 +378,18 @@ export function detectAuthAntipatterns(
261
378
  filePath: string,
262
379
  options: AuthAntipatternOptions = {}
263
380
  ): Vulnerability[] {
264
- const { middlewareConfig, authHelpers, fileAuthImports } = options
381
+ const { middlewareConfig, authHelpers, fileAuthImports, parsed } = options
265
382
  const vulnerabilities: Vulnerability[] = []
266
- const lines = content.split('\n')
383
+
384
+ // Skip scanner/fixture files to avoid self-detection
385
+ if (isScannerOrFixtureFile(filePath)) return vulnerabilities
386
+
387
+ const lines = parsed?.lines ?? content.split('\n')
267
388
  const isAuthFile = isAuthRelatedFile(filePath)
389
+ const isAuthImpl = isAuthImplementationFile(filePath)
390
+
391
+ // Check framework route hierarchy protection (Remix, Next.js route groups)
392
+ const routeHierarchy = getRouteProtectionContext(filePath)
268
393
 
269
394
  // Check if this route is protected by global middleware
270
395
  const routePath = getRoutePathFromFile(filePath)
@@ -279,6 +404,9 @@ export function detectAuthAntipatterns(
279
404
  // Check if file uses throwing auth helpers
280
405
  const helpersList = authHelpers?.helpers || []
281
406
 
407
+ // Check if this is a component only used in authenticated contexts
408
+ const isAuthOnlyComponent = isAuthenticatedOnlyComponent(filePath)
409
+
282
410
  lines.forEach((line, index) => {
283
411
  // Skip comment lines
284
412
  if (isComment(line)) return
@@ -291,6 +419,12 @@ export function detectAuthAntipatterns(
291
419
  if (pattern.name === 'Unprotected API route' ||
292
420
  pattern.name === 'Express route without auth middleware') {
293
421
 
422
+ // PRIORITY -1: Skip auth implementation files entirely
423
+ // These files ARE the auth system - flagging them for "missing auth" is conceptually wrong
424
+ if (isAuthImpl) {
425
+ break // Skip this pattern
426
+ }
427
+
294
428
  // PRIORITY 0: Check if this is actually a route file
295
429
  // In Next.js, routes must be in `route.ts/js` files. Files like `handlers.ts`,
296
430
  // `safe-handlers.ts`, `utils.ts` etc. are NOT actual API routes even if they
@@ -308,6 +442,32 @@ export function detectAuthAntipatterns(
308
442
  break
309
443
  }
310
444
 
445
+ // PRIORITY 0.5: Check if route is in a protected route hierarchy
446
+ // Framework route conventions (Remix _authenticated+, Next.js route groups)
447
+ if (routeHierarchy.isInProtectedHierarchy) {
448
+ // Route is in a protected hierarchy - cap severity at info
449
+ vulnerabilities.push({
450
+ id: `auth-antipattern-${filePath}-${index + 1}-${pattern.name}`,
451
+ filePath,
452
+ lineNumber: index + 1,
453
+ lineContent: line.trim(),
454
+ severity: 'info',
455
+ category: 'missing_auth',
456
+ title: pattern.name + ' (in protected route hierarchy)',
457
+ description: `This route is within a protected route hierarchy (${routeHierarchy.protectionSource.join(', ')}). Authentication is likely handled by parent layout/middleware.`,
458
+ suggestedFix: 'Verify parent layout enforces authentication. If not, add auth check here.',
459
+ confidence: 'low',
460
+ layer: 2,
461
+ })
462
+ break // Only report once per line
463
+ }
464
+
465
+ // PRIORITY 0.75: Check if this is a component only used in authenticated contexts
466
+ if (isAuthOnlyComponent) {
467
+ // Component is in admin/dashboard/etc - skip entirely
468
+ break
469
+ }
470
+
311
471
  // PRIORITY 1: Check if route is protected by global middleware
312
472
  // This is the STRONGEST signal - if middleware protects the route, suppress entirely
313
473
  if (middlewareProtection.isProtected) {
@@ -390,5 +550,60 @@ export function detectAuthAntipatterns(
390
550
  }
391
551
  })
392
552
 
553
+ // Special handling: Password in error message with smart intent detection
554
+ // Only flag actual password VALUES, not error CODES like 'SAME_PASSWORD'
555
+ const passwordErrorPattern = /throw\s+new\s+Error\s*\([^)]*password|Error\s*\([^)]*password/gi
556
+ lines.forEach((line, index) => {
557
+ if (isComment(line)) return
558
+
559
+ if (passwordErrorPattern.test(line)) {
560
+ // Reset regex state
561
+ passwordErrorPattern.lastIndex = 0
562
+
563
+ // Skip if this is an error CODE, not a VALUE
564
+ if (isPasswordErrorCode(line)) {
565
+ return // This is fine - 'SAME_PASSWORD' is a code, not a value
566
+ }
567
+
568
+ // Only flag if actual password value is in the error
569
+ if (hasPasswordValueInError(line)) {
570
+ vulnerabilities.push({
571
+ id: `auth-antipattern-${filePath}-${index + 1}-password-in-error`,
572
+ filePath,
573
+ lineNumber: index + 1,
574
+ lineContent: line.trim(),
575
+ severity: 'high',
576
+ category: 'missing_auth',
577
+ title: 'Password value in error message',
578
+ description: 'Actual password value may be included in error message, exposing sensitive data.',
579
+ suggestedFix: 'Never include actual password values in error messages. Use error codes instead.',
580
+ confidence: 'high',
581
+ layer: 2,
582
+ })
583
+ }
584
+ }
585
+ })
586
+
587
+ // Special handling: 2FA optional fields with OR validation
588
+ // Don't flag .optional() on 2FA fields if there's .refine() enforcing OR logic
589
+ const twoFAOptionalPattern = /\.(totp|otp|backupCode|recoveryCode|twoFactor|2fa|mfa).*\.optional\s*\(\)/gi
590
+ lines.forEach((line, index) => {
591
+ if (isComment(line)) return
592
+
593
+ if (twoFAOptionalPattern.test(line)) {
594
+ // Reset regex state
595
+ twoFAOptionalPattern.lastIndex = 0
596
+
597
+ // Check if this is legitimate OR validation (either TOTP or backup code required)
598
+ if (is2FAOrValidation(content, index)) {
599
+ // This is legitimate OR validation - skip or report as info
600
+ return
601
+ }
602
+
603
+ // Only flag if this truly allows bypassing 2FA
604
+ // Most cases with .refine() are fine - this is handled by schema-semantics.ts
605
+ }
606
+ })
607
+
393
608
  return vulnerabilities
394
609
  }
@@ -5,8 +5,9 @@
5
5
  */
6
6
 
7
7
  import type { Vulnerability, VulnerabilitySeverity } from '../types'
8
+ import type { ParsedFile } from '../utils/parsed-file'
8
9
  import type { MiddlewareAuthConfig } from '../utils/middleware-detector'
9
- import { isComment, isTestOrMockFile, isExampleFile, isPlaceholderValue } from '../utils/context-helpers'
10
+ import { isComment, isTestOrMockFile, isExampleFile, isPlaceholderValue, isScannerOrFixtureFile } from '../utils/context-helpers'
10
11
  import { isRouteProtectedByMiddleware, getRoutePathFromFile, detectUserScopingPatterns } from '../utils/middleware-detector'
11
12
 
12
13
  /**
@@ -221,10 +222,15 @@ function isKeyLogged(content: string, lineNumber: number): boolean {
221
222
  export function detectBYOKPatterns(
222
223
  content: string,
223
224
  filePath: string,
224
- middlewareConfig?: MiddlewareAuthConfig
225
+ middlewareConfig?: MiddlewareAuthConfig,
226
+ options?: { parsed?: ParsedFile }
225
227
  ): Vulnerability[] {
226
228
  const vulnerabilities: Vulnerability[] = []
227
- const lines = content.split('\n')
229
+
230
+ // Skip scanner/fixture files to avoid self-detection
231
+ if (isScannerOrFixtureFile(filePath)) return vulnerabilities
232
+
233
+ const lines = options?.parsed?.lines ?? content.split('\n')
228
234
  const isTestFile = isTestOrMockFile(filePath)
229
235
 
230
236
  // Skip example/demo files entirely - they contain placeholder credentials by design
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Child Process Detection
3
+ *
4
+ * Detection logic for child_process functions (exec, spawn, execFile, etc.)
5
+ * that can lead to command injection vulnerabilities.
6
+ */
7
+
8
+ /**
9
+ * Check if exec() call is from child_process (dangerous) vs RegExp.exec (safe)
10
+ * Returns true if this is a child_process exec call that should be flagged
11
+ */
12
+ export function isChildProcessExec(content: string, lineContent: string): boolean {
13
+ // Check for child_process import
14
+ const hasChildProcessImport =
15
+ /require\s*\(\s*['"]child_process['"]\s*\)/.test(content) ||
16
+ /from\s+['"]child_process['"]/.test(content) ||
17
+ /import\s+.*child_process/.test(content) ||
18
+ /require\s*\(\s*['"]node:child_process['"]\s*\)/.test(content) ||
19
+ /from\s+['"]node:child_process['"]/.test(content)
20
+
21
+ // If no child_process import, this is likely RegExp.exec or similar
22
+ if (!hasChildProcessImport) {
23
+ return false
24
+ }
25
+
26
+ // Check if this specific line is RegExp.exec pattern
27
+ // RegExp.exec is called as: regex.exec(string) or /pattern/.exec(string)
28
+ const isRegExpExec =
29
+ /\.\s*exec\s*\(/.test(lineContent) && // Method call on an object
30
+ !/\bexec\s*\(/.test(lineContent.replace(/\.\s*exec\s*\(/, '')) // Not a standalone exec()
31
+
32
+ // Also check for common RegExp patterns
33
+ const isRegExpPattern =
34
+ /\/[^/]+\/[gimsuy]*\.exec\s*\(/.test(lineContent) || // /pattern/.exec()
35
+ /new\s+RegExp\s*\([^)]+\)\.exec\s*\(/.test(lineContent) || // new RegExp().exec()
36
+ /regex\.exec\s*\(/i.test(lineContent) || // regex.exec()
37
+ /pattern\.exec\s*\(/i.test(lineContent) || // pattern.exec()
38
+ /match\.exec\s*\(/i.test(lineContent) || // match.exec()
39
+ /re\.exec\s*\(/i.test(lineContent) // re.exec()
40
+
41
+ if (isRegExpExec || isRegExpPattern) {
42
+ return false
43
+ }
44
+
45
+ // Check if exec is imported/destructured from child_process
46
+ const execImported =
47
+ /\{\s*[^}]*\bexec\b[^}]*\}\s*=\s*require\s*\(\s*['"]child_process['"]/.test(
48
+ content
49
+ ) ||
50
+ /\{\s*[^}]*\bexec\b[^}]*\}\s*=\s*require\s*\(\s*['"]node:child_process['"]/.test(
51
+ content
52
+ ) ||
53
+ /import\s+\{\s*[^}]*\bexec\b[^}]*\}\s+from\s+['"]child_process['"]/.test(
54
+ content
55
+ ) ||
56
+ /import\s+\{\s*[^}]*\bexec\b[^}]*\}\s+from\s+['"]node:child_process['"]/.test(
57
+ content
58
+ )
59
+
60
+ // If exec is directly imported from child_process, standalone exec() is dangerous
61
+ if (execImported && /\bexec\s*\(/.test(lineContent)) {
62
+ return true
63
+ }
64
+
65
+ // Check for child_process.exec() pattern
66
+ if (
67
+ /child_process\.exec\s*\(/.test(lineContent) ||
68
+ /cp\.exec\s*\(/.test(lineContent) ||
69
+ /childProcess\.exec\s*\(/.test(lineContent)
70
+ ) {
71
+ return true
72
+ }
73
+
74
+ // If we have child_process import but can't determine usage, be conservative
75
+ // Only flag if it looks like a standalone exec() call
76
+ return /\bexec\s*\(/.test(lineContent) && !/\.\s*exec\s*\(/.test(lineContent)
77
+ }
78
+
79
+ /**
80
+ * Check if spawn/execFile/execSync is from child_process
81
+ */
82
+ export function isChildProcessSpawn(content: string, lineContent: string): boolean {
83
+ // Check for child_process import
84
+ const hasChildProcessImport =
85
+ /require\s*\(\s*['"]child_process['"]\s*\)/.test(content) ||
86
+ /from\s+['"]child_process['"]/.test(content) ||
87
+ /require\s*\(\s*['"]node:child_process['"]\s*\)/.test(content) ||
88
+ /from\s+['"]node:child_process['"]/.test(content)
89
+
90
+ if (!hasChildProcessImport) {
91
+ return false
92
+ }
93
+
94
+ // These functions are always from child_process when that module is imported
95
+ return /\b(spawn|spawnSync|execSync|execFile|execFileSync)\s*\(/.test(
96
+ lineContent
97
+ )
98
+ }