@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
@@ -86,6 +86,145 @@ export async function chromaUnscopedQuery(query: string) {
86
86
  })
87
87
  return results
88
88
  }
89
+ `,
90
+ language: 'typescript',
91
+ size: 1800,
92
+ },
93
+ },
94
+ // AI Detection Roadmap Phase 1: Enhanced RAG Detection
95
+ {
96
+ name: 'RAG Safety - Corpus Poisoning True Positives',
97
+ expectFindings: true,
98
+ expectedCategories: ['ai_rag_corpus_poisoning'],
99
+ description: 'User uploads directly embedded without sanitization',
100
+ file: {
101
+ path: 'src/api/rag/upload-handler.ts',
102
+ content: `
103
+ import { Pinecone } from '@pinecone-database/pinecone'
104
+ import { OpenAI } from 'openai'
105
+
106
+ const pinecone = new Pinecone()
107
+ const openai = new OpenAI()
108
+
109
+ // Dangerous: User upload embedded directly without sanitization
110
+ export async function handleDocumentUpload(req: Request) {
111
+ const { userId, document } = await req.json()
112
+
113
+ // Direct embedding of user content - no sanitization!
114
+ const embedding = await openai.embeddings.create({
115
+ model: 'text-embedding-3-small',
116
+ input: document.content // Raw user content embedded
117
+ })
118
+
119
+ const index = pinecone.index('knowledge-base')
120
+ await index.upsert([{
121
+ id: document.id,
122
+ values: embedding.data[0].embedding,
123
+ metadata: { userId, content: document.content }
124
+ }])
125
+
126
+ return { success: true }
127
+ }
128
+
129
+ // Dangerous: External content fetched and embedded without validation
130
+ export async function indexExternalContent(url: string) {
131
+ const response = await fetch(url)
132
+ const content = await response.text()
133
+
134
+ // External content embedded without sanitization
135
+ const embedding = await createEmbedding(content)
136
+ await vectorStore.addDocument({ content, embedding })
137
+ }
138
+
139
+ // Dangerous: User-provided PDF indexed without scanning
140
+ export async function indexUploadedPdf(pdfBuffer: Buffer, userId: string) {
141
+ const pdfText = await pdfParser.parse(pdfBuffer)
142
+
143
+ // PDF content could contain injection instructions
144
+ await addToCorpus(pdfText, { userId })
145
+ }
146
+
147
+ // Dangerous: Slack messages indexed without filtering
148
+ export async function indexSlackChannel(channelId: string) {
149
+ const messages = await slack.getMessages(channelId)
150
+
151
+ // User messages embedded - could contain injections
152
+ for (const msg of messages) {
153
+ await embedDocument(msg.text, { author: msg.user })
154
+ }
155
+ }
156
+ `,
157
+ language: 'typescript',
158
+ size: 1500,
159
+ },
160
+ },
161
+ {
162
+ name: 'RAG Safety - PII Leakage True Positives',
163
+ expectFindings: true,
164
+ expectedCategories: ['ai_rag_pii_leakage'],
165
+ description: 'PII fields exposed in RAG retrieval responses',
166
+ file: {
167
+ path: 'src/api/rag/search-handler.ts',
168
+ content: `
169
+ import { VectorStore } from 'langchain/vectorstores'
170
+
171
+ // Dangerous: PII fields in embedded documents
172
+ export async function indexUserProfile(user: User) {
173
+ const doc = {
174
+ content: user.bio,
175
+ metadata: {
176
+ userId: user.id,
177
+ email: user.email, // PII in metadata!
178
+ ssn: user.ssn, // Highly sensitive PII!
179
+ phoneNumber: user.phone, // PII in metadata!
180
+ fullName: user.fullName, // PII in metadata!
181
+ dateOfBirth: user.dob, // PII in metadata!
182
+ address: user.homeAddress, // PII in metadata!
183
+ }
184
+ }
185
+
186
+ await vectorStore.addDocument(doc)
187
+ }
188
+
189
+ // Dangerous: Returning PII in retrieval response
190
+ export async function searchDocuments(query: string) {
191
+ const results = await vectorStore.similaritySearch(query)
192
+
193
+ // Returning full metadata including PII
194
+ return results.map(doc => ({
195
+ content: doc.pageContent,
196
+ email: doc.metadata.email, // PII in response!
197
+ phone: doc.metadata.phone, // PII in response!
198
+ ssn: doc.metadata.ssn, // PII in response!
199
+ author: doc.metadata.fullName, // PII in response!
200
+ }))
201
+ }
202
+
203
+ // Dangerous: Medical records embedded with patient info
204
+ export async function indexMedicalRecords(records: MedicalRecord[]) {
205
+ for (const record of records) {
206
+ await embedDocument(record.diagnosis, {
207
+ patientName: record.patientName, // PHI!
208
+ patientDob: record.dateOfBirth, // PHI!
209
+ patientSsn: record.ssn, // PHI!
210
+ insuranceId: record.insuranceNumber // PHI!
211
+ })
212
+ }
213
+ }
214
+
215
+ // Dangerous: Credit card info in indexed data
216
+ export async function indexTransactions(transactions: Transaction[]) {
217
+ for (const tx of transactions) {
218
+ await vectorStore.addDocument({
219
+ content: tx.description,
220
+ metadata: {
221
+ cardNumber: tx.cardLastFour, // PCI data!
222
+ cvv: tx.cvv, // PCI data - CRITICAL!
223
+ accountNumber: tx.accountNum, // Financial PII!
224
+ }
225
+ })
226
+ }
227
+ }
89
228
  `,
90
229
  language: 'typescript',
91
230
  size: 1800,
@@ -67,6 +67,13 @@ export async function POST(request: Request) {
67
67
  name: 'BYOK - False Negatives',
68
68
  expectFindings: false,
69
69
  description: 'Secure BYOK patterns that should NOT be flagged',
70
+ allowedInfoFindings: [
71
+ {
72
+ category: 'ai_endpoint_unprotected',
73
+ maxCount: 1,
74
+ reason: 'BYOK with auth but missing rate limiting is info-level (user pays for own usage)',
75
+ },
76
+ ],
70
77
  file: {
71
78
  path: 'src/api/ai/byok-transient.ts',
72
79
  content: `
@@ -83,6 +83,69 @@ export async function handleError(error: any) {
83
83
  size: 1400,
84
84
  },
85
85
  },
86
+ {
87
+ name: 'Data Exposure - More Response Patterns',
88
+ expectFindings: true,
89
+ expectedCategories: ['data_exposure'],
90
+ description: 'Additional data exposure patterns in responses that MUST be detected',
91
+ file: {
92
+ path: 'src/api/admin/route.ts',
93
+ content: `
94
+ import { NextResponse } from 'next/server'
95
+
96
+ // Full error object in response - HIGH
97
+ export async function fetchResource() {
98
+ try {
99
+ const data = await db.resource.findMany()
100
+ return NextResponse.json(data)
101
+ } catch (error) {
102
+ return NextResponse.json(error) // Full error object exposed!
103
+ }
104
+ }
105
+
106
+ // Error spread in response - HIGH
107
+ export async function updateResource() {
108
+ try {
109
+ await db.resource.update({ where: { id: 1 }, data: {} })
110
+ } catch (err) {
111
+ return NextResponse.json({ ...err, timestamp: Date.now() }) // Error spread!
112
+ }
113
+ }
114
+
115
+ // Stack trace in API response - HIGH
116
+ export async function processRequest() {
117
+ try {
118
+ await doSomething()
119
+ } catch (error) {
120
+ return NextResponse.json({
121
+ error: error.stack, // Stack trace exposed!
122
+ details: 'Internal error'
123
+ })
124
+ }
125
+ }
126
+
127
+ // Detailed error info in response - MEDIUM
128
+ export async function handleWebhook() {
129
+ try {
130
+ await processWebhook()
131
+ } catch (err) {
132
+ return res.status(500).json({
133
+ details: err.details, // Internal details exposed
134
+ internal: err.message
135
+ })
136
+ }
137
+ }
138
+
139
+ // User object in response (may contain sensitive fields) - LOW
140
+ export async function getProfile(userId: string) {
141
+ const user = await db.user.findUnique({ where: { id: userId } })
142
+ return NextResponse.json({ user }) // May expose sensitive fields
143
+ }
144
+ `,
145
+ language: 'typescript',
146
+ size: 1100,
147
+ },
148
+ },
86
149
  ],
87
150
 
88
151
  falseNegatives: [
@@ -0,0 +1,221 @@
1
+ /**
2
+ * Excessive Agency Test Fixtures
3
+ * Tests for detecting unbounded agent autonomy risks
4
+ * AI Detection Roadmap Phase 2
5
+ */
6
+
7
+ import type { TestGroup } from '../../types'
8
+
9
+ export const excessiveAgencyTests: TestGroup = {
10
+ name: 'Excessive Agency Detection',
11
+ tier: 'A',
12
+ layer: 2,
13
+ description: 'Detection of unbounded AI agent execution and missing human oversight',
14
+
15
+ truePositives: [
16
+ {
17
+ name: 'Excessive Agency - Unbounded Loops',
18
+ expectFindings: true,
19
+ expectedCategories: ['ai_excessive_agency'],
20
+ description: 'Unbounded agent execution patterns that MUST be detected',
21
+ file: {
22
+ path: 'src/agents/unbounded-agent.ts',
23
+ content: `
24
+ import { Agent } from '@langchain/agents'
25
+
26
+ // Unbounded while loop - HIGH
27
+ async function runAgentForever(agent: Agent) {
28
+ while (true) {
29
+ await agent.step() // No termination condition!
30
+ }
31
+ }
32
+
33
+ // No iteration limit - HIGH
34
+ const agentConfig = {
35
+ maxIterations: -1, // Unbounded!
36
+ tools: [searchTool, calculatorTool],
37
+ }
38
+
39
+ // Timeout disabled - MEDIUM
40
+ const runtimeConfig = {
41
+ timeout: 0, // No timeout!
42
+ maxIterations: 10,
43
+ }
44
+
45
+ // Another timeout disabled pattern - MEDIUM
46
+ const config2 = {
47
+ timeout: null, // Disabled
48
+ }
49
+
50
+ // Auto-approve without oversight - HIGH
51
+ const autoAgent = {
52
+ autoApprove: true, // No human review!
53
+ tools: [deleteFileTool, sendEmailTool],
54
+ }
55
+
56
+ // Human-in-loop disabled - MEDIUM
57
+ const unsupervisedAgent = {
58
+ humanInLoop: false, // Explicitly disabled
59
+ capabilities: ['code_execution', 'file_write'],
60
+ }
61
+ `,
62
+ language: 'typescript',
63
+ size: 700,
64
+ },
65
+ },
66
+ {
67
+ name: 'Excessive Agency - CrewAI Unsafe',
68
+ expectFindings: true,
69
+ expectedCategories: ['ai_excessive_agency'],
70
+ description: 'CrewAI unsafe code execution patterns that MUST be detected',
71
+ file: {
72
+ path: 'src/agents/crewai-unsafe.py',
73
+ content: `
74
+ from crewai import Agent, Task, Crew
75
+
76
+ # CrewAI unsafe code execution mode - CRITICAL
77
+ agent = Agent(
78
+ role="Code Executor",
79
+ goal="Execute user code",
80
+ code_execution_mode="unsafe" # CRITICAL: No sandboxing!
81
+ )
82
+
83
+ # CrewAI code execution without Docker - HIGH
84
+ dangerous_agent = Agent(
85
+ role="Script Runner",
86
+ allow_code_execution=True, # HIGH: Runs on host without Docker
87
+ code_execution_config={
88
+ "timeout": 60,
89
+ }
90
+ )
91
+ `,
92
+ language: 'python',
93
+ size: 400,
94
+ },
95
+ },
96
+ {
97
+ name: 'Excessive Agency - AutoGen Unsafe',
98
+ expectFindings: true,
99
+ expectedCategories: ['ai_excessive_agency'],
100
+ description: 'AutoGen unsafe patterns that MUST be detected',
101
+ file: {
102
+ path: 'src/agents/autogen-unsafe.py',
103
+ content: `
104
+ from autogen import UserProxyAgent, AssistantAgent
105
+ from autogen.code_utils import LocalCommandLineCodeExecutor
106
+
107
+ # AutoGen use_docker=False - CRITICAL
108
+ code_executor = LocalCommandLineCodeExecutor(
109
+ work_dir="workspace",
110
+ use_docker=False # CRITICAL: Executes directly on host!
111
+ )
112
+
113
+ # Another use_docker=False pattern
114
+ config = {
115
+ "code_execution_config": {
116
+ "use_docker": False, # CRITICAL
117
+ "work_dir": "workspace",
118
+ }
119
+ }
120
+
121
+ # AutoGen NEVER human input - HIGH
122
+ proxy = UserProxyAgent(
123
+ name="user_proxy",
124
+ human_input_mode="NEVER", # HIGH: No human oversight
125
+ code_execution_config=config,
126
+ )
127
+
128
+ # UserProxyAgent without reply limit - MEDIUM
129
+ unlimited_proxy = UserProxyAgent(
130
+ name="unlimited_proxy",
131
+ human_input_mode="TERMINATE",
132
+ # Missing max_consecutive_auto_reply!
133
+ )
134
+ `,
135
+ language: 'python',
136
+ size: 600,
137
+ },
138
+ },
139
+ ],
140
+
141
+ falseNegatives: [
142
+ {
143
+ name: 'Excessive Agency - Safe Patterns',
144
+ expectFindings: false,
145
+ description: 'Safe agent patterns with proper limits that should NOT be flagged',
146
+ file: {
147
+ path: 'src/agents/safe-agent.ts',
148
+ content: `
149
+ import { Agent } from '@langchain/agents'
150
+
151
+ // Bounded iteration loop - SAFE
152
+ async function runAgentWithLimits(agent: Agent) {
153
+ const maxIterations = 10
154
+ for (let i = 0; i < maxIterations; i++) {
155
+ const result = await agent.step()
156
+ if (result.done) break
157
+ }
158
+ }
159
+
160
+ // Proper configuration - SAFE
161
+ const safeConfig = {
162
+ maxIterations: 15, // Bounded
163
+ timeout: 300000, // 5 minute timeout
164
+ humanInLoop: true, // Human oversight
165
+ budgetLimit: 100, // Cost limit
166
+ }
167
+
168
+ // Human approval required - SAFE
169
+ const reviewedAgent = {
170
+ requireApproval: true,
171
+ tools: [searchTool],
172
+ }
173
+ `,
174
+ language: 'typescript',
175
+ size: 500,
176
+ },
177
+ },
178
+ {
179
+ name: 'Excessive Agency - Safe CrewAI/AutoGen',
180
+ expectFindings: false,
181
+ description: 'Safe CrewAI and AutoGen patterns that should NOT be flagged',
182
+ file: {
183
+ path: 'src/agents/safe-frameworks.py',
184
+ content: `
185
+ from crewai import Agent
186
+ from autogen import UserProxyAgent
187
+ from autogen.code_utils import DockerCommandLineCodeExecutor
188
+
189
+ # CrewAI with safe mode - SAFE
190
+ safe_crewai_agent = Agent(
191
+ role="Safe Executor",
192
+ code_execution_mode="safe" # SAFE: Sandboxed execution
193
+ )
194
+
195
+ # AutoGen with Docker - SAFE
196
+ docker_executor = DockerCommandLineCodeExecutor(
197
+ image="python:3.10-slim",
198
+ timeout=60,
199
+ )
200
+
201
+ # AutoGen with human input - SAFE
202
+ supervised_proxy = UserProxyAgent(
203
+ name="supervised",
204
+ human_input_mode="ALWAYS", # SAFE: Human oversight
205
+ max_consecutive_auto_reply=5, # SAFE: Limited replies
206
+ )
207
+
208
+ # Config with Docker enabled - SAFE
209
+ safe_config = {
210
+ "code_execution_config": {
211
+ "use_docker": True, # SAFE
212
+ "timeout": 60,
213
+ }
214
+ }
215
+ `,
216
+ language: 'python',
217
+ size: 600,
218
+ },
219
+ },
220
+ ],
221
+ }
@@ -21,6 +21,12 @@ export { logicGatesTests } from './logic-gates'
21
21
  export { sensitiveVariablesTests } from './variables'
22
22
  export { riskyImportsTests } from './risky-imports'
23
23
  export { frameworkChecksTests } from './framework-checks'
24
+ // AI Detection Roadmap Phase 1
25
+ export { aiPackageHallucinationTests } from './ai-package-hallucination'
26
+ export { aiMcpSecurityTests } from './ai-mcp-security'
27
+ // AI Detection Roadmap Phase 2
28
+ export { modelSupplyChainTests } from './model-supply-chain'
29
+ export { excessiveAgencyTests } from './excessive-agency'
24
30
 
25
31
  import type { TestGroup } from '../../types'
26
32
  import { dangerousFunctionsTests } from './dangerous-functions'
@@ -41,6 +47,12 @@ import { logicGatesTests } from './logic-gates'
41
47
  import { sensitiveVariablesTests } from './variables'
42
48
  import { riskyImportsTests } from './risky-imports'
43
49
  import { frameworkChecksTests } from './framework-checks'
50
+ // AI Detection Roadmap Phase 1
51
+ import { aiPackageHallucinationTests } from './ai-package-hallucination'
52
+ import { aiMcpSecurityTests } from './ai-mcp-security'
53
+ // AI Detection Roadmap Phase 2
54
+ import { modelSupplyChainTests } from './model-supply-chain'
55
+ import { excessiveAgencyTests } from './excessive-agency'
44
56
 
45
57
  /**
46
58
  * All Layer 2 test groups
@@ -64,4 +76,10 @@ export const layer2TestGroups: TestGroup[] = [
64
76
  sensitiveVariablesTests,
65
77
  riskyImportsTests,
66
78
  frameworkChecksTests,
79
+ // AI Detection Roadmap Phase 1
80
+ aiPackageHallucinationTests,
81
+ aiMcpSecurityTests,
82
+ // AI Detection Roadmap Phase 2
83
+ modelSupplyChainTests,
84
+ excessiveAgencyTests,
67
85
  ]
@@ -0,0 +1,204 @@
1
+ /**
2
+ * Model Supply Chain Security Test Fixtures
3
+ * Tests for detecting unsafe model loading and supply chain risks
4
+ * AI Detection Roadmap Phase 2
5
+ */
6
+
7
+ import type { TestGroup } from '../../types'
8
+
9
+ export const modelSupplyChainTests: TestGroup = {
10
+ name: 'Model Supply Chain Security',
11
+ tier: 'A',
12
+ layer: 2,
13
+ description: 'Detection of unsafe model loading patterns that can lead to RCE',
14
+
15
+ truePositives: [
16
+ {
17
+ name: 'Model Supply Chain - Pickle RCE',
18
+ expectFindings: true,
19
+ expectedCategories: ['ai_unsafe_model_load'],
20
+ description: 'Unsafe pickle/joblib deserialization that MUST be detected',
21
+ file: {
22
+ path: 'src/ml/model_loader.py',
23
+ content: `
24
+ import pickle
25
+ import joblib
26
+ import torch
27
+
28
+ # Pickle deserialization - CRITICAL RCE risk
29
+ def load_user_model(model_path):
30
+ """Load a model file uploaded by user"""
31
+ with open(model_path, 'rb') as f:
32
+ model = pickle.load(f) # CRITICAL: Arbitrary code execution
33
+ return model
34
+
35
+ # Joblib deserialization - CRITICAL RCE risk
36
+ def load_sklearn_model(model_path):
37
+ """Load sklearn model from user upload"""
38
+ model = joblib.load(model_path) # CRITICAL: Uses pickle internally
39
+ return model
40
+
41
+ # Torch.load without weights_only - HIGH
42
+ def load_pytorch_model(checkpoint_path):
43
+ """Load PyTorch checkpoint"""
44
+ checkpoint = torch.load(checkpoint_path) # HIGH: Can execute code
45
+ return checkpoint['model']
46
+ `,
47
+ language: 'python',
48
+ size: 600,
49
+ },
50
+ },
51
+ {
52
+ name: 'Model Supply Chain - Unverified Sources',
53
+ expectFindings: true,
54
+ expectedCategories: ['ai_unverified_model', 'ai_unsafe_model_load'],
55
+ description: 'Models loaded from untrusted sources that MUST be detected',
56
+ file: {
57
+ path: 'src/ml/download_model.py',
58
+ content: `
59
+ from transformers import AutoModelForCausalLM, AutoTokenizer
60
+ import urllib.request
61
+
62
+ # Model from HTTP URL - HIGH (no integrity verification)
63
+ def load_from_url():
64
+ model = AutoModelForCausalLM.from_pretrained("http://malicious-server.com/model")
65
+ return model
66
+
67
+ # trust_remote_code=True - HIGH (executes arbitrary code)
68
+ def load_with_remote_code():
69
+ model = AutoModelForCausalLM.from_pretrained(
70
+ "unknown-org/untrusted-model",
71
+ trust_remote_code=True # HIGH: Executes arbitrary Python
72
+ )
73
+ return model
74
+
75
+ # Model download without checksum - MEDIUM
76
+ def download_raw_model():
77
+ urllib.request.urlretrieve(
78
+ "https://example.com/model.pth", # No checksum verification
79
+ "model.pth"
80
+ )
81
+ `,
82
+ language: 'python',
83
+ size: 500,
84
+ },
85
+ },
86
+ {
87
+ name: 'Model Supply Chain - Unsafe Fine-tuning',
88
+ expectFindings: true,
89
+ expectedCategories: ['ai_unsafe_finetuning'],
90
+ description: 'Unsafe fine-tuning on user data that MUST be detected',
91
+ file: {
92
+ path: 'src/ml/finetune.py',
93
+ content: `
94
+ from transformers import Trainer, TrainingArguments
95
+
96
+ # Training on user uploads - HIGH (data poisoning risk)
97
+ def finetune_on_user_data(user_uploads):
98
+ """Fine-tune model on user-uploaded data"""
99
+ training_args = TrainingArguments(
100
+ output_dir="./results",
101
+ num_train_epochs=3,
102
+ )
103
+ trainer = Trainer(
104
+ model=model,
105
+ args=training_args,
106
+ train_dataset=user_uploads, # HIGH: Unvalidated user data
107
+ )
108
+ trainer.train() # Training on untrusted data
109
+ `,
110
+ language: 'python',
111
+ size: 400,
112
+ },
113
+ },
114
+ {
115
+ name: 'Model Supply Chain - Unverified Downloads',
116
+ expectFindings: true,
117
+ expectedCategories: ['ai_unverified_model'],
118
+ description: 'Model downloads without integrity verification that MUST be detected',
119
+ file: {
120
+ path: 'src/ml/model_downloader.py',
121
+ content: `
122
+ import requests
123
+ import wget
124
+ from transformers import AutoModelForCausalLM
125
+
126
+ # Direct model download without checksum - MEDIUM
127
+ def download_model_unsafe():
128
+ # Using requests to download model file
129
+ response = requests.get("https://random-server.com/model.pth")
130
+ with open("model.pth", "wb") as f:
131
+ f.write(response.content) # No integrity check!
132
+
133
+ # wget without verification - MEDIUM
134
+ def download_with_wget():
135
+ wget.download("http://untrusted-host.com/model.bin", "model.bin")
136
+
137
+ # Model from HTTP (not HTTPS) - HIGH
138
+ def load_from_http():
139
+ model = AutoModelForCausalLM.from_pretrained("http://insecure-host.com/models/gpt")
140
+ return model
141
+
142
+ # Model from unknown Hugging Face org - MEDIUM (no integrity pin)
143
+ def load_unknown_model():
144
+ # No revision pin - could be modified by repo owner
145
+ model = AutoModelForCausalLM.from_pretrained("random-unknown-user/suspicious-model")
146
+ return model
147
+ `,
148
+ language: 'python',
149
+ size: 700,
150
+ },
151
+ },
152
+ ],
153
+
154
+ falseNegatives: [
155
+ {
156
+ name: 'Model Supply Chain - Safe Patterns',
157
+ expectFindings: false,
158
+ description: 'Safe model loading patterns that should NOT be flagged',
159
+ file: {
160
+ path: 'src/ml/safe_model_loader.py',
161
+ content: `
162
+ import torch
163
+ from safetensors.torch import load_file
164
+ from transformers import AutoModelForCausalLM
165
+ import hashlib
166
+
167
+ # SafeTensors - SAFE (no code execution)
168
+ def load_safe_model(model_path):
169
+ """Load model using SafeTensors format"""
170
+ state_dict = load_file(model_path)
171
+ model.load_state_dict(state_dict)
172
+ return model
173
+
174
+ # torch.load with weights_only - SAFE
175
+ def load_pytorch_safe(checkpoint_path):
176
+ """Load PyTorch checkpoint safely"""
177
+ checkpoint = torch.load(checkpoint_path, weights_only=True)
178
+ return checkpoint
179
+
180
+ # Model from trusted source with verification - SAFE
181
+ def load_from_huggingface():
182
+ """Load from official Hugging Face repo with pinned revision"""
183
+ model = AutoModelForCausalLM.from_pretrained(
184
+ "meta-llama/Llama-2-7b",
185
+ revision="a1b2c3d4e5f6" # Pinned to specific commit
186
+ )
187
+ return model
188
+
189
+ # Model with checksum verification - SAFE
190
+ def load_with_verification(model_path, expected_sha256):
191
+ """Load model after verifying checksum"""
192
+ with open(model_path, 'rb') as f:
193
+ file_hash = hashlib.sha256(f.read()).hexdigest()
194
+ if file_hash != expected_sha256:
195
+ raise ValueError("Checksum mismatch!")
196
+ # Safe to load after verification
197
+ return torch.load(model_path, weights_only=True)
198
+ `,
199
+ language: 'python',
200
+ size: 800,
201
+ },
202
+ },
203
+ ],
204
+ }