@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,420 @@
1
+ /**
2
+ * Layer 3: OSV/Security Advisory Integration
3
+ * Checks packages against OSV.dev for known vulnerabilities
4
+ *
5
+ * Features:
6
+ * - Queries OSV.dev API for known malicious/vulnerable packages
7
+ * - Caches advisories for efficiency
8
+ * - Supports npm and PyPI ecosystems
9
+ */
10
+
11
+ import type { Vulnerability, VulnerabilitySeverity } from '../types'
12
+ import {
13
+ extractNpmDependencies,
14
+ extractPythonRequirements,
15
+ getPackageFileType,
16
+ rateLimitDelay,
17
+ type ExtractedDependency,
18
+ } from '../utils/registry-clients'
19
+
20
+ // ============================================================================
21
+ // Configuration
22
+ // ============================================================================
23
+
24
+ // OSV API endpoint
25
+ const OSV_API_URL = 'https://api.osv.dev/v1/query'
26
+ const OSV_BATCH_URL = 'https://api.osv.dev/v1/querybatch'
27
+
28
+ // Cache TTL (24 hours)
29
+ const CACHE_TTL_MS = 24 * 60 * 60 * 1000
30
+
31
+ // Maximum packages to check per scan (cost/time control)
32
+ const MAX_PACKAGES_TO_CHECK = 100
33
+
34
+ // ============================================================================
35
+ // Types
36
+ // ============================================================================
37
+
38
+ interface OSVQuery {
39
+ package: {
40
+ name: string
41
+ ecosystem: 'npm' | 'PyPI'
42
+ }
43
+ version?: string
44
+ }
45
+
46
+ interface OSVVulnerability {
47
+ id: string
48
+ summary?: string
49
+ details?: string
50
+ severity?: Array<{
51
+ type: string
52
+ score: string
53
+ }>
54
+ references?: Array<{
55
+ type: string
56
+ url: string
57
+ }>
58
+ affected?: Array<{
59
+ package: {
60
+ name: string
61
+ ecosystem: string
62
+ }
63
+ ranges?: Array<{
64
+ type: string
65
+ events: Array<{ introduced?: string; fixed?: string }>
66
+ }>
67
+ }>
68
+ database_specific?: {
69
+ malicious?: boolean
70
+ severity?: string
71
+ }
72
+ }
73
+
74
+ interface OSVResponse {
75
+ vulns?: OSVVulnerability[]
76
+ }
77
+
78
+ interface OSVBatchResponse {
79
+ results: OSVResponse[]
80
+ }
81
+
82
+ interface CachedAdvisory {
83
+ timestamp: number
84
+ advisories: OSVVulnerability[]
85
+ }
86
+
87
+ // ============================================================================
88
+ // Advisory Cache
89
+ // ============================================================================
90
+
91
+ const advisoryCache = new Map<string, CachedAdvisory>()
92
+
93
+ /**
94
+ * Get cache key for a package
95
+ */
96
+ function getCacheKey(name: string, ecosystem: string): string {
97
+ return `${ecosystem}:${name.toLowerCase()}`
98
+ }
99
+
100
+ /**
101
+ * Check if cached advisory is still valid
102
+ */
103
+ function isCacheValid(cached: CachedAdvisory): boolean {
104
+ return Date.now() - cached.timestamp < CACHE_TTL_MS
105
+ }
106
+
107
+ /**
108
+ * Get cached advisories for a package
109
+ */
110
+ function getCachedAdvisories(name: string, ecosystem: string): OSVVulnerability[] | null {
111
+ const key = getCacheKey(name, ecosystem)
112
+ const cached = advisoryCache.get(key)
113
+ if (cached && isCacheValid(cached)) {
114
+ return cached.advisories
115
+ }
116
+ return null
117
+ }
118
+
119
+ /**
120
+ * Cache advisories for a package
121
+ */
122
+ function cacheAdvisories(name: string, ecosystem: string, advisories: OSVVulnerability[]): void {
123
+ const key = getCacheKey(name, ecosystem)
124
+ advisoryCache.set(key, {
125
+ timestamp: Date.now(),
126
+ advisories,
127
+ })
128
+ }
129
+
130
+ // ============================================================================
131
+ // OSV API Client
132
+ // ============================================================================
133
+
134
+ /**
135
+ * Query OSV.dev for vulnerabilities affecting a single package
136
+ */
137
+ async function queryOSV(
138
+ packageName: string,
139
+ ecosystem: 'npm' | 'PyPI',
140
+ version?: string
141
+ ): Promise<OSVVulnerability[]> {
142
+ // Check cache first
143
+ const cached = getCachedAdvisories(packageName, ecosystem)
144
+ if (cached !== null) {
145
+ return cached
146
+ }
147
+
148
+ try {
149
+ const query: OSVQuery = {
150
+ package: {
151
+ name: packageName,
152
+ ecosystem,
153
+ },
154
+ }
155
+
156
+ if (version) {
157
+ query.version = version
158
+ }
159
+
160
+ const response = await fetch(OSV_API_URL, {
161
+ method: 'POST',
162
+ headers: {
163
+ 'Content-Type': 'application/json',
164
+ },
165
+ body: JSON.stringify(query),
166
+ })
167
+
168
+ if (!response.ok) {
169
+ // Don't throw - gracefully degrade
170
+ cacheAdvisories(packageName, ecosystem, [])
171
+ return []
172
+ }
173
+
174
+ const data = (await response.json()) as OSVResponse
175
+ const advisories = data.vulns || []
176
+
177
+ // Cache the result
178
+ cacheAdvisories(packageName, ecosystem, advisories)
179
+
180
+ return advisories
181
+ } catch {
182
+ // Network error - gracefully degrade
183
+ return []
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Query OSV.dev for multiple packages in batch
189
+ */
190
+ async function queryOSVBatch(
191
+ packages: Array<{ name: string; ecosystem: 'npm' | 'PyPI'; version?: string }>
192
+ ): Promise<Map<string, OSVVulnerability[]>> {
193
+ const results = new Map<string, OSVVulnerability[]>()
194
+
195
+ // Split into cached and uncached
196
+ const uncached: Array<{ name: string; ecosystem: 'npm' | 'PyPI'; version?: string; index: number }> = []
197
+
198
+ for (let i = 0; i < packages.length; i++) {
199
+ const pkg = packages[i]
200
+ const cached = getCachedAdvisories(pkg.name, pkg.ecosystem)
201
+ if (cached !== null) {
202
+ results.set(getCacheKey(pkg.name, pkg.ecosystem), cached)
203
+ } else {
204
+ uncached.push({ ...pkg, index: i })
205
+ }
206
+ }
207
+
208
+ if (uncached.length === 0) {
209
+ return results
210
+ }
211
+
212
+ try {
213
+ const queries = uncached.map(pkg => ({
214
+ package: {
215
+ name: pkg.name,
216
+ ecosystem: pkg.ecosystem,
217
+ },
218
+ version: pkg.version,
219
+ }))
220
+
221
+ const response = await fetch(OSV_BATCH_URL, {
222
+ method: 'POST',
223
+ headers: {
224
+ 'Content-Type': 'application/json',
225
+ },
226
+ body: JSON.stringify({ queries }),
227
+ })
228
+
229
+ if (!response.ok) {
230
+ // Gracefully degrade - return empty for all uncached
231
+ for (const pkg of uncached) {
232
+ cacheAdvisories(pkg.name, pkg.ecosystem, [])
233
+ results.set(getCacheKey(pkg.name, pkg.ecosystem), [])
234
+ }
235
+ return results
236
+ }
237
+
238
+ const data = (await response.json()) as OSVBatchResponse
239
+
240
+ // Process batch results
241
+ for (let i = 0; i < uncached.length; i++) {
242
+ const pkg = uncached[i]
243
+ const advisories = data.results[i]?.vulns || []
244
+ cacheAdvisories(pkg.name, pkg.ecosystem, advisories)
245
+ results.set(getCacheKey(pkg.name, pkg.ecosystem), advisories)
246
+ }
247
+
248
+ return results
249
+ } catch {
250
+ // Network error - gracefully degrade
251
+ for (const pkg of uncached) {
252
+ results.set(getCacheKey(pkg.name, pkg.ecosystem), [])
253
+ }
254
+ return results
255
+ }
256
+ }
257
+
258
+ // ============================================================================
259
+ // Severity Mapping
260
+ // ============================================================================
261
+
262
+ /**
263
+ * Determine severity from OSV vulnerability
264
+ */
265
+ function mapOSVSeverity(vuln: OSVVulnerability): VulnerabilitySeverity {
266
+ // Check for malicious package (critical)
267
+ if (vuln.database_specific?.malicious) {
268
+ return 'critical'
269
+ }
270
+
271
+ // Check CVSS score
272
+ const cvss = vuln.severity?.find(s => s.type === 'CVSS_V3')
273
+ if (cvss) {
274
+ const score = parseFloat(cvss.score)
275
+ if (score >= 9.0) return 'critical'
276
+ if (score >= 7.0) return 'high'
277
+ if (score >= 4.0) return 'medium'
278
+ return 'low'
279
+ }
280
+
281
+ // Check database_specific severity
282
+ const dbSeverity = vuln.database_specific?.severity?.toLowerCase()
283
+ if (dbSeverity) {
284
+ if (dbSeverity === 'critical') return 'critical'
285
+ if (dbSeverity === 'high') return 'high'
286
+ if (dbSeverity === 'moderate' || dbSeverity === 'medium') return 'medium'
287
+ if (dbSeverity === 'low') return 'low'
288
+ }
289
+
290
+ // Default to high for unknown severity (conservative)
291
+ return 'high'
292
+ }
293
+
294
+ /**
295
+ * Check if vulnerability is for a malicious package
296
+ */
297
+ function isMaliciousPackage(vuln: OSVVulnerability): boolean {
298
+ return vuln.database_specific?.malicious === true ||
299
+ vuln.id.startsWith('MAL-') ||
300
+ (vuln.summary?.toLowerCase().includes('malicious') ?? false)
301
+ }
302
+
303
+ // ============================================================================
304
+ // Main Check Function
305
+ // ============================================================================
306
+
307
+ /**
308
+ * Check packages in a file for known vulnerabilities via OSV.dev
309
+ */
310
+ export async function checkPackageAdvisories(
311
+ content: string,
312
+ filePath: string
313
+ ): Promise<Vulnerability[]> {
314
+ const vulnerabilities: Vulnerability[] = []
315
+
316
+ // Determine file type
317
+ const fileType = getPackageFileType(filePath)
318
+ if (!fileType) {
319
+ return vulnerabilities
320
+ }
321
+
322
+ // Extract dependencies based on file type
323
+ let dependencies: ExtractedDependency[] = []
324
+
325
+ if (fileType === 'npm' && filePath.endsWith('package.json')) {
326
+ dependencies = extractNpmDependencies(content)
327
+ } else if (fileType === 'python') {
328
+ dependencies = extractPythonRequirements(content)
329
+ }
330
+
331
+ if (dependencies.length === 0) {
332
+ return vulnerabilities
333
+ }
334
+
335
+ const lines = content.split('\n')
336
+ const ecosystem = fileType === 'npm' ? 'npm' : 'PyPI'
337
+
338
+ // Limit packages to check
339
+ const limitedDeps = dependencies.slice(0, MAX_PACKAGES_TO_CHECK)
340
+
341
+ // Query OSV in batch for efficiency
342
+ const packagesToQuery = limitedDeps.map(dep => ({
343
+ name: dep.name,
344
+ ecosystem: ecosystem as 'npm' | 'PyPI',
345
+ version: dep.version,
346
+ }))
347
+
348
+ const advisoriesMap = await queryOSVBatch(packagesToQuery)
349
+
350
+ // Process results
351
+ for (const dep of limitedDeps) {
352
+ const key = getCacheKey(dep.name, ecosystem)
353
+ const advisories = advisoriesMap.get(key) || []
354
+
355
+ if (advisories.length === 0) continue
356
+
357
+ // Find the most severe vulnerability
358
+ let mostSevere: OSVVulnerability | null = null
359
+ let highestSeverity: VulnerabilitySeverity = 'info'
360
+ const severityOrder = ['info', 'low', 'medium', 'high', 'critical']
361
+
362
+ for (const adv of advisories) {
363
+ const sev = mapOSVSeverity(adv)
364
+ if (severityOrder.indexOf(sev) > severityOrder.indexOf(highestSeverity)) {
365
+ highestSeverity = sev
366
+ mostSevere = adv
367
+ }
368
+ }
369
+
370
+ if (!mostSevere) continue
371
+
372
+ // Determine category based on malicious vs vulnerable
373
+ const isMalicious = advisories.some(a => isMaliciousPackage(a))
374
+ const category = isMalicious ? 'ai_package_malicious' : 'suspicious_package'
375
+
376
+ // Build description
377
+ const advIds = advisories.map(a => a.id).slice(0, 3).join(', ')
378
+ const moreCount = advisories.length > 3 ? ` +${advisories.length - 3} more` : ''
379
+ const description = isMalicious
380
+ ? `Package "${dep.name}" is flagged as MALICIOUS in OSV.dev (${advIds}${moreCount}). This package may contain malware or data exfiltration code.`
381
+ : `Package "${dep.name}" has ${advisories.length} known security advisories (${advIds}${moreCount}). ${mostSevere.summary || 'Review before use.'}`
382
+
383
+ // Build suggested fix
384
+ const suggestedFix = isMalicious
385
+ ? `Remove "${dep.name}" immediately. Do not use this package.`
386
+ : `Update "${dep.name}" to a patched version or find an alternative. Check: https://osv.dev/list?ecosystem=${ecosystem}&q=${encodeURIComponent(dep.name)}`
387
+
388
+ vulnerabilities.push({
389
+ id: `osv-${filePath}-${dep.name}`,
390
+ filePath,
391
+ lineNumber: dep.line,
392
+ lineContent: lines[dep.line - 1]?.trim() || dep.name,
393
+ severity: highestSeverity,
394
+ category,
395
+ title: isMalicious
396
+ ? `Malicious package: ${dep.name}`
397
+ : `Vulnerable package: ${dep.name} (${advisories.length} advisories)`,
398
+ description,
399
+ suggestedFix,
400
+ confidence: 'high',
401
+ layer: 3,
402
+ requiresAIValidation: false, // OSV data is authoritative
403
+ })
404
+
405
+ // Rate limit between individual package queries if not using batch
406
+ await rateLimitDelay()
407
+ }
408
+
409
+ return vulnerabilities
410
+ }
411
+
412
+ // Export for testing
413
+ export {
414
+ queryOSV,
415
+ queryOSVBatch,
416
+ mapOSVSeverity,
417
+ isMaliciousPackage,
418
+ getCacheKey,
419
+ advisoryCache,
420
+ }