@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
@@ -124,6 +124,50 @@ function hasTenantContextVerification(context: string): boolean {
124
124
  return tenantContextPatterns.some(p => p.test(context))
125
125
  }
126
126
 
127
+ /**
128
+ * Check if this is an MCP file with proper security controls
129
+ * MCP files with sanitization and authorization should be downgraded
130
+ */
131
+ function isMCPFileWithSafePatterns(content: string, filePath: string): boolean {
132
+ // Check if this is an MCP file
133
+ const mcpPatterns = [
134
+ /McpServer/i,
135
+ /@modelcontextprotocol/i,
136
+ /server\.tool\s*\(/i,
137
+ /@server\.tool/i,
138
+ /\/mcp\//i,
139
+ ]
140
+
141
+ if (!mcpPatterns.some(p => p.test(content) || p.test(filePath))) {
142
+ return false
143
+ }
144
+
145
+ // Check for content sanitization patterns
146
+ const sanitizationPatterns = [
147
+ /sanitize|DOMPurify|purify/i,
148
+ /escapeHtml|escape_html/i,
149
+ /validateSchema|schema\.parse|safeParse/i,
150
+ /ALLOWED_TAGS/i,
151
+ /filterHtml|cleanHtml/i,
152
+ ]
153
+
154
+ // Check for authorization patterns
155
+ const authorizationPatterns = [
156
+ /if\s*\([^)]*ownerId\s*[!=]==?/i,
157
+ /if\s*\([^)]*userId\s*[!=]==?/i,
158
+ /if\s*\([^)]*tenantId\s*[!=]==?/i,
159
+ /throw.*Error.*(?:auth|Forbidden|Unauthorized)/i,
160
+ /Not\s*authorized/i,
161
+ /checkPermission|hasPermission|isAuthorized/i,
162
+ ]
163
+
164
+ const hasSanitization = sanitizationPatterns.some(p => p.test(content))
165
+ const hasAuthorization = authorizationPatterns.some(p => p.test(content))
166
+
167
+ // MCP file with BOTH sanitization AND authorization is safe
168
+ return hasSanitization && hasAuthorization
169
+ }
170
+
127
171
  /**
128
172
  * Patterns indicating strong/verified restrictions (actual implementation)
129
173
  */
@@ -412,6 +456,197 @@ const OVERPERMISSIVE_TOOL_PATTERNS: ToolPattern[] = [
412
456
  },
413
457
  ]
414
458
 
459
+ // ============================================================================
460
+ // Phase 2: Excessive Agency Detection
461
+ // ============================================================================
462
+
463
+ interface ExcessiveAgencyPattern {
464
+ name: string
465
+ pattern: RegExp
466
+ baseSeverity: VulnerabilitySeverity
467
+ description: string
468
+ suggestedFix: string
469
+ framework?: 'crewai' | 'autogen' | 'langchain' | 'generic'
470
+ }
471
+
472
+ /**
473
+ * Check if agent has proper iteration limits
474
+ */
475
+ function hasIterationLimits(context: string): boolean {
476
+ const limitPatterns = [
477
+ /maxIterations\s*[:=]\s*\d{1,2}\b/i, // 1-99
478
+ /max_iterations\s*[:=]\s*\d{1,2}\b/i,
479
+ /iteration_limit\s*[:=]\s*\d{1,2}\b/i,
480
+ /max_steps\s*[:=]\s*\d{1,2}\b/i,
481
+ ]
482
+ return limitPatterns.some(p => p.test(context))
483
+ }
484
+
485
+ /**
486
+ * Check if agent has timeout configured
487
+ */
488
+ function hasTimeoutConfigured(context: string): boolean {
489
+ const timeoutPatterns = [
490
+ /timeout\s*[:=]\s*[1-9]\d*/i, // Positive number
491
+ /max_execution_time\s*[:=]\s*[1-9]/i,
492
+ /execution_timeout\s*[:=]\s*[1-9]/i,
493
+ ]
494
+ return timeoutPatterns.some(p => p.test(context))
495
+ }
496
+
497
+ /**
498
+ * Check if human-in-the-loop is enabled
499
+ */
500
+ function hasHumanInLoop(context: string): boolean {
501
+ const humanPatterns = [
502
+ /humanInLoop\s*[:=]\s*true/i,
503
+ /human_in_loop\s*[:=]\s*True/i,
504
+ /requireApproval\s*[:=]\s*true/i,
505
+ /require_approval\s*[:=]\s*True/i,
506
+ /human_input_mode\s*[:=]\s*['"`](?:ALWAYS|TERMINATE)['"`]/i,
507
+ /confirm_before\s*[:=]\s*true/i,
508
+ ]
509
+ return humanPatterns.some(p => p.test(context))
510
+ }
511
+
512
+ /**
513
+ * Check if Docker is configured for code execution
514
+ */
515
+ function hasDockerConfigured(context: string): boolean {
516
+ const dockerPatterns = [
517
+ /use_docker\s*[:=]\s*True/i,
518
+ /docker\s*[:=]\s*true/i,
519
+ /container\s*[:=]\s*true/i,
520
+ /sandboxed\s*[:=]\s*true/i,
521
+ ]
522
+ return dockerPatterns.some(p => p.test(context))
523
+ }
524
+
525
+ /**
526
+ * Check if budget/cost limits are configured
527
+ */
528
+ function hasBudgetLimits(context: string): boolean {
529
+ const budgetPatterns = [
530
+ /budgetLimit|budget_limit/i,
531
+ /costLimit|cost_limit/i,
532
+ /max_cost|maxCost/i,
533
+ /spending_limit/i,
534
+ /token_limit|tokenLimit/i,
535
+ ]
536
+ return budgetPatterns.some(p => p.test(context))
537
+ }
538
+
539
+ /**
540
+ * Excessive agency patterns for unbounded agent autonomy
541
+ */
542
+ const EXCESSIVE_AGENCY_PATTERNS: ExcessiveAgencyPattern[] = [
543
+ // ========== Generic Unbounded Loops ==========
544
+ {
545
+ name: 'Unbounded agent loop',
546
+ pattern: /while\s*\(\s*(?:true|1|True)\s*\)[\s\S]{0,100}(?:agent|step|run|execute|iterate)/gi,
547
+ baseSeverity: 'high',
548
+ description: 'Agent runs in an unbounded loop without explicit termination condition. This can lead to infinite execution, resource exhaustion, or runaway costs.',
549
+ suggestedFix: 'Add maxIterations limit: while (iterations < maxIterations) { ... }. Consider adding timeout and cost limits.',
550
+ framework: 'generic',
551
+ },
552
+ {
553
+ name: 'No iteration limit configured',
554
+ pattern: /maxIterations\s*[:=]\s*(?:-1|null|undefined|None|Infinity|float\s*\(\s*['"`]inf)/gi,
555
+ baseSeverity: 'high',
556
+ description: 'Agent configured with no iteration limit. This allows unbounded execution which can consume excessive resources.',
557
+ suggestedFix: 'Set a reasonable iteration limit: maxIterations: 10 (adjust based on your use case).',
558
+ framework: 'generic',
559
+ },
560
+ {
561
+ name: 'No timeout configured',
562
+ pattern: /timeout\s*[:=]\s*(?:-1|0|null|undefined|None|false|False)/gi,
563
+ baseSeverity: 'medium',
564
+ description: 'Agent timeout is disabled or set to zero. Long-running agents can hang indefinitely.',
565
+ suggestedFix: 'Configure a reasonable timeout: timeout: 300000 (5 minutes). Adjust based on expected execution time.',
566
+ framework: 'generic',
567
+ },
568
+ {
569
+ name: 'Auto-approve without human oversight',
570
+ pattern: /(?:autoApprove|auto_approve)\s*[:=]\s*(?:true|True)/gi,
571
+ baseSeverity: 'high',
572
+ description: 'Agent auto-approves actions without human review. Combined with destructive capabilities, this is dangerous.',
573
+ suggestedFix: 'Enable human-in-the-loop for sensitive operations: autoApprove: false, or implement approval workflows for destructive actions.',
574
+ framework: 'generic',
575
+ },
576
+ {
577
+ name: 'Human-in-loop disabled',
578
+ pattern: /(?:humanInLoop|human_in_loop)\s*[:=]\s*(?:false|False)/gi,
579
+ baseSeverity: 'medium',
580
+ description: 'Human oversight is explicitly disabled. The agent can take actions without human review.',
581
+ suggestedFix: 'Enable human-in-the-loop for sensitive operations: humanInLoop: true. Add confirmation prompts for destructive actions.',
582
+ framework: 'generic',
583
+ },
584
+
585
+ // ========== CrewAI Specific ==========
586
+ {
587
+ name: 'CrewAI unsafe code execution mode',
588
+ pattern: /code_execution_mode\s*[:=]\s*['"`]unsafe['"`]/gi,
589
+ baseSeverity: 'critical',
590
+ description: 'CrewAI agent configured with unsafe code execution mode. This allows arbitrary code execution without sandboxing.',
591
+ suggestedFix: 'Use safe mode: code_execution_mode="safe". This runs code in a restricted environment.',
592
+ framework: 'crewai',
593
+ },
594
+ {
595
+ name: 'CrewAI code execution without Docker',
596
+ pattern: /allow_code_execution\s*[:=]\s*True(?![\s\S]{0,50}use_docker\s*[:=]\s*True)/gi,
597
+ baseSeverity: 'high',
598
+ description: 'CrewAI agent allows code execution without Docker containerization. Code runs directly on the host system.',
599
+ suggestedFix: 'Enable Docker for code execution: Agent(..., allow_code_execution=True, code_execution_config={"use_docker": True})',
600
+ framework: 'crewai',
601
+ },
602
+
603
+ // ========== AutoGen Specific ==========
604
+ {
605
+ name: 'AutoGen use_docker=False',
606
+ pattern: /(?:code_execution_config|LocalCommandLineCodeExecutor)\s*[\s\S]{0,50}use_docker\s*[:=]\s*False/gi,
607
+ baseSeverity: 'critical',
608
+ description: 'AutoGen code execution configured without Docker. Code executes directly on the host, enabling full system access.',
609
+ suggestedFix: 'Use Docker: code_execution_config={"use_docker": True}. Or use DockerCommandLineCodeExecutor for sandboxed execution.',
610
+ framework: 'autogen',
611
+ },
612
+ {
613
+ name: 'AutoGen NEVER human input mode',
614
+ pattern: /human_input_mode\s*[:=]\s*['"`]NEVER['"`]/gi,
615
+ baseSeverity: 'high',
616
+ description: 'AutoGen agent configured to never request human input. Agent can execute indefinitely without human oversight.',
617
+ suggestedFix: 'Use "ALWAYS" or "TERMINATE" for human_input_mode. "TERMINATE" allows agent to complete but requests input on termination.',
618
+ framework: 'autogen',
619
+ },
620
+ {
621
+ name: 'AutoGen UserProxyAgent without reply limit',
622
+ pattern: /UserProxyAgent\s*\((?![^)]*max_consecutive_auto_reply)[^)]*\)/gi,
623
+ baseSeverity: 'medium',
624
+ description: 'AutoGen UserProxyAgent without max_consecutive_auto_reply limit. Agent can auto-reply indefinitely.',
625
+ suggestedFix: 'Add reply limit: UserProxyAgent(..., max_consecutive_auto_reply=10). Adjust limit based on expected conversation length.',
626
+ framework: 'autogen',
627
+ },
628
+
629
+ // ========== LangChain Specific ==========
630
+ {
631
+ name: 'LangChain AgentExecutor without limits',
632
+ pattern: /AgentExecutor\s*\([^)]*(?!max_iterations)[^)]*\)/gi,
633
+ baseSeverity: 'medium',
634
+ description: 'LangChain AgentExecutor without max_iterations. Agent can loop indefinitely on complex tasks.',
635
+ suggestedFix: 'Set iteration limit: AgentExecutor(..., max_iterations=15). Add early_stopping_method="generate" to gracefully stop.',
636
+ framework: 'langchain',
637
+ },
638
+
639
+ // ========== Overpermissioned Agents ==========
640
+ {
641
+ name: 'Agent with excessive tools',
642
+ pattern: /tools\s*[:=]\s*\[(?:[^\]]*,){10,}[^\]]*\]/gi,
643
+ baseSeverity: 'medium',
644
+ description: 'Agent configured with more than 10 tools. Overpermissioned agents have larger attack surface if compromised via prompt injection.',
645
+ suggestedFix: 'Follow principle of least privilege. Split into specialized agents with focused tool sets. Remove unused tools.',
646
+ framework: 'generic',
647
+ },
648
+ ]
649
+
415
650
  /**
416
651
  * Patterns for missing authorization in tools
417
652
  */
@@ -506,6 +741,8 @@ export function detectAIAgentTools(
506
741
 
507
742
  // Calculate severity
508
743
  let severity = pattern.baseSeverity
744
+ const isMCPSafe = isMCPFileWithSafePatterns(content, filePath)
745
+
509
746
  if (isTestFile) {
510
747
  severity = 'info'
511
748
  } else if (isExample) {
@@ -515,6 +752,9 @@ export function detectAIAgentTools(
515
752
  // Library code - tool definitions are intentionally flexible
516
753
  // Consumers add restrictions when they use the tools
517
754
  severity = 'info'
755
+ } else if (isMCPSafe) {
756
+ // MCP file with proper security controls (sanitization + authorization)
757
+ severity = 'info'
518
758
  } else if (hasPartialMitigation || hasUserContext || hasTenantContext) {
519
759
  // Partial mitigation - downgrade
520
760
  if (severity === 'critical') severity = 'high'
@@ -532,6 +772,8 @@ export function detectAIAgentTools(
532
772
  description += ' (In example/demo directory - not production code.)'
533
773
  } else if (isLibrary) {
534
774
  description += ' (Library code - tool definitions are generic; consumers add restrictions.)'
775
+ } else if (isMCPSafe) {
776
+ description += ' (MCP file with sanitization and authorization controls detected.)'
535
777
  }
536
778
 
537
779
  vulnerabilities.push({
@@ -597,5 +839,99 @@ export function detectAIAgentTools(
597
839
  }
598
840
  }
599
841
 
842
+ // Scan for excessive agency patterns (Phase 2)
843
+ for (const pattern of EXCESSIVE_AGENCY_PATTERNS) {
844
+ const regex = new RegExp(pattern.pattern.source, pattern.pattern.flags)
845
+ let match
846
+
847
+ while ((match = regex.exec(content)) !== null) {
848
+ const lineNumber = content.substring(0, match.index).split('\n').length
849
+ const lineContent = lines[lineNumber - 1]?.trim() || ''
850
+
851
+ // Skip comments
852
+ if (isComment(lineContent)) continue
853
+
854
+ // Get surrounding context for mitigation checks
855
+ const { context } = findToolDefinitionContext(content, lineNumber)
856
+
857
+ // Check for mitigations
858
+ let isMitigated = false
859
+ let isPartiallyMitigated = false
860
+ let description = pattern.description
861
+
862
+ // Check iteration limits
863
+ if (hasIterationLimits(context)) {
864
+ isPartiallyMitigated = true
865
+ description += ' (Iteration limits detected nearby.)'
866
+ }
867
+
868
+ // Check timeout configuration
869
+ if (hasTimeoutConfigured(context)) {
870
+ isPartiallyMitigated = true
871
+ description += ' (Timeout configured.)'
872
+ }
873
+
874
+ // Check human-in-the-loop
875
+ if (hasHumanInLoop(context)) {
876
+ isPartiallyMitigated = true
877
+ description += ' (Human-in-loop enabled.)'
878
+ }
879
+
880
+ // Check Docker for code execution patterns
881
+ if (pattern.framework === 'crewai' || pattern.framework === 'autogen') {
882
+ if (hasDockerConfigured(context)) {
883
+ isMitigated = true
884
+ description += ' (Docker containerization detected.)'
885
+ }
886
+ }
887
+
888
+ // Check budget limits
889
+ if (hasBudgetLimits(context)) {
890
+ isPartiallyMitigated = true
891
+ description += ' (Budget limits configured.)'
892
+ }
893
+
894
+ // Calculate severity
895
+ let severity = pattern.baseSeverity
896
+ const isMCPSafe = isMCPFileWithSafePatterns(content, filePath)
897
+
898
+ if (isMitigated) {
899
+ severity = 'info'
900
+ } else if (isTestFile) {
901
+ severity = 'info'
902
+ description += ' (In test file.)'
903
+ } else if (isExample) {
904
+ severity = 'info'
905
+ description += ' (In example/demo directory.)'
906
+ } else if (isLibrary) {
907
+ severity = 'info'
908
+ description += ' (Library code.)'
909
+ } else if (isPartiallyMitigated) {
910
+ // Downgrade if partial mitigations present
911
+ if (severity === 'critical') severity = 'high'
912
+ else if (severity === 'high') severity = 'medium'
913
+ else if (severity === 'medium') severity = 'low'
914
+ }
915
+
916
+ // Skip fully mitigated or info-level in non-agent files
917
+ if (isMitigated && severity === 'info') continue
918
+
919
+ vulnerabilities.push({
920
+ id: `ai-agency-${filePath}-${lineNumber}-${pattern.name.replace(/\s+/g, '-')}`,
921
+ filePath,
922
+ lineNumber,
923
+ lineContent,
924
+ severity,
925
+ category: 'ai_excessive_agency',
926
+ title: pattern.name,
927
+ description,
928
+ suggestedFix: pattern.suggestedFix,
929
+ confidence: severity === 'info' ? 'low' : 'medium',
930
+ layer: 2,
931
+ requiresAIValidation: severity !== 'info' && severity !== 'low',
932
+ })
933
+ }
934
+ }
935
+
600
936
  return vulnerabilities
601
937
  }
@@ -136,6 +136,12 @@ function isBYOKEndpoint(content: string): boolean {
136
136
  // Headers with user's key
137
137
  /headers\[['"`]x-openai-key['"`]\]/i,
138
138
  /headers\[['"`]x-api-key['"`]\]/i,
139
+ // Destructuring from request body
140
+ /const\s*\{\s*[^}]*apiKey[^}]*\}\s*=\s*await\s*(?:request|req)\.json\(\)/i,
141
+ /const\s*\{\s*[^}]*api_key[^}]*\}\s*=\s*await\s*(?:request|req)\.json\(\)/i,
142
+ // OpenAI/Anthropic client with user-provided key
143
+ /new\s+OpenAI\s*\(\s*\{\s*apiKey\s*[,}]/i,
144
+ /new\s+Anthropic\s*\(\s*\{\s*apiKey\s*[,}]/i,
139
145
  ]
140
146
  return byokPatterns.some(p => p.test(content))
141
147
  }
@@ -327,10 +333,17 @@ export function detectAIEndpointProtection(
327
333
  notes.push('Missing authentication and rate limiting')
328
334
  }
329
335
 
330
- // BYOK endpoints have lower risk
336
+ // BYOK endpoints have lower risk - user provides own API key
331
337
  if (isByok && severity !== 'info') {
332
- severity = severity === 'high' ? 'medium' : (severity === 'medium' ? 'low' : severity)
333
- notes.push('BYOK endpoint - user provides API key')
338
+ // BYOK with auth = info (user pays for own usage, access controlled)
339
+ // BYOK without auth = low (potential abuse but user still pays)
340
+ if (handlerHasAuth || fileHasAuth) {
341
+ severity = 'info'
342
+ notes.push('BYOK endpoint with authentication - user pays for their own usage')
343
+ } else {
344
+ severity = 'low'
345
+ notes.push('BYOK endpoint without auth - potential abuse but user provides API key')
346
+ }
334
347
  }
335
348
 
336
349
  // Downgrade test files