@oculum/scanner 1.0.9 → 1.0.11

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 (365) hide show
  1. package/dist/baseline/diff.d.ts +32 -0
  2. package/dist/baseline/diff.d.ts.map +1 -0
  3. package/dist/baseline/diff.js +119 -0
  4. package/dist/baseline/diff.js.map +1 -0
  5. package/dist/baseline/index.d.ts +9 -0
  6. package/dist/baseline/index.d.ts.map +1 -0
  7. package/dist/baseline/index.js +19 -0
  8. package/dist/baseline/index.js.map +1 -0
  9. package/dist/baseline/manager.d.ts +67 -0
  10. package/dist/baseline/manager.d.ts.map +1 -0
  11. package/dist/baseline/manager.js +180 -0
  12. package/dist/baseline/manager.js.map +1 -0
  13. package/dist/baseline/types.d.ts +91 -0
  14. package/dist/baseline/types.d.ts.map +1 -0
  15. package/dist/baseline/types.js +12 -0
  16. package/dist/baseline/types.js.map +1 -0
  17. package/dist/formatters/cli-terminal.d.ts +38 -0
  18. package/dist/formatters/cli-terminal.d.ts.map +1 -1
  19. package/dist/formatters/cli-terminal.js +365 -42
  20. package/dist/formatters/cli-terminal.js.map +1 -1
  21. package/dist/formatters/github-comment.d.ts +1 -1
  22. package/dist/formatters/github-comment.d.ts.map +1 -1
  23. package/dist/formatters/github-comment.js +75 -11
  24. package/dist/formatters/github-comment.js.map +1 -1
  25. package/dist/formatters/index.d.ts +1 -1
  26. package/dist/formatters/index.d.ts.map +1 -1
  27. package/dist/formatters/index.js +4 -1
  28. package/dist/formatters/index.js.map +1 -1
  29. package/dist/index.d.ts +7 -0
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +155 -16
  32. package/dist/index.js.map +1 -1
  33. package/dist/layer1/config-audit.d.ts.map +1 -1
  34. package/dist/layer1/config-audit.js +20 -3
  35. package/dist/layer1/config-audit.js.map +1 -1
  36. package/dist/layer1/config-mcp-audit.d.ts +20 -0
  37. package/dist/layer1/config-mcp-audit.d.ts.map +1 -0
  38. package/dist/layer1/config-mcp-audit.js +239 -0
  39. package/dist/layer1/config-mcp-audit.js.map +1 -0
  40. package/dist/layer1/index.d.ts +1 -0
  41. package/dist/layer1/index.d.ts.map +1 -1
  42. package/dist/layer1/index.js +9 -1
  43. package/dist/layer1/index.js.map +1 -1
  44. package/dist/layer2/ai-agent-tools.d.ts.map +1 -1
  45. package/dist/layer2/ai-agent-tools.js +303 -0
  46. package/dist/layer2/ai-agent-tools.js.map +1 -1
  47. package/dist/layer2/ai-endpoint-protection.d.ts.map +1 -1
  48. package/dist/layer2/ai-endpoint-protection.js +17 -3
  49. package/dist/layer2/ai-endpoint-protection.js.map +1 -1
  50. package/dist/layer2/ai-execution-sinks.d.ts.map +1 -1
  51. package/dist/layer2/ai-execution-sinks.js +462 -12
  52. package/dist/layer2/ai-execution-sinks.js.map +1 -1
  53. package/dist/layer2/ai-fingerprinting.d.ts.map +1 -1
  54. package/dist/layer2/ai-fingerprinting.js +3 -0
  55. package/dist/layer2/ai-fingerprinting.js.map +1 -1
  56. package/dist/layer2/ai-mcp-security.d.ts +17 -0
  57. package/dist/layer2/ai-mcp-security.d.ts.map +1 -0
  58. package/dist/layer2/ai-mcp-security.js +679 -0
  59. package/dist/layer2/ai-mcp-security.js.map +1 -0
  60. package/dist/layer2/ai-package-hallucination.d.ts +19 -0
  61. package/dist/layer2/ai-package-hallucination.d.ts.map +1 -0
  62. package/dist/layer2/ai-package-hallucination.js +696 -0
  63. package/dist/layer2/ai-package-hallucination.js.map +1 -0
  64. package/dist/layer2/ai-prompt-hygiene.d.ts.map +1 -1
  65. package/dist/layer2/ai-prompt-hygiene.js +495 -9
  66. package/dist/layer2/ai-prompt-hygiene.js.map +1 -1
  67. package/dist/layer2/ai-rag-safety.d.ts.map +1 -1
  68. package/dist/layer2/ai-rag-safety.js +372 -1
  69. package/dist/layer2/ai-rag-safety.js.map +1 -1
  70. package/dist/layer2/auth-antipatterns.d.ts.map +1 -1
  71. package/dist/layer2/auth-antipatterns.js +4 -0
  72. package/dist/layer2/auth-antipatterns.js.map +1 -1
  73. package/dist/layer2/byok-patterns.d.ts.map +1 -1
  74. package/dist/layer2/byok-patterns.js +3 -0
  75. package/dist/layer2/byok-patterns.js.map +1 -1
  76. package/dist/layer2/dangerous-functions/child-process.d.ts +16 -0
  77. package/dist/layer2/dangerous-functions/child-process.d.ts.map +1 -0
  78. package/dist/layer2/dangerous-functions/child-process.js +74 -0
  79. package/dist/layer2/dangerous-functions/child-process.js.map +1 -0
  80. package/dist/layer2/dangerous-functions/dom-xss.d.ts +29 -0
  81. package/dist/layer2/dangerous-functions/dom-xss.d.ts.map +1 -0
  82. package/dist/layer2/dangerous-functions/dom-xss.js +179 -0
  83. package/dist/layer2/dangerous-functions/dom-xss.js.map +1 -0
  84. package/dist/layer2/dangerous-functions/index.d.ts +13 -0
  85. package/dist/layer2/dangerous-functions/index.d.ts.map +1 -0
  86. package/dist/layer2/dangerous-functions/index.js +621 -0
  87. package/dist/layer2/dangerous-functions/index.js.map +1 -0
  88. package/dist/layer2/dangerous-functions/json-parse.d.ts +31 -0
  89. package/dist/layer2/dangerous-functions/json-parse.d.ts.map +1 -0
  90. package/dist/layer2/dangerous-functions/json-parse.js +319 -0
  91. package/dist/layer2/dangerous-functions/json-parse.js.map +1 -0
  92. package/dist/layer2/dangerous-functions/math-random.d.ts +61 -0
  93. package/dist/layer2/dangerous-functions/math-random.d.ts.map +1 -0
  94. package/dist/layer2/dangerous-functions/math-random.js +459 -0
  95. package/dist/layer2/dangerous-functions/math-random.js.map +1 -0
  96. package/dist/layer2/dangerous-functions/patterns.d.ts +21 -0
  97. package/dist/layer2/dangerous-functions/patterns.d.ts.map +1 -0
  98. package/dist/layer2/dangerous-functions/patterns.js +161 -0
  99. package/dist/layer2/dangerous-functions/patterns.js.map +1 -0
  100. package/dist/layer2/dangerous-functions/request-validation.d.ts +13 -0
  101. package/dist/layer2/dangerous-functions/request-validation.d.ts.map +1 -0
  102. package/dist/layer2/dangerous-functions/request-validation.js +119 -0
  103. package/dist/layer2/dangerous-functions/request-validation.js.map +1 -0
  104. package/dist/layer2/dangerous-functions/utils/control-flow.d.ts +23 -0
  105. package/dist/layer2/dangerous-functions/utils/control-flow.d.ts.map +1 -0
  106. package/dist/layer2/dangerous-functions/utils/control-flow.js +149 -0
  107. package/dist/layer2/dangerous-functions/utils/control-flow.js.map +1 -0
  108. package/dist/layer2/dangerous-functions/utils/helpers.d.ts +31 -0
  109. package/dist/layer2/dangerous-functions/utils/helpers.d.ts.map +1 -0
  110. package/dist/layer2/dangerous-functions/utils/helpers.js +124 -0
  111. package/dist/layer2/dangerous-functions/utils/helpers.js.map +1 -0
  112. package/dist/layer2/dangerous-functions/utils/index.d.ts +9 -0
  113. package/dist/layer2/dangerous-functions/utils/index.d.ts.map +1 -0
  114. package/dist/layer2/dangerous-functions/utils/index.js +23 -0
  115. package/dist/layer2/dangerous-functions/utils/index.js.map +1 -0
  116. package/dist/layer2/dangerous-functions/utils/schema-validation.d.ts +22 -0
  117. package/dist/layer2/dangerous-functions/utils/schema-validation.d.ts.map +1 -0
  118. package/dist/layer2/dangerous-functions/utils/schema-validation.js +89 -0
  119. package/dist/layer2/dangerous-functions/utils/schema-validation.js.map +1 -0
  120. package/dist/layer2/data-exposure.d.ts.map +1 -1
  121. package/dist/layer2/data-exposure.js +3 -0
  122. package/dist/layer2/data-exposure.js.map +1 -1
  123. package/dist/layer2/framework-checks.d.ts.map +1 -1
  124. package/dist/layer2/framework-checks.js +3 -0
  125. package/dist/layer2/framework-checks.js.map +1 -1
  126. package/dist/layer2/index.d.ts +3 -0
  127. package/dist/layer2/index.d.ts.map +1 -1
  128. package/dist/layer2/index.js +61 -2
  129. package/dist/layer2/index.js.map +1 -1
  130. package/dist/layer2/logic-gates.d.ts.map +1 -1
  131. package/dist/layer2/logic-gates.js +4 -0
  132. package/dist/layer2/logic-gates.js.map +1 -1
  133. package/dist/layer2/model-supply-chain.d.ts +20 -0
  134. package/dist/layer2/model-supply-chain.d.ts.map +1 -0
  135. package/dist/layer2/model-supply-chain.js +376 -0
  136. package/dist/layer2/model-supply-chain.js.map +1 -0
  137. package/dist/layer2/risky-imports.d.ts.map +1 -1
  138. package/dist/layer2/risky-imports.js +4 -0
  139. package/dist/layer2/risky-imports.js.map +1 -1
  140. package/dist/layer2/variables.d.ts.map +1 -1
  141. package/dist/layer2/variables.js +4 -0
  142. package/dist/layer2/variables.js.map +1 -1
  143. package/dist/layer3/anthropic/auto-dismiss.d.ts +24 -0
  144. package/dist/layer3/anthropic/auto-dismiss.d.ts.map +1 -0
  145. package/dist/layer3/anthropic/auto-dismiss.js +188 -0
  146. package/dist/layer3/anthropic/auto-dismiss.js.map +1 -0
  147. package/dist/layer3/anthropic/clients.d.ts +44 -0
  148. package/dist/layer3/anthropic/clients.d.ts.map +1 -0
  149. package/dist/layer3/anthropic/clients.js +81 -0
  150. package/dist/layer3/anthropic/clients.js.map +1 -0
  151. package/dist/layer3/anthropic/index.d.ts +41 -0
  152. package/dist/layer3/anthropic/index.d.ts.map +1 -0
  153. package/dist/layer3/anthropic/index.js +141 -0
  154. package/dist/layer3/anthropic/index.js.map +1 -0
  155. package/dist/layer3/anthropic/prompts/index.d.ts +8 -0
  156. package/dist/layer3/anthropic/prompts/index.d.ts.map +1 -0
  157. package/dist/layer3/anthropic/prompts/index.js +14 -0
  158. package/dist/layer3/anthropic/prompts/index.js.map +1 -0
  159. package/dist/layer3/anthropic/prompts/semantic-analysis.d.ts +15 -0
  160. package/dist/layer3/anthropic/prompts/semantic-analysis.d.ts.map +1 -0
  161. package/dist/layer3/anthropic/prompts/semantic-analysis.js +169 -0
  162. package/dist/layer3/anthropic/prompts/semantic-analysis.js.map +1 -0
  163. package/dist/layer3/anthropic/prompts/validation.d.ts +12 -0
  164. package/dist/layer3/anthropic/prompts/validation.d.ts.map +1 -0
  165. package/dist/layer3/anthropic/prompts/validation.js +421 -0
  166. package/dist/layer3/anthropic/prompts/validation.js.map +1 -0
  167. package/dist/layer3/anthropic/providers/anthropic.d.ts +21 -0
  168. package/dist/layer3/anthropic/providers/anthropic.d.ts.map +1 -0
  169. package/dist/layer3/anthropic/providers/anthropic.js +266 -0
  170. package/dist/layer3/anthropic/providers/anthropic.js.map +1 -0
  171. package/dist/layer3/anthropic/providers/index.d.ts +8 -0
  172. package/dist/layer3/anthropic/providers/index.d.ts.map +1 -0
  173. package/dist/layer3/anthropic/providers/index.js +15 -0
  174. package/dist/layer3/anthropic/providers/index.js.map +1 -0
  175. package/dist/layer3/anthropic/providers/openai.d.ts +18 -0
  176. package/dist/layer3/anthropic/providers/openai.d.ts.map +1 -0
  177. package/dist/layer3/anthropic/providers/openai.js +340 -0
  178. package/dist/layer3/anthropic/providers/openai.js.map +1 -0
  179. package/dist/layer3/anthropic/request-builder.d.ts +20 -0
  180. package/dist/layer3/anthropic/request-builder.d.ts.map +1 -0
  181. package/dist/layer3/anthropic/request-builder.js +134 -0
  182. package/dist/layer3/anthropic/request-builder.js.map +1 -0
  183. package/dist/layer3/anthropic/types.d.ts +88 -0
  184. package/dist/layer3/anthropic/types.d.ts.map +1 -0
  185. package/dist/layer3/anthropic/types.js +38 -0
  186. package/dist/layer3/anthropic/types.js.map +1 -0
  187. package/dist/layer3/anthropic/utils/index.d.ts +9 -0
  188. package/dist/layer3/anthropic/utils/index.d.ts.map +1 -0
  189. package/dist/layer3/anthropic/utils/index.js +24 -0
  190. package/dist/layer3/anthropic/utils/index.js.map +1 -0
  191. package/dist/layer3/anthropic/utils/path-helpers.d.ts +21 -0
  192. package/dist/layer3/anthropic/utils/path-helpers.d.ts.map +1 -0
  193. package/dist/layer3/anthropic/utils/path-helpers.js +69 -0
  194. package/dist/layer3/anthropic/utils/path-helpers.js.map +1 -0
  195. package/dist/layer3/anthropic/utils/response-parser.d.ts +40 -0
  196. package/dist/layer3/anthropic/utils/response-parser.d.ts.map +1 -0
  197. package/dist/layer3/anthropic/utils/response-parser.js +285 -0
  198. package/dist/layer3/anthropic/utils/response-parser.js.map +1 -0
  199. package/dist/layer3/anthropic/utils/retry.d.ts +15 -0
  200. package/dist/layer3/anthropic/utils/retry.d.ts.map +1 -0
  201. package/dist/layer3/anthropic/utils/retry.js +62 -0
  202. package/dist/layer3/anthropic/utils/retry.js.map +1 -0
  203. package/dist/layer3/index.d.ts +1 -0
  204. package/dist/layer3/index.d.ts.map +1 -1
  205. package/dist/layer3/index.js +16 -6
  206. package/dist/layer3/index.js.map +1 -1
  207. package/dist/layer3/osv-check.d.ts +75 -0
  208. package/dist/layer3/osv-check.d.ts.map +1 -0
  209. package/dist/layer3/osv-check.js +308 -0
  210. package/dist/layer3/osv-check.js.map +1 -0
  211. package/dist/rules/framework-fixes.d.ts +48 -0
  212. package/dist/rules/framework-fixes.d.ts.map +1 -0
  213. package/dist/rules/framework-fixes.js +439 -0
  214. package/dist/rules/framework-fixes.js.map +1 -0
  215. package/dist/rules/index.d.ts +8 -0
  216. package/dist/rules/index.d.ts.map +1 -0
  217. package/dist/rules/index.js +18 -0
  218. package/dist/rules/index.js.map +1 -0
  219. package/dist/rules/metadata.d.ts +43 -0
  220. package/dist/rules/metadata.d.ts.map +1 -0
  221. package/dist/rules/metadata.js +734 -0
  222. package/dist/rules/metadata.js.map +1 -0
  223. package/dist/suppression/config-loader.d.ts +74 -0
  224. package/dist/suppression/config-loader.d.ts.map +1 -0
  225. package/dist/suppression/config-loader.js +424 -0
  226. package/dist/suppression/config-loader.js.map +1 -0
  227. package/dist/suppression/hash.d.ts +48 -0
  228. package/dist/suppression/hash.d.ts.map +1 -0
  229. package/dist/suppression/hash.js +88 -0
  230. package/dist/suppression/hash.js.map +1 -0
  231. package/dist/suppression/index.d.ts +11 -0
  232. package/dist/suppression/index.d.ts.map +1 -0
  233. package/dist/suppression/index.js +39 -0
  234. package/dist/suppression/index.js.map +1 -0
  235. package/dist/suppression/inline-parser.d.ts +39 -0
  236. package/dist/suppression/inline-parser.d.ts.map +1 -0
  237. package/dist/suppression/inline-parser.js +218 -0
  238. package/dist/suppression/inline-parser.js.map +1 -0
  239. package/dist/suppression/manager.d.ts +94 -0
  240. package/dist/suppression/manager.d.ts.map +1 -0
  241. package/dist/suppression/manager.js +292 -0
  242. package/dist/suppression/manager.js.map +1 -0
  243. package/dist/suppression/types.d.ts +151 -0
  244. package/dist/suppression/types.d.ts.map +1 -0
  245. package/dist/suppression/types.js +28 -0
  246. package/dist/suppression/types.js.map +1 -0
  247. package/dist/tiers.d.ts +1 -1
  248. package/dist/tiers.d.ts.map +1 -1
  249. package/dist/tiers.js +27 -0
  250. package/dist/tiers.js.map +1 -1
  251. package/dist/types.d.ts +62 -1
  252. package/dist/types.d.ts.map +1 -1
  253. package/dist/types.js.map +1 -1
  254. package/dist/utils/context-helpers.d.ts +4 -0
  255. package/dist/utils/context-helpers.d.ts.map +1 -1
  256. package/dist/utils/context-helpers.js +13 -9
  257. package/dist/utils/context-helpers.js.map +1 -1
  258. package/package.json +4 -2
  259. package/src/__tests__/benchmark/fixtures/layer1/mcp-config-audit.json +31 -0
  260. package/src/__tests__/benchmark/fixtures/layer2/ai-execution-sinks.ts +1489 -82
  261. package/src/__tests__/benchmark/fixtures/layer2/ai-mcp-security.ts +495 -0
  262. package/src/__tests__/benchmark/fixtures/layer2/ai-package-hallucination.ts +255 -0
  263. package/src/__tests__/benchmark/fixtures/layer2/ai-prompt-hygiene.ts +300 -1
  264. package/src/__tests__/benchmark/fixtures/layer2/ai-rag-safety.ts +139 -0
  265. package/src/__tests__/benchmark/fixtures/layer2/byok-patterns.ts +7 -0
  266. package/src/__tests__/benchmark/fixtures/layer2/data-exposure.ts +63 -0
  267. package/src/__tests__/benchmark/fixtures/layer2/excessive-agency.ts +221 -0
  268. package/src/__tests__/benchmark/fixtures/layer2/index.ts +18 -0
  269. package/src/__tests__/benchmark/fixtures/layer2/model-supply-chain.ts +204 -0
  270. package/src/__tests__/benchmark/fixtures/layer2/phase1-enhancements.ts +157 -0
  271. package/src/__tests__/snapshots/__snapshots__/anthropic-validation-refactor.test.ts.snap +758 -0
  272. package/src/__tests__/snapshots/__snapshots__/dangerous-functions-refactor.test.ts.snap +503 -0
  273. package/src/__tests__/snapshots/anthropic-validation-refactor.test.ts +321 -0
  274. package/src/__tests__/snapshots/dangerous-functions-refactor.test.ts +439 -0
  275. package/src/baseline/__tests__/diff.test.ts +261 -0
  276. package/src/baseline/__tests__/manager.test.ts +225 -0
  277. package/src/baseline/diff.ts +135 -0
  278. package/src/baseline/index.ts +29 -0
  279. package/src/baseline/manager.ts +230 -0
  280. package/src/baseline/types.ts +97 -0
  281. package/src/formatters/cli-terminal.ts +444 -41
  282. package/src/formatters/github-comment.ts +79 -11
  283. package/src/formatters/index.ts +4 -0
  284. package/src/index.ts +197 -14
  285. package/src/layer1/config-audit.ts +24 -3
  286. package/src/layer1/config-mcp-audit.ts +276 -0
  287. package/src/layer1/index.ts +16 -6
  288. package/src/layer2/ai-agent-tools.ts +336 -0
  289. package/src/layer2/ai-endpoint-protection.ts +16 -3
  290. package/src/layer2/ai-execution-sinks.ts +516 -12
  291. package/src/layer2/ai-fingerprinting.ts +5 -1
  292. package/src/layer2/ai-mcp-security.ts +730 -0
  293. package/src/layer2/ai-package-hallucination.ts +791 -0
  294. package/src/layer2/ai-prompt-hygiene.ts +547 -9
  295. package/src/layer2/ai-rag-safety.ts +382 -3
  296. package/src/layer2/auth-antipatterns.ts +5 -0
  297. package/src/layer2/byok-patterns.ts +5 -1
  298. package/src/layer2/dangerous-functions/child-process.ts +98 -0
  299. package/src/layer2/dangerous-functions/dom-xss.ts +220 -0
  300. package/src/layer2/dangerous-functions/index.ts +949 -0
  301. package/src/layer2/dangerous-functions/json-parse.ts +385 -0
  302. package/src/layer2/dangerous-functions/math-random.ts +537 -0
  303. package/src/layer2/dangerous-functions/patterns.ts +174 -0
  304. package/src/layer2/dangerous-functions/request-validation.ts +145 -0
  305. package/src/layer2/dangerous-functions/utils/control-flow.ts +162 -0
  306. package/src/layer2/dangerous-functions/utils/helpers.ts +170 -0
  307. package/src/layer2/dangerous-functions/utils/index.ts +25 -0
  308. package/src/layer2/dangerous-functions/utils/schema-validation.ts +91 -0
  309. package/src/layer2/data-exposure.ts +5 -1
  310. package/src/layer2/framework-checks.ts +5 -0
  311. package/src/layer2/index.ts +63 -1
  312. package/src/layer2/logic-gates.ts +5 -0
  313. package/src/layer2/model-supply-chain.ts +456 -0
  314. package/src/layer2/risky-imports.ts +5 -0
  315. package/src/layer2/variables.ts +5 -0
  316. package/src/layer3/__tests__/osv-check.test.ts +384 -0
  317. package/src/layer3/anthropic/auto-dismiss.ts +212 -0
  318. package/src/layer3/anthropic/clients.ts +84 -0
  319. package/src/layer3/anthropic/index.ts +170 -0
  320. package/src/layer3/anthropic/prompts/index.ts +14 -0
  321. package/src/layer3/anthropic/prompts/semantic-analysis.ts +173 -0
  322. package/src/layer3/anthropic/prompts/validation.ts +419 -0
  323. package/src/layer3/anthropic/providers/anthropic.ts +310 -0
  324. package/src/layer3/anthropic/providers/index.ts +8 -0
  325. package/src/layer3/anthropic/providers/openai.ts +384 -0
  326. package/src/layer3/anthropic/request-builder.ts +150 -0
  327. package/src/layer3/anthropic/types.ts +148 -0
  328. package/src/layer3/anthropic/utils/index.ts +26 -0
  329. package/src/layer3/anthropic/utils/path-helpers.ts +68 -0
  330. package/src/layer3/anthropic/utils/response-parser.ts +322 -0
  331. package/src/layer3/anthropic/utils/retry.ts +75 -0
  332. package/src/layer3/index.ts +18 -5
  333. package/src/layer3/osv-check.ts +420 -0
  334. package/src/rules/__tests__/framework-fixes.test.ts +689 -0
  335. package/src/rules/__tests__/metadata.test.ts +218 -0
  336. package/src/rules/framework-fixes.ts +470 -0
  337. package/src/rules/index.ts +21 -0
  338. package/src/rules/metadata.ts +831 -0
  339. package/src/suppression/__tests__/config-loader.test.ts +382 -0
  340. package/src/suppression/__tests__/hash.test.ts +166 -0
  341. package/src/suppression/__tests__/inline-parser.test.ts +212 -0
  342. package/src/suppression/__tests__/manager.test.ts +415 -0
  343. package/src/suppression/config-loader.ts +462 -0
  344. package/src/suppression/hash.ts +95 -0
  345. package/src/suppression/index.ts +51 -0
  346. package/src/suppression/inline-parser.ts +273 -0
  347. package/src/suppression/manager.ts +379 -0
  348. package/src/suppression/types.ts +174 -0
  349. package/src/tiers.ts +36 -0
  350. package/src/types.ts +90 -0
  351. package/src/utils/context-helpers.ts +13 -9
  352. package/dist/layer2/dangerous-functions.d.ts +0 -7
  353. package/dist/layer2/dangerous-functions.d.ts.map +0 -1
  354. package/dist/layer2/dangerous-functions.js +0 -1701
  355. package/dist/layer2/dangerous-functions.js.map +0 -1
  356. package/dist/layer3/anthropic.d.ts +0 -87
  357. package/dist/layer3/anthropic.d.ts.map +0 -1
  358. package/dist/layer3/anthropic.js +0 -1948
  359. package/dist/layer3/anthropic.js.map +0 -1
  360. package/dist/layer3/openai.d.ts +0 -25
  361. package/dist/layer3/openai.d.ts.map +0 -1
  362. package/dist/layer3/openai.js +0 -238
  363. package/dist/layer3/openai.js.map +0 -1
  364. package/src/layer2/dangerous-functions.ts +0 -1940
  365. package/src/layer3/anthropic.ts +0 -2257
@@ -0,0 +1,310 @@
1
+ /**
2
+ * Anthropic Provider Implementation
3
+ *
4
+ * Validation using Anthropic Claude 3.5 Haiku model.
5
+ */
6
+
7
+ import type { Vulnerability, ScanFile, ValidationStatus } from '../../../types'
8
+ import type { ProjectContext } from '../../../utils/project-context-builder'
9
+ import { buildProjectContext } from '../../../utils/project-context-builder'
10
+ import type { ValidationStats, AIValidationResult } from '../types'
11
+ import { getAnthropicClient, HAIKU_PRICING, FILES_PER_API_BATCH } from '../clients'
12
+ import { makeAnthropicRequestWithRetry } from '../utils/retry'
13
+ import { parseMultiFileValidationResponse, parseValidationResponse, applyValidationResults } from '../utils/response-parser'
14
+ import { buildMultiFileValidationRequest } from '../request-builder'
15
+ import { HIGH_CONTEXT_VALIDATION_PROMPT } from '../prompts/validation'
16
+
17
+ // Cache for project context (built once per scan)
18
+ let cachedProjectContext: ProjectContext | null = null
19
+
20
+ /**
21
+ * Validate findings using Anthropic Claude 3.5 Haiku
22
+ */
23
+ export async function validateWithAnthropic(
24
+ findings: Vulnerability[],
25
+ files: ScanFile[],
26
+ projectContext: ProjectContext | undefined,
27
+ stats: ValidationStats,
28
+ onProgress?: (progress: { filesProcessed: number; totalFiles: number; status: string }) => void
29
+ ): Promise<AIValidationResult> {
30
+ console.log('[AI Validation] Initializing Anthropic client...')
31
+ const client = getAnthropicClient()
32
+
33
+ // Build or use cached project context
34
+ const context = projectContext || cachedProjectContext || buildProjectContext(files)
35
+ if (!projectContext && !cachedProjectContext) {
36
+ cachedProjectContext = context
37
+ console.log('[AI Validation] Built project context:', {
38
+ hasAuthMiddleware: context.auth.hasGlobalMiddleware,
39
+ authProvider: context.auth.authProvider,
40
+ orm: context.dataAccess.orm,
41
+ framework: context.frameworks.primary,
42
+ })
43
+ }
44
+
45
+ // Group findings by file for efficient validation
46
+ const findingsByFile = new Map<string, Vulnerability[]>()
47
+ for (const finding of findings) {
48
+ const existing = findingsByFile.get(finding.filePath) || []
49
+ existing.push(finding)
50
+ findingsByFile.set(finding.filePath, existing)
51
+ }
52
+
53
+ const validatedFindings: Vulnerability[] = []
54
+
55
+ // Phase 2: Multi-file batching
56
+ const fileEntries = Array.from(findingsByFile.entries())
57
+
58
+ // Track metrics
59
+ let totalBatchWaitTime = 0
60
+ let totalApiBatches = 0
61
+
62
+ const totalFileBatches = Math.ceil(fileEntries.length / FILES_PER_API_BATCH)
63
+ console.log(`[AI Validation] Phase 2: Processing ${fileEntries.length} files in ${totalFileBatches} API batch(es) (${FILES_PER_API_BATCH} files/batch)`)
64
+
65
+ // Track files processed for progress reporting
66
+ let filesValidated = 0
67
+
68
+ // Process files in batches - each batch is ONE API call with multiple files
69
+ for (let batchStart = 0; batchStart < fileEntries.length; batchStart += FILES_PER_API_BATCH) {
70
+ const fileBatch = fileEntries.slice(batchStart, batchStart + FILES_PER_API_BATCH)
71
+ const batchNum = Math.floor(batchStart / FILES_PER_API_BATCH) + 1
72
+
73
+ // Report progress before processing batch
74
+ if (onProgress) {
75
+ onProgress({
76
+ filesProcessed: filesValidated,
77
+ totalFiles: fileEntries.length,
78
+ status: `AI validating batch ${batchNum}/${totalFileBatches}`,
79
+ })
80
+ }
81
+
82
+ console.log(`[AI Validation] API Batch ${batchNum}/${totalFileBatches}: ${fileBatch.length} files`)
83
+
84
+ // Prepare file data for batch request
85
+ const fileDataList: Array<{ file: ScanFile; findings: Vulnerability[]; filePath: string }> = []
86
+ const filesWithoutContent: Array<{ filePath: string; findings: Vulnerability[] }> = []
87
+
88
+ for (const [filePath, fileFindings] of fileBatch) {
89
+ const file = files.find(f => f.path === filePath)
90
+ if (!file) {
91
+ filesWithoutContent.push({ filePath, findings: fileFindings })
92
+ } else {
93
+ fileDataList.push({ file, findings: fileFindings, filePath })
94
+ }
95
+ }
96
+
97
+ // Handle files without content - mark as not validated
98
+ for (const { findings } of filesWithoutContent) {
99
+ for (const f of findings) {
100
+ validatedFindings.push({
101
+ ...f,
102
+ validatedByAI: false,
103
+ validationStatus: 'not_validated' as ValidationStatus,
104
+ validationNotes: 'File content not available for validation',
105
+ })
106
+ }
107
+ }
108
+
109
+ // Skip API call if no files with content
110
+ if (fileDataList.length === 0) {
111
+ continue
112
+ }
113
+
114
+ const batchStartTime = Date.now()
115
+
116
+ try {
117
+ // Build multi-file validation request
118
+ const validationRequest = buildMultiFileValidationRequest(
119
+ fileDataList.map(({ file, findings }) => ({ file, findings })),
120
+ context
121
+ )
122
+
123
+ // Use Anthropic prompt caching with multi-file request
124
+ const response = await makeAnthropicRequestWithRetry(() =>
125
+ client.messages.create({
126
+ model: 'claude-3-5-haiku-20241022',
127
+ max_tokens: 1500, // Reduced from 4096 - optimized format needs less output
128
+ system: [
129
+ {
130
+ type: 'text',
131
+ text: HIGH_CONTEXT_VALIDATION_PROMPT,
132
+ cache_control: { type: 'ephemeral' }, // Cache for 5 minutes
133
+ },
134
+ ],
135
+ messages: [{ role: 'user', content: validationRequest }],
136
+ })
137
+ )
138
+
139
+ // Track API call stats
140
+ stats.apiCalls++
141
+ totalApiBatches++
142
+
143
+ // Extract cache metrics from usage
144
+ const usage = response.usage
145
+ if (usage) {
146
+ // DEBUG: Log full usage object to understand token breakdown
147
+ console.log(`[DEBUG] Batch ${batchNum} - Full API Response Usage:`)
148
+ console.log(JSON.stringify(usage, null, 2))
149
+ console.log(`[DEBUG] Breakdown:`)
150
+ console.log(` - input_tokens: ${usage.input_tokens || 0}`)
151
+ console.log(` - output_tokens: ${usage.output_tokens || 0}`)
152
+ // @ts-ignore
153
+ console.log(` - cache_creation_input_tokens: ${usage.cache_creation_input_tokens || 0}`)
154
+ // @ts-ignore
155
+ console.log(` - cache_read_input_tokens: ${usage.cache_read_input_tokens || 0}`)
156
+
157
+ stats.estimatedInputTokens += usage.input_tokens || 0
158
+ stats.estimatedOutputTokens += usage.output_tokens || 0
159
+
160
+ // @ts-ignore - cache fields not in types yet
161
+ const cacheCreation = usage.cache_creation_input_tokens || 0
162
+ // @ts-ignore
163
+ const cacheRead = usage.cache_read_input_tokens || 0
164
+
165
+ stats.cacheCreationTokens += cacheCreation
166
+ stats.cacheReadTokens += cacheRead
167
+ }
168
+
169
+ const textContent = response.content.find((block: { type: string }) => block.type === 'text')
170
+ if (!textContent || textContent.type !== 'text') {
171
+ // No valid response - mark all findings as not validated
172
+ for (const { findings } of fileDataList) {
173
+ for (const f of findings) {
174
+ validatedFindings.push({
175
+ ...f,
176
+ validatedByAI: false,
177
+ validationStatus: 'not_validated' as ValidationStatus,
178
+ validationNotes: 'No valid response from AI',
179
+ })
180
+ }
181
+ }
182
+ continue
183
+ }
184
+
185
+ // Parse multi-file response
186
+ const expectedFiles = fileDataList.map(({ filePath }) => filePath)
187
+ const validationResultsMap = parseMultiFileValidationResponse(textContent.text, expectedFiles)
188
+
189
+ // Apply results per file
190
+ for (const { filePath, findings } of fileDataList) {
191
+ const fileResults = validationResultsMap.get(filePath)
192
+
193
+ if (!fileResults || fileResults.length === 0) {
194
+ // No results for this file - try single-file parsing as fallback
195
+ const singleFileResults = parseValidationResponse(textContent.text)
196
+
197
+ if (singleFileResults.length > 0 && fileDataList.length === 1) {
198
+ // Single file in batch, use single-file parsing
199
+ const { processed: processedFindings, dismissedCount } = applyValidationResults(findings, singleFileResults)
200
+ stats.validatedFindings += processedFindings.length + dismissedCount
201
+ stats.dismissedFindings += dismissedCount
202
+ for (const processed of processedFindings) {
203
+ if (processed.validationStatus === 'confirmed') {
204
+ stats.confirmedFindings++
205
+ } else if (processed.validationStatus === 'downgraded') {
206
+ stats.downgradedFindings++
207
+ }
208
+ validatedFindings.push(processed)
209
+ }
210
+ } else {
211
+ // No validation results - REJECT all findings for this file (conservative approach)
212
+ console.warn(`[AI Validation] No results for ${filePath} - REJECTING ${findings.length} findings`)
213
+ stats.validatedFindings += findings.length
214
+ stats.dismissedFindings += findings.length
215
+ // Don't add to validatedFindings - findings are rejected
216
+ }
217
+ } else {
218
+ // Apply validation results for this file
219
+ const { processed: processedFindings, dismissedCount } = applyValidationResults(findings, fileResults)
220
+ stats.validatedFindings += processedFindings.length + dismissedCount
221
+ stats.dismissedFindings += dismissedCount
222
+ for (const processed of processedFindings) {
223
+ if (processed.validationStatus === 'confirmed') {
224
+ stats.confirmedFindings++
225
+ } else if (processed.validationStatus === 'downgraded') {
226
+ stats.downgradedFindings++
227
+ }
228
+ validatedFindings.push(processed)
229
+ }
230
+ }
231
+ }
232
+
233
+ } catch (error) {
234
+ console.error(`[AI Validation] Error in batch ${batchNum}:`, error)
235
+ // Fallback: keep all findings but mark as not validated
236
+ for (const { findings } of fileDataList) {
237
+ for (const f of findings) {
238
+ validatedFindings.push({
239
+ ...f,
240
+ validatedByAI: false,
241
+ validationStatus: 'not_validated' as ValidationStatus,
242
+ validationNotes: 'Validation failed due to API error',
243
+ })
244
+ }
245
+ }
246
+ }
247
+
248
+ const batchDuration = Date.now() - batchStartTime
249
+ totalBatchWaitTime += batchDuration
250
+
251
+ // Update files validated counter
252
+ filesValidated += fileBatch.length
253
+
254
+ // Report progress after batch completion
255
+ if (onProgress) {
256
+ onProgress({
257
+ filesProcessed: filesValidated,
258
+ totalFiles: fileEntries.length,
259
+ status: `AI validation complete for batch ${batchNum}/${totalFileBatches}`,
260
+ })
261
+ }
262
+ }
263
+
264
+ // Calculate cache hit rate
265
+ const totalCacheableTokens = stats.cacheCreationTokens + stats.cacheReadTokens
266
+ stats.cacheHitRate = totalCacheableTokens > 0
267
+ ? stats.cacheReadTokens / totalCacheableTokens
268
+ : 0
269
+
270
+ // Calculate estimated cost with cache pricing
271
+ const freshInputCost = (stats.estimatedInputTokens * HAIKU_PRICING.input) / 1_000_000
272
+ const cacheWriteCost = (stats.cacheCreationTokens * HAIKU_PRICING.cacheWrite) / 1_000_000
273
+ const cacheReadCost = (stats.cacheReadTokens * HAIKU_PRICING.cacheRead) / 1_000_000
274
+ const outputCost = (stats.estimatedOutputTokens * HAIKU_PRICING.output) / 1_000_000
275
+
276
+ stats.estimatedCost = freshInputCost + cacheWriteCost + cacheReadCost + outputCost
277
+
278
+ // Log validation stats with cache metrics and performance
279
+ console.log(`[AI Validation] Stats:`)
280
+ console.log(` - Total findings: ${stats.totalFindings}`)
281
+ console.log(` - AI validated: ${stats.validatedFindings}`)
282
+ console.log(` - Confirmed: ${stats.confirmedFindings}`)
283
+ console.log(` - Dismissed: ${stats.dismissedFindings}`)
284
+ console.log(` - Downgraded: ${stats.downgradedFindings}`)
285
+ console.log(` - API calls: ${stats.apiCalls}`)
286
+ console.log(` - Performance:`)
287
+ console.log(` - Total duration: ${(totalBatchWaitTime / 1000).toFixed(1)}s`)
288
+ console.log(` - Total API batches: ${totalApiBatches}`)
289
+ console.log(` - Avg time per file: ${fileEntries.length > 0 ? (totalBatchWaitTime / fileEntries.length).toFixed(0) : 0}ms`)
290
+ console.log(` - Cache metrics:`)
291
+ console.log(` - Cache writes: ${stats.cacheCreationTokens.toLocaleString()} tokens`)
292
+ console.log(` - Cache reads: ${stats.cacheReadTokens.toLocaleString()} tokens`)
293
+ console.log(` - Cache hit rate: ${(stats.cacheHitRate * 100).toFixed(1)}%`)
294
+ console.log(` - Token usage:`)
295
+ console.log(` - Input (total): ${stats.estimatedInputTokens.toLocaleString()} tokens`)
296
+ console.log(` - Output: ${stats.estimatedOutputTokens.toLocaleString()} tokens`)
297
+ console.log(` - Estimated cost: $${stats.estimatedCost.toFixed(4)}`)
298
+
299
+ // Clear cache after validation complete
300
+ cachedProjectContext = null
301
+
302
+ return { vulnerabilities: validatedFindings, stats }
303
+ }
304
+
305
+ /**
306
+ * Clear cached project context (called after validation complete)
307
+ */
308
+ export function clearAnthropicCache(): void {
309
+ cachedProjectContext = null
310
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * AI Providers Index
3
+ *
4
+ * Re-exports all AI provider implementations.
5
+ */
6
+
7
+ export { validateWithOpenAI, clearOpenAICache } from './openai'
8
+ export { validateWithAnthropic, clearAnthropicCache } from './anthropic'