@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,495 @@
1
+ /**
2
+ * MCP Security Test Fixtures
3
+ * Tests for detecting security issues in Model Context Protocol (MCP) tools
4
+ *
5
+ * Background: MCP enables AI agents to call external tools. Security risks include:
6
+ * - Tool Poisoning: External content returned without validation
7
+ * - Credential Issues: Credentials in tool parameters/responses
8
+ * - Confused Deputy: Operations without proper user context
9
+ *
10
+ * Reference: CVE-2025-6514, 13,000+ MCP servers deployed
11
+ */
12
+
13
+ import type { TestGroup } from '../../types'
14
+
15
+ export const aiMcpSecurityTests: TestGroup = {
16
+ name: 'MCP Tool Security',
17
+ tier: 'A',
18
+ layer: 2,
19
+ description: 'Detection of security issues in Model Context Protocol tools',
20
+
21
+ truePositives: [
22
+ {
23
+ name: 'MCP Security - Tool Poisoning True Positives',
24
+ expectFindings: true,
25
+ expectedCategories: ['ai_mcp_tool_poisoning'],
26
+ description: 'MCP tools returning unvalidated external content',
27
+ file: {
28
+ path: 'src/mcp/tools/fetch-tool.ts',
29
+ content: `
30
+ import { McpServer, Tool } from '@modelcontextprotocol/sdk'
31
+
32
+ const server = new McpServer({ name: 'fetch-server' })
33
+
34
+ // Dangerous: Returns raw external content without sanitization
35
+ server.tool('fetch_webpage', async ({ url }: { url: string }) => {
36
+ const response = await fetch(url)
37
+ const html = await response.text()
38
+ // Returning raw HTML - could contain prompt injection payloads
39
+ return { content: html }
40
+ })
41
+
42
+ // Dangerous: Raw file content returned without validation
43
+ server.tool('read_file', async ({ path }: { path: string }) => {
44
+ const content = await fs.readFile(path, 'utf-8')
45
+ // No validation of file content
46
+ return { content }
47
+ })
48
+
49
+ // Dangerous: Database query results returned directly
50
+ server.tool('query_database', async ({ query }: { query: string }) => {
51
+ const results = await db.query(query)
52
+ // Raw database content could contain injected instructions
53
+ return { data: results.rows }
54
+ })
55
+
56
+ // Dangerous: Email content without sanitization
57
+ server.tool('get_email', async ({ id }: { id: string }) => {
58
+ const email = await emailClient.getMessage(id)
59
+ return {
60
+ subject: email.subject,
61
+ body: email.body, // Raw email body - could contain malicious instructions
62
+ attachments: email.attachments
63
+ }
64
+ })
65
+
66
+ // Dangerous: RSS feed content
67
+ server.tool('fetch_rss', async ({ feedUrl }: { feedUrl: string }) => {
68
+ const feed = await parser.parseURL(feedUrl)
69
+ // Entire feed content returned - titles, descriptions could be poisoned
70
+ return { items: feed.items }
71
+ })
72
+ `,
73
+ language: 'typescript',
74
+ size: 1300,
75
+ },
76
+ },
77
+ {
78
+ name: 'MCP Security - Credential Issues True Positives',
79
+ expectFindings: true,
80
+ expectedCategories: ['ai_mcp_credential_issue'],
81
+ description: 'MCP tools with credential exposure in parameters or responses',
82
+ file: {
83
+ path: 'src/mcp/tools/auth-tool.ts',
84
+ content: `
85
+ import { McpServer } from '@modelcontextprotocol/sdk'
86
+
87
+ const server = new McpServer({ name: 'auth-server' })
88
+
89
+ // Dangerous: API key passed as tool parameter
90
+ server.tool('call_api', async ({ apiKey, endpoint }: { apiKey: string; endpoint: string }) => {
91
+ const response = await fetch(endpoint, {
92
+ headers: { 'Authorization': \`Bearer \${apiKey}\` }
93
+ })
94
+ return { data: await response.json() }
95
+ })
96
+
97
+ // Dangerous: Returning credentials in response
98
+ server.tool('create_user', async ({ email }: { email: string }) => {
99
+ const user = await db.createUser(email)
100
+ const password = generatePassword()
101
+ await db.setPassword(user.id, password)
102
+ // Returning password to the model!
103
+ return { userId: user.id, password, apiKey: user.apiKey }
104
+ })
105
+
106
+ // Dangerous: Token in response
107
+ server.tool('authenticate', async ({ username, password }: { username: string; password: string }) => {
108
+ const result = await auth.login(username, password)
109
+ // JWT token exposed to model
110
+ return { token: result.jwt, refreshToken: result.refreshToken }
111
+ })
112
+
113
+ // Dangerous: Database connection string in parameter
114
+ server.tool('connect_db', async ({ connectionString }: { connectionString: string }) => {
115
+ const client = await Database.connect(connectionString)
116
+ return { status: 'connected' }
117
+ })
118
+
119
+ // Dangerous: Private key parameter
120
+ server.tool('sign_message', async ({ privateKey, message }: { privateKey: string; message: string }) => {
121
+ const signature = crypto.sign(privateKey, message)
122
+ return { signature }
123
+ })
124
+
125
+ // Dangerous: Returning secrets from environment
126
+ server.tool('get_config', async () => {
127
+ return {
128
+ apiUrl: process.env.API_URL,
129
+ apiKey: process.env.API_KEY, // Secret exposed!
130
+ secretKey: process.env.SECRET_KEY, // Secret exposed!
131
+ }
132
+ })
133
+ `,
134
+ language: 'typescript',
135
+ size: 1500,
136
+ },
137
+ },
138
+ {
139
+ name: 'MCP Security - Confused Deputy True Positives',
140
+ expectFindings: true,
141
+ expectedCategories: ['ai_mcp_confused_deputy'],
142
+ description: 'MCP tools performing operations without user context',
143
+ file: {
144
+ path: 'src/mcp/tools/data-tool.ts',
145
+ content: `
146
+ import { McpServer } from '@modelcontextprotocol/sdk'
147
+
148
+ const server = new McpServer({ name: 'data-server' })
149
+
150
+ // Dangerous: No user context - can access any user's files
151
+ server.tool('read_user_file', async ({ fileId }: { fileId: string }) => {
152
+ // No user authentication/authorization
153
+ const file = await db.files.findById(fileId)
154
+ return { content: file.content }
155
+ })
156
+
157
+ // Dangerous: Delete without user verification
158
+ server.tool('delete_record', async ({ recordId }: { recordId: string }) => {
159
+ // No check if user owns this record
160
+ await db.records.delete(recordId)
161
+ return { success: true }
162
+ })
163
+
164
+ // Dangerous: Update any user's data
165
+ server.tool('update_profile', async ({ userId, data }: { userId: string; data: any }) => {
166
+ // Can update ANY user's profile, not just the current user
167
+ await db.users.update(userId, data)
168
+ return { success: true }
169
+ })
170
+
171
+ // Dangerous: Cross-tenant data access
172
+ server.tool('get_organization_data', async ({ orgId }: { orgId: string }) => {
173
+ // No tenant verification - can access any org's data
174
+ const data = await db.organizations.findById(orgId)
175
+ return { data }
176
+ })
177
+
178
+ // Dangerous: Admin action without auth
179
+ server.tool('grant_admin', async ({ userId }: { userId: string }) => {
180
+ // No authorization check - any agent can make users admin
181
+ await db.users.update(userId, { role: 'admin' })
182
+ return { success: true }
183
+ })
184
+
185
+ // Dangerous: Sending email as any user
186
+ server.tool('send_email', async ({ from, to, subject, body }: { from: string; to: string; subject: string; body: string }) => {
187
+ // No verification that 'from' is the actual user
188
+ await emailService.send({ from, to, subject, body })
189
+ return { sent: true }
190
+ })
191
+
192
+ // Dangerous: Accessing financial data without scope
193
+ server.tool('get_transactions', async ({ accountId }: { accountId: string }) => {
194
+ // Can access any account's transactions
195
+ const transactions = await financeService.getTransactions(accountId)
196
+ return { transactions }
197
+ })
198
+ `,
199
+ language: 'typescript',
200
+ size: 1700,
201
+ },
202
+ },
203
+ {
204
+ name: 'MCP Security - Python MCP Tools True Positives',
205
+ expectFindings: true,
206
+ expectedCategories: ['ai_mcp_tool_poisoning', 'ai_mcp_credential_issue', 'ai_mcp_confused_deputy'],
207
+ description: 'Python MCP server with security issues',
208
+ file: {
209
+ path: 'src/mcp/server.py',
210
+ content: `
211
+ from mcp import McpServer
212
+ from mcp.server import Tool
213
+
214
+ server = McpServer(name="python-mcp")
215
+
216
+ # Tool poisoning: raw external content
217
+ @server.tool("fetch_url")
218
+ async def fetch_url(url: str) -> dict:
219
+ response = await httpx.get(url)
220
+ # Raw content returned without sanitization
221
+ return {"content": response.text}
222
+
223
+ # Credential issue: API key parameter
224
+ @server.tool("api_call")
225
+ async def api_call(api_key: str, endpoint: str) -> dict:
226
+ response = await httpx.get(endpoint, headers={"Authorization": f"Bearer {api_key}"})
227
+ return {"data": response.json()}
228
+
229
+ # Confused deputy: no user context
230
+ @server.tool("delete_file")
231
+ async def delete_file(file_id: str) -> dict:
232
+ # No user verification
233
+ await storage.delete(file_id)
234
+ return {"deleted": True}
235
+
236
+ # Tool poisoning: returning database content
237
+ @server.tool("search_documents")
238
+ async def search_documents(query: str) -> dict:
239
+ results = await db.search(query)
240
+ return {"documents": results}
241
+
242
+ # Credential in response
243
+ @server.tool("create_api_key")
244
+ async def create_api_key(name: str) -> dict:
245
+ key = await keys.create(name)
246
+ return {"api_key": key.secret} # Exposing secret!
247
+ `,
248
+ language: 'python',
249
+ size: 1100,
250
+ },
251
+ },
252
+ ],
253
+
254
+ falseNegatives: [
255
+ {
256
+ name: 'MCP Security - Safe Patterns',
257
+ expectFindings: false,
258
+ description: 'Safe MCP tool implementations that should NOT be flagged',
259
+ allowedInfoFindings: [
260
+ {
261
+ category: 'ai_mcp_tool_poisoning',
262
+ maxCount: 5,
263
+ reason: 'Some safe patterns may still flag at info level for hygiene',
264
+ },
265
+ {
266
+ category: 'ai_mcp_confused_deputy',
267
+ maxCount: 5,
268
+ reason: 'User context patterns may still flag at info level',
269
+ },
270
+ {
271
+ category: 'ai_overpermissive_tool',
272
+ maxCount: 10,
273
+ reason: 'ai-agent-tools detector flags MCP tool registrations (separate detector)',
274
+ },
275
+ {
276
+ category: 'high_entropy_string',
277
+ maxCount: 2,
278
+ reason: 'DOMPurify import may trigger entropy detection',
279
+ },
280
+ ],
281
+ file: {
282
+ path: 'src/mcp/tools/safe-tools.ts',
283
+ content: `
284
+ import { McpServer } from '@modelcontextprotocol/sdk'
285
+ import { sanitize } from 'dompurify'
286
+ import { validateSchema } from 'zod'
287
+
288
+ const server = new McpServer({ name: 'safe-server' })
289
+
290
+ // Safe: Content sanitized before return
291
+ server.tool('fetch_safe', async ({ url }: { url: string }, context) => {
292
+ const userId = context.user.id // User context!
293
+ const response = await fetch(url)
294
+ const html = await response.text()
295
+ // Content is sanitized
296
+ const sanitized = sanitize(html, { ALLOWED_TAGS: ['p', 'a', 'b'] })
297
+ return { content: sanitized }
298
+ })
299
+
300
+ // Safe: User context properly validated
301
+ server.tool('get_my_files', async (_params, context) => {
302
+ const userId = context.user.id
303
+ // Only getting the current user's files
304
+ const files = await db.files.findByUser(userId)
305
+ return { files: files.map(f => ({ id: f.id, name: f.name })) }
306
+ })
307
+
308
+ // Safe: Server-side auth, no credentials exposed
309
+ server.tool('call_external_api', async ({ endpoint }: { endpoint: string }) => {
310
+ // API key from environment, not passed as parameter
311
+ const response = await fetch(endpoint, {
312
+ headers: { 'Authorization': \`Bearer \${process.env.INTERNAL_API_KEY}\` }
313
+ })
314
+ // Only returning safe data, no credentials
315
+ return { data: await response.json() }
316
+ })
317
+
318
+ // Safe: Proper authorization check
319
+ server.tool('delete_my_record', async ({ recordId }: { recordId: string }, context) => {
320
+ const userId = context.user.id
321
+ const record = await db.records.findById(recordId)
322
+
323
+ // Authorization check
324
+ if (record.ownerId !== userId) {
325
+ throw new Error('Not authorized')
326
+ }
327
+
328
+ await db.records.delete(recordId)
329
+ return { success: true }
330
+ })
331
+
332
+ // Safe: Content validation with schema
333
+ server.tool('search_public_data', async ({ query }: { query: string }, context) => {
334
+ const userId = context.user.id
335
+ const results = await db.publicData.search(query)
336
+ // Returning only safe fields, validated structure
337
+ return {
338
+ results: results.map(r => ({
339
+ id: r.id,
340
+ title: sanitize(r.title), // Sanitized
341
+ summary: sanitize(r.summary) // Sanitized
342
+ }))
343
+ }
344
+ })
345
+
346
+ // Safe: Tenant-scoped operations
347
+ server.tool('get_org_report', async ({ reportId }: { reportId: string }, context) => {
348
+ const tenantId = context.user.tenantId
349
+ const report = await db.reports.findById(reportId)
350
+
351
+ // Tenant check
352
+ if (report.tenantId !== tenantId) {
353
+ throw new Error('Not authorized')
354
+ }
355
+
356
+ return { report }
357
+ })
358
+
359
+ // Safe: Pure computation, no external data
360
+ server.tool('calculate', async ({ expression }: { expression: string }) => {
361
+ // Safe math evaluation, no external content
362
+ const result = mathjs.evaluate(expression)
363
+ return { result }
364
+ })
365
+
366
+ // Safe: Static data only
367
+ server.tool('get_documentation', async ({ topic }: { topic: string }) => {
368
+ // Returns static documentation, not user content
369
+ const docs = await loadStaticDocs(topic)
370
+ return { content: docs }
371
+ })
372
+ `,
373
+ language: 'typescript',
374
+ size: 2500,
375
+ },
376
+ },
377
+ {
378
+ name: 'MCP Security - Test File Patterns',
379
+ expectFindings: false,
380
+ description: 'Test files should not be flagged',
381
+ allowedInfoFindings: [
382
+ {
383
+ category: 'ai_mcp_tool_poisoning',
384
+ maxCount: 3,
385
+ reason: 'Test file may have info-level findings for review',
386
+ },
387
+ {
388
+ category: 'ai_mcp_credential_issue',
389
+ maxCount: 3,
390
+ reason: 'Test file may have info-level findings for review',
391
+ },
392
+ {
393
+ category: 'ai_mcp_confused_deputy',
394
+ maxCount: 3,
395
+ reason: 'Test file may have info-level findings for review',
396
+ },
397
+ {
398
+ category: 'ai_overpermissive_tool',
399
+ maxCount: 3,
400
+ reason: 'ai-agent-tools detector may flag MCP patterns',
401
+ },
402
+ ],
403
+ file: {
404
+ path: 'src/mcp/__tests__/tools.test.ts',
405
+ content: `
406
+ import { McpServer } from '@modelcontextprotocol/sdk'
407
+
408
+ describe('MCP Tools', () => {
409
+ it('should handle raw content in tests', async () => {
410
+ const server = new McpServer({ name: 'test-server' })
411
+
412
+ server.tool('fetch_test', async ({ url }) => {
413
+ const response = await fetch(url)
414
+ return { content: await response.text() }
415
+ })
416
+
417
+ // Test assertions
418
+ })
419
+
420
+ it('should test credential handling', async () => {
421
+ const server = new McpServer({ name: 'test-server' })
422
+
423
+ server.tool('auth_test', async ({ apiKey }) => {
424
+ return { token: 'test-token', apiKey }
425
+ })
426
+ })
427
+
428
+ it('should test user operations', async () => {
429
+ const server = new McpServer({ name: 'test-server' })
430
+
431
+ server.tool('delete_test', async ({ id }) => {
432
+ await mockDb.delete(id)
433
+ return { success: true }
434
+ })
435
+ })
436
+ })
437
+ `,
438
+ language: 'typescript',
439
+ size: 900,
440
+ },
441
+ },
442
+ {
443
+ name: 'MCP Security - Example/Demo Files',
444
+ expectFindings: false,
445
+ description: 'Example files in documentation should be downgraded',
446
+ allowedInfoFindings: [
447
+ {
448
+ category: 'ai_mcp_tool_poisoning',
449
+ maxCount: 5,
450
+ reason: 'Example files may have info-level findings',
451
+ },
452
+ {
453
+ category: 'ai_mcp_credential_issue',
454
+ maxCount: 3,
455
+ reason: 'Example files may have info-level findings',
456
+ },
457
+ {
458
+ category: 'ai_mcp_confused_deputy',
459
+ maxCount: 3,
460
+ reason: 'Example files may have info-level findings',
461
+ },
462
+ {
463
+ category: 'ai_overpermissive_tool',
464
+ maxCount: 3,
465
+ reason: 'ai-agent-tools detector may flag MCP patterns',
466
+ },
467
+ ],
468
+ file: {
469
+ path: 'examples/mcp-quickstart/server.ts',
470
+ content: `
471
+ // This is an example file for documentation
472
+ import { McpServer } from '@modelcontextprotocol/sdk'
473
+
474
+ const server = new McpServer({ name: 'example-server' })
475
+
476
+ // Example: Simple fetch tool
477
+ server.tool('example_fetch', async ({ url }) => {
478
+ const response = await fetch(url)
479
+ return { content: await response.text() }
480
+ })
481
+
482
+ // Example: Data retrieval
483
+ server.tool('example_query', async ({ query }) => {
484
+ const results = await db.query(query)
485
+ return { data: results }
486
+ })
487
+
488
+ console.log('Example server started')
489
+ `,
490
+ language: 'typescript',
491
+ size: 500,
492
+ },
493
+ },
494
+ ],
495
+ }