circle-ir-ai 1.1.0

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 (420) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/LICENSE +15 -0
  3. package/README.md +336 -0
  4. package/dist/action-queue/aggregator.d.ts +40 -0
  5. package/dist/action-queue/aggregator.d.ts.map +1 -0
  6. package/dist/action-queue/aggregator.js +375 -0
  7. package/dist/action-queue/aggregator.js.map +1 -0
  8. package/dist/action-queue/index.d.ts +14 -0
  9. package/dist/action-queue/index.d.ts.map +1 -0
  10. package/dist/action-queue/index.js +17 -0
  11. package/dist/action-queue/index.js.map +1 -0
  12. package/dist/action-queue/queue.d.ts +74 -0
  13. package/dist/action-queue/queue.d.ts.map +1 -0
  14. package/dist/action-queue/queue.js +433 -0
  15. package/dist/action-queue/queue.js.map +1 -0
  16. package/dist/action-queue/types.d.ts +162 -0
  17. package/dist/action-queue/types.d.ts.map +1 -0
  18. package/dist/action-queue/types.js +44 -0
  19. package/dist/action-queue/types.js.map +1 -0
  20. package/dist/agents/enrichment-agent.d.ts +16 -0
  21. package/dist/agents/enrichment-agent.d.ts.map +1 -0
  22. package/dist/agents/enrichment-agent.js +102 -0
  23. package/dist/agents/enrichment-agent.js.map +1 -0
  24. package/dist/agents/index.d.ts +12 -0
  25. package/dist/agents/index.d.ts.map +1 -0
  26. package/dist/agents/index.js +15 -0
  27. package/dist/agents/index.js.map +1 -0
  28. package/dist/agents/mastra/agents.d.ts +373 -0
  29. package/dist/agents/mastra/agents.d.ts.map +1 -0
  30. package/dist/agents/mastra/agents.js +347 -0
  31. package/dist/agents/mastra/agents.js.map +1 -0
  32. package/dist/agents/mastra/index.d.ts +12 -0
  33. package/dist/agents/mastra/index.d.ts.map +1 -0
  34. package/dist/agents/mastra/index.js +17 -0
  35. package/dist/agents/mastra/index.js.map +1 -0
  36. package/dist/agents/mastra/instance.d.ts +383 -0
  37. package/dist/agents/mastra/instance.d.ts.map +1 -0
  38. package/dist/agents/mastra/instance.js +37 -0
  39. package/dist/agents/mastra/instance.js.map +1 -0
  40. package/dist/agents/mastra/steps.d.ts +300 -0
  41. package/dist/agents/mastra/steps.d.ts.map +1 -0
  42. package/dist/agents/mastra/steps.js +468 -0
  43. package/dist/agents/mastra/steps.js.map +1 -0
  44. package/dist/agents/mastra/swarm.d.ts +106 -0
  45. package/dist/agents/mastra/swarm.d.ts.map +1 -0
  46. package/dist/agents/mastra/swarm.js +501 -0
  47. package/dist/agents/mastra/swarm.js.map +1 -0
  48. package/dist/agents/mastra/workflow.d.ts +81 -0
  49. package/dist/agents/mastra/workflow.d.ts.map +1 -0
  50. package/dist/agents/mastra/workflow.js +460 -0
  51. package/dist/agents/mastra/workflow.js.map +1 -0
  52. package/dist/agents/multi/agents/security.d.ts +29 -0
  53. package/dist/agents/multi/agents/security.d.ts.map +1 -0
  54. package/dist/agents/multi/agents/security.js +830 -0
  55. package/dist/agents/multi/agents/security.js.map +1 -0
  56. package/dist/agents/multi/extractor.d.ts +21 -0
  57. package/dist/agents/multi/extractor.d.ts.map +1 -0
  58. package/dist/agents/multi/extractor.js +483 -0
  59. package/dist/agents/multi/extractor.js.map +1 -0
  60. package/dist/agents/multi/index.d.ts +32 -0
  61. package/dist/agents/multi/index.d.ts.map +1 -0
  62. package/dist/agents/multi/index.js +34 -0
  63. package/dist/agents/multi/index.js.map +1 -0
  64. package/dist/agents/multi/runner.d.ts +79 -0
  65. package/dist/agents/multi/runner.d.ts.map +1 -0
  66. package/dist/agents/multi/runner.js +323 -0
  67. package/dist/agents/multi/runner.js.map +1 -0
  68. package/dist/agents/security-agent.d.ts +16 -0
  69. package/dist/agents/security-agent.d.ts.map +1 -0
  70. package/dist/agents/security-agent.js +299 -0
  71. package/dist/agents/security-agent.js.map +1 -0
  72. package/dist/agents/types.d.ts +373 -0
  73. package/dist/agents/types.d.ts.map +1 -0
  74. package/dist/agents/types.js +14 -0
  75. package/dist/agents/types.js.map +1 -0
  76. package/dist/agents/verification-agent.d.ts +23 -0
  77. package/dist/agents/verification-agent.d.ts.map +1 -0
  78. package/dist/agents/verification-agent.js +217 -0
  79. package/dist/agents/verification-agent.js.map +1 -0
  80. package/dist/agents/workflow.d.ts +30 -0
  81. package/dist/agents/workflow.d.ts.map +1 -0
  82. package/dist/agents/workflow.js +79 -0
  83. package/dist/agents/workflow.js.map +1 -0
  84. package/dist/analysis/enriched.d.ts +16 -0
  85. package/dist/analysis/enriched.d.ts.map +1 -0
  86. package/dist/analysis/enriched.js +297 -0
  87. package/dist/analysis/enriched.js.map +1 -0
  88. package/dist/analysis/llm-correlated-predicates.d.ts +80 -0
  89. package/dist/analysis/llm-correlated-predicates.d.ts.map +1 -0
  90. package/dist/analysis/llm-correlated-predicates.js +255 -0
  91. package/dist/analysis/llm-correlated-predicates.js.map +1 -0
  92. package/dist/analysis/llm-cross-file-taint.d.ts +86 -0
  93. package/dist/analysis/llm-cross-file-taint.d.ts.map +1 -0
  94. package/dist/analysis/llm-cross-file-taint.js +264 -0
  95. package/dist/analysis/llm-cross-file-taint.js.map +1 -0
  96. package/dist/analysis/pattern-discovery.d.ts +79 -0
  97. package/dist/analysis/pattern-discovery.d.ts.map +1 -0
  98. package/dist/analysis/pattern-discovery.js +447 -0
  99. package/dist/analysis/pattern-discovery.js.map +1 -0
  100. package/dist/cache/file-cache.d.ts +89 -0
  101. package/dist/cache/file-cache.d.ts.map +1 -0
  102. package/dist/cache/file-cache.js +208 -0
  103. package/dist/cache/file-cache.js.map +1 -0
  104. package/dist/cache/index.d.ts +6 -0
  105. package/dist/cache/index.d.ts.map +1 -0
  106. package/dist/cache/index.js +5 -0
  107. package/dist/cache/index.js.map +1 -0
  108. package/dist/cli/args.d.ts +52 -0
  109. package/dist/cli/args.d.ts.map +1 -0
  110. package/dist/cli/args.js +422 -0
  111. package/dist/cli/args.js.map +1 -0
  112. package/dist/cli/colors.d.ts +31 -0
  113. package/dist/cli/colors.d.ts.map +1 -0
  114. package/dist/cli/colors.js +80 -0
  115. package/dist/cli/colors.js.map +1 -0
  116. package/dist/cli/commands/analyze-skill.d.ts +33 -0
  117. package/dist/cli/commands/analyze-skill.d.ts.map +1 -0
  118. package/dist/cli/commands/analyze-skill.js +217 -0
  119. package/dist/cli/commands/analyze-skill.js.map +1 -0
  120. package/dist/cli/commands/analyze.d.ts +18 -0
  121. package/dist/cli/commands/analyze.d.ts.map +1 -0
  122. package/dist/cli/commands/analyze.js +30 -0
  123. package/dist/cli/commands/analyze.js.map +1 -0
  124. package/dist/cli/commands/benchmark-runner.d.ts +42 -0
  125. package/dist/cli/commands/benchmark-runner.d.ts.map +1 -0
  126. package/dist/cli/commands/benchmark-runner.js +18 -0
  127. package/dist/cli/commands/benchmark-runner.js.map +1 -0
  128. package/dist/cli/commands/benchmark.d.ts +11 -0
  129. package/dist/cli/commands/benchmark.d.ts.map +1 -0
  130. package/dist/cli/commands/benchmark.js +90 -0
  131. package/dist/cli/commands/benchmark.js.map +1 -0
  132. package/dist/cli/commands/dead-code.d.ts +11 -0
  133. package/dist/cli/commands/dead-code.d.ts.map +1 -0
  134. package/dist/cli/commands/dead-code.js +65 -0
  135. package/dist/cli/commands/dead-code.js.map +1 -0
  136. package/dist/cli/commands/generate-spec.d.ts +11 -0
  137. package/dist/cli/commands/generate-spec.d.ts.map +1 -0
  138. package/dist/cli/commands/generate-spec.js +67 -0
  139. package/dist/cli/commands/generate-spec.js.map +1 -0
  140. package/dist/cli/commands/health.d.ts +11 -0
  141. package/dist/cli/commands/health.d.ts.map +1 -0
  142. package/dist/cli/commands/health.js +67 -0
  143. package/dist/cli/commands/health.js.map +1 -0
  144. package/dist/cli/commands/project.d.ts +21 -0
  145. package/dist/cli/commands/project.d.ts.map +1 -0
  146. package/dist/cli/commands/project.js +92 -0
  147. package/dist/cli/commands/project.js.map +1 -0
  148. package/dist/cli/commands/scan.d.ts +11 -0
  149. package/dist/cli/commands/scan.d.ts.map +1 -0
  150. package/dist/cli/commands/scan.js +68 -0
  151. package/dist/cli/commands/scan.js.map +1 -0
  152. package/dist/cli/commands/secrets.d.ts +11 -0
  153. package/dist/cli/commands/secrets.d.ts.map +1 -0
  154. package/dist/cli/commands/secrets.js +71 -0
  155. package/dist/cli/commands/secrets.js.map +1 -0
  156. package/dist/cli/commands/swarm.d.ts +20 -0
  157. package/dist/cli/commands/swarm.d.ts.map +1 -0
  158. package/dist/cli/commands/swarm.js +174 -0
  159. package/dist/cli/commands/swarm.js.map +1 -0
  160. package/dist/cli/config.d.ts +103 -0
  161. package/dist/cli/config.d.ts.map +1 -0
  162. package/dist/cli/config.js +307 -0
  163. package/dist/cli/config.js.map +1 -0
  164. package/dist/cli/discovery.d.ts +31 -0
  165. package/dist/cli/discovery.d.ts.map +1 -0
  166. package/dist/cli/discovery.js +212 -0
  167. package/dist/cli/discovery.js.map +1 -0
  168. package/dist/cli/formatters/index.d.ts +15 -0
  169. package/dist/cli/formatters/index.d.ts.map +1 -0
  170. package/dist/cli/formatters/index.js +51 -0
  171. package/dist/cli/formatters/index.js.map +1 -0
  172. package/dist/cli/formatters/json.d.ts +11 -0
  173. package/dist/cli/formatters/json.d.ts.map +1 -0
  174. package/dist/cli/formatters/json.js +12 -0
  175. package/dist/cli/formatters/json.js.map +1 -0
  176. package/dist/cli/formatters/project-json.d.ts +11 -0
  177. package/dist/cli/formatters/project-json.d.ts.map +1 -0
  178. package/dist/cli/formatters/project-json.js +12 -0
  179. package/dist/cli/formatters/project-json.js.map +1 -0
  180. package/dist/cli/formatters/project-sarif.d.ts +11 -0
  181. package/dist/cli/formatters/project-sarif.d.ts.map +1 -0
  182. package/dist/cli/formatters/project-sarif.js +127 -0
  183. package/dist/cli/formatters/project-sarif.js.map +1 -0
  184. package/dist/cli/formatters/project-summary.d.ts +11 -0
  185. package/dist/cli/formatters/project-summary.d.ts.map +1 -0
  186. package/dist/cli/formatters/project-summary.js +202 -0
  187. package/dist/cli/formatters/project-summary.js.map +1 -0
  188. package/dist/cli/formatters/sarif-shared.d.ts +101 -0
  189. package/dist/cli/formatters/sarif-shared.d.ts.map +1 -0
  190. package/dist/cli/formatters/sarif-shared.js +57 -0
  191. package/dist/cli/formatters/sarif-shared.js.map +1 -0
  192. package/dist/cli/formatters/sarif.d.ts +12 -0
  193. package/dist/cli/formatters/sarif.d.ts.map +1 -0
  194. package/dist/cli/formatters/sarif.js +92 -0
  195. package/dist/cli/formatters/sarif.js.map +1 -0
  196. package/dist/cli/formatters/summary.d.ts +11 -0
  197. package/dist/cli/formatters/summary.d.ts.map +1 -0
  198. package/dist/cli/formatters/summary.js +240 -0
  199. package/dist/cli/formatters/summary.js.map +1 -0
  200. package/dist/cli/formatters/two-phase-summary.d.ts +11 -0
  201. package/dist/cli/formatters/two-phase-summary.d.ts.map +1 -0
  202. package/dist/cli/formatters/two-phase-summary.js +188 -0
  203. package/dist/cli/formatters/two-phase-summary.js.map +1 -0
  204. package/dist/cli/index.d.ts +15 -0
  205. package/dist/cli/index.d.ts.map +1 -0
  206. package/dist/cli/index.js +555 -0
  207. package/dist/cli/index.js.map +1 -0
  208. package/dist/components/clustering.d.ts +60 -0
  209. package/dist/components/clustering.d.ts.map +1 -0
  210. package/dist/components/clustering.js +129 -0
  211. package/dist/components/clustering.js.map +1 -0
  212. package/dist/components/enrichment.d.ts +45 -0
  213. package/dist/components/enrichment.d.ts.map +1 -0
  214. package/dist/components/enrichment.js +193 -0
  215. package/dist/components/enrichment.js.map +1 -0
  216. package/dist/components/index.d.ts +29 -0
  217. package/dist/components/index.d.ts.map +1 -0
  218. package/dist/components/index.js +56 -0
  219. package/dist/components/index.js.map +1 -0
  220. package/dist/dead-code/detector.d.ts +200 -0
  221. package/dist/dead-code/detector.d.ts.map +1 -0
  222. package/dist/dead-code/detector.js +1003 -0
  223. package/dist/dead-code/detector.js.map +1 -0
  224. package/dist/dead-code/index.d.ts +7 -0
  225. package/dist/dead-code/index.d.ts.map +1 -0
  226. package/dist/dead-code/index.js +7 -0
  227. package/dist/dead-code/index.js.map +1 -0
  228. package/dist/extractors/index.d.ts +15 -0
  229. package/dist/extractors/index.d.ts.map +1 -0
  230. package/dist/extractors/index.js +14 -0
  231. package/dist/extractors/index.js.map +1 -0
  232. package/dist/extractors/natural-language.d.ts +46 -0
  233. package/dist/extractors/natural-language.d.ts.map +1 -0
  234. package/dist/extractors/natural-language.js +228 -0
  235. package/dist/extractors/natural-language.js.map +1 -0
  236. package/dist/extractors/tree-sitter.d.ts +33 -0
  237. package/dist/extractors/tree-sitter.d.ts.map +1 -0
  238. package/dist/extractors/tree-sitter.js +69 -0
  239. package/dist/extractors/tree-sitter.js.map +1 -0
  240. package/dist/extractors/types.d.ts +62 -0
  241. package/dist/extractors/types.d.ts.map +1 -0
  242. package/dist/extractors/types.js +54 -0
  243. package/dist/extractors/types.js.map +1 -0
  244. package/dist/health-score/calculator.d.ts +123 -0
  245. package/dist/health-score/calculator.d.ts.map +1 -0
  246. package/dist/health-score/calculator.js +444 -0
  247. package/dist/health-score/calculator.js.map +1 -0
  248. package/dist/health-score/index.d.ts +12 -0
  249. package/dist/health-score/index.d.ts.map +1 -0
  250. package/dist/health-score/index.js +14 -0
  251. package/dist/health-score/index.js.map +1 -0
  252. package/dist/health-score/metrics.d.ts +142 -0
  253. package/dist/health-score/metrics.d.ts.map +1 -0
  254. package/dist/health-score/metrics.js +332 -0
  255. package/dist/health-score/metrics.js.map +1 -0
  256. package/dist/index.d.ts +26 -0
  257. package/dist/index.d.ts.map +1 -0
  258. package/dist/index.js +43 -0
  259. package/dist/index.js.map +1 -0
  260. package/dist/llm/ax-client.d.ts +477 -0
  261. package/dist/llm/ax-client.d.ts.map +1 -0
  262. package/dist/llm/ax-client.js +1641 -0
  263. package/dist/llm/ax-client.js.map +1 -0
  264. package/dist/llm/config.d.ts +58 -0
  265. package/dist/llm/config.d.ts.map +1 -0
  266. package/dist/llm/config.js +97 -0
  267. package/dist/llm/config.js.map +1 -0
  268. package/dist/llm/discovery.d.ts +123 -0
  269. package/dist/llm/discovery.d.ts.map +1 -0
  270. package/dist/llm/discovery.js +505 -0
  271. package/dist/llm/discovery.js.map +1 -0
  272. package/dist/llm/enrichment.d.ts +108 -0
  273. package/dist/llm/enrichment.d.ts.map +1 -0
  274. package/dist/llm/enrichment.js +312 -0
  275. package/dist/llm/enrichment.js.map +1 -0
  276. package/dist/llm/index.d.ts +13 -0
  277. package/dist/llm/index.d.ts.map +1 -0
  278. package/dist/llm/index.js +22 -0
  279. package/dist/llm/index.js.map +1 -0
  280. package/dist/llm/language-context.d.ts +64 -0
  281. package/dist/llm/language-context.d.ts.map +1 -0
  282. package/dist/llm/language-context.js +492 -0
  283. package/dist/llm/language-context.js.map +1 -0
  284. package/dist/llm/pattern-verification.d.ts +39 -0
  285. package/dist/llm/pattern-verification.d.ts.map +1 -0
  286. package/dist/llm/pattern-verification.js +127 -0
  287. package/dist/llm/pattern-verification.js.map +1 -0
  288. package/dist/llm/prompt-security.d.ts +120 -0
  289. package/dist/llm/prompt-security.d.ts.map +1 -0
  290. package/dist/llm/prompt-security.js +301 -0
  291. package/dist/llm/prompt-security.js.map +1 -0
  292. package/dist/llm/prompts/index.d.ts +31 -0
  293. package/dist/llm/prompts/index.d.ts.map +1 -0
  294. package/dist/llm/prompts/index.js +92 -0
  295. package/dist/llm/prompts/index.js.map +1 -0
  296. package/dist/llm/prompts/rust.d.ts +30 -0
  297. package/dist/llm/prompts/rust.d.ts.map +1 -0
  298. package/dist/llm/prompts/rust.js +121 -0
  299. package/dist/llm/prompts/rust.js.map +1 -0
  300. package/dist/llm/schemas.d.ts +892 -0
  301. package/dist/llm/schemas.d.ts.map +1 -0
  302. package/dist/llm/schemas.js +258 -0
  303. package/dist/llm/schemas.js.map +1 -0
  304. package/dist/llm/verification.d.ts +127 -0
  305. package/dist/llm/verification.d.ts.map +1 -0
  306. package/dist/llm/verification.js +394 -0
  307. package/dist/llm/verification.js.map +1 -0
  308. package/dist/project/analyzer.d.ts +30 -0
  309. package/dist/project/analyzer.d.ts.map +1 -0
  310. package/dist/project/analyzer.js +358 -0
  311. package/dist/project/analyzer.js.map +1 -0
  312. package/dist/project/call-graph.d.ts +22 -0
  313. package/dist/project/call-graph.d.ts.map +1 -0
  314. package/dist/project/call-graph.js +246 -0
  315. package/dist/project/call-graph.js.map +1 -0
  316. package/dist/project/index.d.ts +18 -0
  317. package/dist/project/index.d.ts.map +1 -0
  318. package/dist/project/index.js +20 -0
  319. package/dist/project/index.js.map +1 -0
  320. package/dist/project/taint-paths.d.ts +22 -0
  321. package/dist/project/taint-paths.d.ts.map +1 -0
  322. package/dist/project/taint-paths.js +265 -0
  323. package/dist/project/taint-paths.js.map +1 -0
  324. package/dist/project/two-phase-analyzer.d.ts +143 -0
  325. package/dist/project/two-phase-analyzer.d.ts.map +1 -0
  326. package/dist/project/two-phase-analyzer.js +646 -0
  327. package/dist/project/two-phase-analyzer.js.map +1 -0
  328. package/dist/project/type-hierarchy.d.ts +28 -0
  329. package/dist/project/type-hierarchy.d.ts.map +1 -0
  330. package/dist/project/type-hierarchy.js +218 -0
  331. package/dist/project/type-hierarchy.js.map +1 -0
  332. package/dist/secret-scan/index.d.ts +12 -0
  333. package/dist/secret-scan/index.d.ts.map +1 -0
  334. package/dist/secret-scan/index.js +14 -0
  335. package/dist/secret-scan/index.js.map +1 -0
  336. package/dist/secret-scan/patterns.d.ts +38 -0
  337. package/dist/secret-scan/patterns.d.ts.map +1 -0
  338. package/dist/secret-scan/patterns.js +473 -0
  339. package/dist/secret-scan/patterns.js.map +1 -0
  340. package/dist/secret-scan/scanner.d.ts +162 -0
  341. package/dist/secret-scan/scanner.d.ts.map +1 -0
  342. package/dist/secret-scan/scanner.js +511 -0
  343. package/dist/secret-scan/scanner.js.map +1 -0
  344. package/dist/security-scan/index.d.ts +12 -0
  345. package/dist/security-scan/index.d.ts.map +1 -0
  346. package/dist/security-scan/index.js +15 -0
  347. package/dist/security-scan/index.js.map +1 -0
  348. package/dist/security-scan/owasp-mapping.d.ts +29 -0
  349. package/dist/security-scan/owasp-mapping.d.ts.map +1 -0
  350. package/dist/security-scan/owasp-mapping.js +246 -0
  351. package/dist/security-scan/owasp-mapping.js.map +1 -0
  352. package/dist/security-scan/scanner.d.ts +204 -0
  353. package/dist/security-scan/scanner.d.ts.map +1 -0
  354. package/dist/security-scan/scanner.js +693 -0
  355. package/dist/security-scan/scanner.js.map +1 -0
  356. package/dist/security-scan/trend-tracker.d.ts +150 -0
  357. package/dist/security-scan/trend-tracker.d.ts.map +1 -0
  358. package/dist/security-scan/trend-tracker.js +299 -0
  359. package/dist/security-scan/trend-tracker.js.map +1 -0
  360. package/dist/skills/bundle-loader.d.ts +26 -0
  361. package/dist/skills/bundle-loader.d.ts.map +1 -0
  362. package/dist/skills/bundle-loader.js +284 -0
  363. package/dist/skills/bundle-loader.js.map +1 -0
  364. package/dist/skills/capability-mismatch.d.ts +21 -0
  365. package/dist/skills/capability-mismatch.d.ts.map +1 -0
  366. package/dist/skills/capability-mismatch.js +188 -0
  367. package/dist/skills/capability-mismatch.js.map +1 -0
  368. package/dist/skills/index.d.ts +10 -0
  369. package/dist/skills/index.d.ts.map +1 -0
  370. package/dist/skills/index.js +9 -0
  371. package/dist/skills/index.js.map +1 -0
  372. package/dist/skills/skill-analyzer.d.ts +16 -0
  373. package/dist/skills/skill-analyzer.d.ts.map +1 -0
  374. package/dist/skills/skill-analyzer.js +361 -0
  375. package/dist/skills/skill-analyzer.js.map +1 -0
  376. package/dist/skills/types.d.ts +195 -0
  377. package/dist/skills/types.d.ts.map +1 -0
  378. package/dist/skills/types.js +7 -0
  379. package/dist/skills/types.js.map +1 -0
  380. package/dist/specifica/conflict-resolver.d.ts +23 -0
  381. package/dist/specifica/conflict-resolver.d.ts.map +1 -0
  382. package/dist/specifica/conflict-resolver.js +129 -0
  383. package/dist/specifica/conflict-resolver.js.map +1 -0
  384. package/dist/specifica/evidence-aggregator.d.ts +33 -0
  385. package/dist/specifica/evidence-aggregator.d.ts.map +1 -0
  386. package/dist/specifica/evidence-aggregator.js +236 -0
  387. package/dist/specifica/evidence-aggregator.js.map +1 -0
  388. package/dist/specifica/evidence-extractor.d.ts +13 -0
  389. package/dist/specifica/evidence-extractor.d.ts.map +1 -0
  390. package/dist/specifica/evidence-extractor.js +431 -0
  391. package/dist/specifica/evidence-extractor.js.map +1 -0
  392. package/dist/specifica/feature-clustering.d.ts +19 -0
  393. package/dist/specifica/feature-clustering.d.ts.map +1 -0
  394. package/dist/specifica/feature-clustering.js +231 -0
  395. package/dist/specifica/feature-clustering.js.map +1 -0
  396. package/dist/specifica/generator.d.ts +16 -0
  397. package/dist/specifica/generator.d.ts.map +1 -0
  398. package/dist/specifica/generator.js +277 -0
  399. package/dist/specifica/generator.js.map +1 -0
  400. package/dist/specifica/index.d.ts +15 -0
  401. package/dist/specifica/index.d.ts.map +1 -0
  402. package/dist/specifica/index.js +18 -0
  403. package/dist/specifica/index.js.map +1 -0
  404. package/dist/specifica/prompts.d.ts +21 -0
  405. package/dist/specifica/prompts.d.ts.map +1 -0
  406. package/dist/specifica/prompts.js +196 -0
  407. package/dist/specifica/prompts.js.map +1 -0
  408. package/dist/specifica/spec-generator.d.ts +22 -0
  409. package/dist/specifica/spec-generator.d.ts.map +1 -0
  410. package/dist/specifica/spec-generator.js +229 -0
  411. package/dist/specifica/spec-generator.js.map +1 -0
  412. package/dist/specifica/types.d.ts +213 -0
  413. package/dist/specifica/types.d.ts.map +1 -0
  414. package/dist/specifica/types.js +7 -0
  415. package/dist/specifica/types.js.map +1 -0
  416. package/dist/utils/logger.d.ts +17 -0
  417. package/dist/utils/logger.d.ts.map +1 -0
  418. package/dist/utils/logger.js +51 -0
  419. package/dist/utils/logger.js.map +1 -0
  420. package/package.json +99 -0
@@ -0,0 +1,830 @@
1
+ /**
2
+ * Security Agents
3
+ *
4
+ * Specialized agents for detecting security vulnerabilities.
5
+ * These agents analyze the enriched IR for different vulnerability types.
6
+ */
7
+ import { registerAgent } from '../runner.js';
8
+ // ============================================================================
9
+ // SQL Injection Agent
10
+ // ============================================================================
11
+ export const sqlInjectionAgent = {
12
+ id: 'security.sql-injection',
13
+ name: 'SQL Injection Detector',
14
+ description: 'Detects SQL injection vulnerabilities by analyzing taint flows to SQL sinks',
15
+ category: 'security',
16
+ async analyze(ir, options) {
17
+ const findings = [];
18
+ const startTime = Date.now();
19
+ // Get SQL-related sinks from base IR
20
+ const sqlSinks = ir.base.taint.sinks.filter(s => s.type === 'sql_injection');
21
+ const sources = ir.base.taint.sources;
22
+ // Check for SQL patterns in strings
23
+ const sqlStrings = ir.strings.filter(s => s.pattern === 'sql');
24
+ for (const sink of sqlSinks) {
25
+ // Check if there's a taint path from any source
26
+ const hasSourceInSameMethod = sources.some(src => src.line < sink.line && findContainingMethod(src.line, ir) === findContainingMethod(sink.line, ir));
27
+ if (hasSourceInSameMethod) {
28
+ findings.push({
29
+ id: `sqli-${sink.line}`,
30
+ type: 'sql-injection',
31
+ message: `Potential SQL injection at line ${sink.line}. User input may flow to SQL query.`,
32
+ severity: 'critical',
33
+ confidence: 0.9,
34
+ cwe: 'CWE-89',
35
+ owasp: 'A03:2021',
36
+ location: {
37
+ file: ir.filePath,
38
+ line: sink.line,
39
+ },
40
+ sink: { line: sink.line, type: sink.type },
41
+ remediation: 'Use parameterized queries (PreparedStatement) instead of string concatenation.',
42
+ });
43
+ }
44
+ }
45
+ // Check for string concatenation in SQL patterns
46
+ for (const str of sqlStrings) {
47
+ if (str.context === 'argument' || str.context === 'assignment') {
48
+ // Check if there's a source in the same method
49
+ const method = str.inMethod;
50
+ const hasSourceInMethod = sources.some(src => findContainingMethod(src.line, ir) === method);
51
+ if (hasSourceInMethod && !findings.some(f => f.location.line === str.line)) {
52
+ findings.push({
53
+ id: `sqli-string-${str.line}`,
54
+ type: 'sql-injection',
55
+ message: `SQL query pattern detected at line ${str.line}. Verify parameterization.`,
56
+ severity: 'high',
57
+ confidence: 0.7,
58
+ cwe: 'CWE-89',
59
+ location: {
60
+ file: ir.filePath,
61
+ line: str.line,
62
+ column: str.column,
63
+ },
64
+ remediation: 'Use parameterized queries instead of string concatenation.',
65
+ });
66
+ }
67
+ }
68
+ }
69
+ return {
70
+ agentId: sqlInjectionAgent.id,
71
+ agentName: sqlInjectionAgent.name,
72
+ category: 'security',
73
+ success: true,
74
+ findings,
75
+ processingTimeMs: Date.now() - startTime,
76
+ };
77
+ },
78
+ };
79
+ // ============================================================================
80
+ // XSS Agent
81
+ // ============================================================================
82
+ export const xssAgent = {
83
+ id: 'security.xss',
84
+ name: 'XSS Detector',
85
+ description: 'Detects Cross-Site Scripting vulnerabilities',
86
+ category: 'security',
87
+ async analyze(ir, options) {
88
+ const findings = [];
89
+ const startTime = Date.now();
90
+ // Get XSS sinks from base IR
91
+ const xssSinks = ir.base.taint.sinks.filter(s => s.type === 'xss');
92
+ const sources = ir.base.taint.sources;
93
+ for (const sink of xssSinks) {
94
+ const hasSourceInSameMethod = sources.some(src => src.line < sink.line && findContainingMethod(src.line, ir) === findContainingMethod(sink.line, ir));
95
+ if (hasSourceInSameMethod) {
96
+ findings.push({
97
+ id: `xss-${sink.line}`,
98
+ type: 'xss',
99
+ message: `Potential XSS vulnerability at line ${sink.line}. User input may be written to response.`,
100
+ severity: 'high',
101
+ confidence: 0.85,
102
+ cwe: 'CWE-79',
103
+ owasp: 'A03:2021',
104
+ location: {
105
+ file: ir.filePath,
106
+ line: sink.line,
107
+ },
108
+ sink: { line: sink.line, type: sink.type },
109
+ remediation: 'Encode output using appropriate escaping (HTML, JavaScript, URL encoding).',
110
+ });
111
+ }
112
+ }
113
+ // Check for HTML patterns in strings with sources
114
+ const htmlStrings = ir.strings.filter(s => s.pattern === 'html');
115
+ for (const str of htmlStrings) {
116
+ const method = str.inMethod;
117
+ const hasSourceInMethod = sources.some(src => findContainingMethod(src.line, ir) === method);
118
+ if (hasSourceInMethod) {
119
+ findings.push({
120
+ id: `xss-html-${str.line}`,
121
+ type: 'xss',
122
+ message: `HTML content generation at line ${str.line}. Verify proper encoding.`,
123
+ severity: 'medium',
124
+ confidence: 0.6,
125
+ cwe: 'CWE-79',
126
+ location: {
127
+ file: ir.filePath,
128
+ line: str.line,
129
+ },
130
+ remediation: 'Use a templating engine with automatic HTML escaping.',
131
+ });
132
+ }
133
+ }
134
+ return {
135
+ agentId: xssAgent.id,
136
+ agentName: xssAgent.name,
137
+ category: 'security',
138
+ success: true,
139
+ findings,
140
+ processingTimeMs: Date.now() - startTime,
141
+ };
142
+ },
143
+ };
144
+ // ============================================================================
145
+ // Command Injection Agent
146
+ // ============================================================================
147
+ export const commandInjectionAgent = {
148
+ id: 'security.command-injection',
149
+ name: 'Command Injection Detector',
150
+ description: 'Detects OS command injection vulnerabilities',
151
+ category: 'security',
152
+ async analyze(ir, options) {
153
+ const findings = [];
154
+ const startTime = Date.now();
155
+ // Get command injection sinks from base IR
156
+ const cmdSinks = ir.base.taint.sinks.filter(s => s.type === 'command_injection');
157
+ const sources = ir.base.taint.sources;
158
+ for (const sink of cmdSinks) {
159
+ const hasSourceInSameMethod = sources.some(src => src.line < sink.line && findContainingMethod(src.line, ir) === findContainingMethod(sink.line, ir));
160
+ if (hasSourceInSameMethod) {
161
+ findings.push({
162
+ id: `cmd-${sink.line}`,
163
+ type: 'command-injection',
164
+ message: `Potential command injection at line ${sink.line}. User input may flow to system command.`,
165
+ severity: 'critical',
166
+ confidence: 0.9,
167
+ cwe: 'CWE-78',
168
+ owasp: 'A03:2021',
169
+ location: {
170
+ file: ir.filePath,
171
+ line: sink.line,
172
+ },
173
+ sink: { line: sink.line, type: sink.type },
174
+ remediation: 'Avoid shell commands with user input. Use allowlists and ProcessBuilder with array arguments.',
175
+ });
176
+ }
177
+ }
178
+ return {
179
+ agentId: commandInjectionAgent.id,
180
+ agentName: commandInjectionAgent.name,
181
+ category: 'security',
182
+ success: true,
183
+ findings,
184
+ processingTimeMs: Date.now() - startTime,
185
+ };
186
+ },
187
+ };
188
+ // ============================================================================
189
+ // Path Traversal Agent
190
+ // ============================================================================
191
+ export const pathTraversalAgent = {
192
+ id: 'security.path-traversal',
193
+ name: 'Path Traversal Detector',
194
+ description: 'Detects path traversal/directory traversal vulnerabilities',
195
+ category: 'security',
196
+ async analyze(ir, options) {
197
+ const findings = [];
198
+ const startTime = Date.now();
199
+ // Get path traversal sinks from base IR
200
+ const pathSinks = ir.base.taint.sinks.filter(s => s.type === 'path_traversal');
201
+ const sources = ir.base.taint.sources;
202
+ for (const sink of pathSinks) {
203
+ const hasSourceInSameMethod = sources.some(src => src.line < sink.line && findContainingMethod(src.line, ir) === findContainingMethod(sink.line, ir));
204
+ if (hasSourceInSameMethod) {
205
+ findings.push({
206
+ id: `path-${sink.line}`,
207
+ type: 'path-traversal',
208
+ message: `Potential path traversal at line ${sink.line}. User input may control file path.`,
209
+ severity: 'high',
210
+ confidence: 0.85,
211
+ cwe: 'CWE-22',
212
+ owasp: 'A01:2021',
213
+ location: {
214
+ file: ir.filePath,
215
+ line: sink.line,
216
+ },
217
+ sink: { line: sink.line, type: sink.type },
218
+ remediation: 'Validate and canonicalize paths. Use allowlists for allowed directories.',
219
+ });
220
+ }
221
+ }
222
+ // Check for path patterns in strings
223
+ const pathStrings = ir.strings.filter(s => s.pattern === 'path');
224
+ for (const str of pathStrings) {
225
+ if (str.value.includes('..')) {
226
+ findings.push({
227
+ id: `path-pattern-${str.line}`,
228
+ type: 'path-traversal',
229
+ message: `Path pattern with ".." detected at line ${str.line}. Review for traversal issues.`,
230
+ severity: 'medium',
231
+ confidence: 0.5,
232
+ cwe: 'CWE-22',
233
+ location: {
234
+ file: ir.filePath,
235
+ line: str.line,
236
+ },
237
+ remediation: 'Avoid using ".." in path construction. Canonicalize and validate paths.',
238
+ });
239
+ }
240
+ }
241
+ return {
242
+ agentId: pathTraversalAgent.id,
243
+ agentName: pathTraversalAgent.name,
244
+ category: 'security',
245
+ success: true,
246
+ findings,
247
+ processingTimeMs: Date.now() - startTime,
248
+ };
249
+ },
250
+ };
251
+ // ============================================================================
252
+ // Deserialization Agent
253
+ // ============================================================================
254
+ export const deserializationAgent = {
255
+ id: 'security.deserialization',
256
+ name: 'Insecure Deserialization Detector',
257
+ description: 'Detects insecure deserialization vulnerabilities',
258
+ category: 'security',
259
+ async analyze(ir, options) {
260
+ const findings = [];
261
+ const startTime = Date.now();
262
+ const deserSinks = ir.base.taint.sinks.filter(s => s.type === 'deserialization');
263
+ const sources = ir.base.taint.sources;
264
+ for (const sink of deserSinks) {
265
+ const hasSourceInSameMethod = sources.some(src => src.line < sink.line && findContainingMethod(src.line, ir) === findContainingMethod(sink.line, ir));
266
+ if (hasSourceInSameMethod) {
267
+ findings.push({
268
+ id: `deser-${sink.line}`,
269
+ type: 'insecure-deserialization',
270
+ message: `Insecure deserialization at line ${sink.line}. User input may control deserialized object.`,
271
+ severity: 'critical',
272
+ confidence: 0.9,
273
+ cwe: 'CWE-502',
274
+ owasp: 'A08:2021',
275
+ location: {
276
+ file: ir.filePath,
277
+ line: sink.line,
278
+ },
279
+ sink: { line: sink.line, type: sink.type },
280
+ remediation: 'Avoid deserializing untrusted data. Use allowlists for allowed classes or safer formats like JSON.',
281
+ });
282
+ }
283
+ }
284
+ // Check for dangerous deserialization patterns in calls
285
+ for (const call of ir.base.calls || []) {
286
+ if (/readObject|readUnshared|XMLDecoder/.test(call.method_name)) {
287
+ if (!findings.some(f => f.location.line === call.location.line)) {
288
+ findings.push({
289
+ id: `deser-call-${call.location.line}`,
290
+ type: 'insecure-deserialization',
291
+ message: `Potentially dangerous deserialization call: ${call.method_name} at line ${call.location.line}.`,
292
+ severity: 'high',
293
+ confidence: 0.7,
294
+ cwe: 'CWE-502',
295
+ location: {
296
+ file: ir.filePath,
297
+ line: call.location.line,
298
+ },
299
+ remediation: 'Review deserialization usage. Consider using ObjectInputFilter or safer alternatives.',
300
+ });
301
+ }
302
+ }
303
+ }
304
+ return {
305
+ agentId: deserializationAgent.id,
306
+ agentName: deserializationAgent.name,
307
+ category: 'security',
308
+ success: true,
309
+ findings,
310
+ processingTimeMs: Date.now() - startTime,
311
+ };
312
+ },
313
+ };
314
+ // ============================================================================
315
+ // XXE Agent
316
+ // ============================================================================
317
+ export const xxeAgent = {
318
+ id: 'security.xxe',
319
+ name: 'XXE Detector',
320
+ description: 'Detects XML External Entity (XXE) vulnerabilities',
321
+ category: 'security',
322
+ async analyze(ir, options) {
323
+ const findings = [];
324
+ const startTime = Date.now();
325
+ const xxeSinks = ir.base.taint.sinks.filter(s => s.type === 'xxe');
326
+ const sources = ir.base.taint.sources;
327
+ for (const sink of xxeSinks) {
328
+ const hasSourceInSameMethod = sources.some(src => src.line < sink.line && findContainingMethod(src.line, ir) === findContainingMethod(sink.line, ir));
329
+ if (hasSourceInSameMethod) {
330
+ findings.push({
331
+ id: `xxe-${sink.line}`,
332
+ type: 'xxe',
333
+ message: `Potential XXE vulnerability at line ${sink.line}. XML parser may process external entities.`,
334
+ severity: 'high',
335
+ confidence: 0.85,
336
+ cwe: 'CWE-611',
337
+ owasp: 'A05:2021',
338
+ location: {
339
+ file: ir.filePath,
340
+ line: sink.line,
341
+ },
342
+ sink: { line: sink.line, type: sink.type },
343
+ remediation: 'Disable external entity processing: setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)',
344
+ });
345
+ }
346
+ }
347
+ // Check for XML parser creation without security configuration
348
+ for (const call of ir.base.calls || []) {
349
+ if (/DocumentBuilderFactory|SAXParserFactory|XMLInputFactory/.test(call.receiver || '')) {
350
+ if (call.method_name === 'newInstance') {
351
+ findings.push({
352
+ id: `xxe-factory-${call.location.line}`,
353
+ type: 'xxe',
354
+ message: `XML parser created at line ${call.location.line}. Verify XXE protections are enabled.`,
355
+ severity: 'medium',
356
+ confidence: 0.6,
357
+ cwe: 'CWE-611',
358
+ location: {
359
+ file: ir.filePath,
360
+ line: call.location.line,
361
+ },
362
+ remediation: 'Configure parser to disable DTDs and external entities before use.',
363
+ });
364
+ }
365
+ }
366
+ }
367
+ return {
368
+ agentId: xxeAgent.id,
369
+ agentName: xxeAgent.name,
370
+ category: 'security',
371
+ success: true,
372
+ findings,
373
+ processingTimeMs: Date.now() - startTime,
374
+ };
375
+ },
376
+ };
377
+ // ============================================================================
378
+ // LDAP Injection Agent
379
+ // ============================================================================
380
+ export const ldapInjectionAgent = {
381
+ id: 'security.ldap-injection',
382
+ name: 'LDAP Injection Detector',
383
+ description: 'Detects LDAP injection vulnerabilities',
384
+ category: 'security',
385
+ async analyze(ir, options) {
386
+ const findings = [];
387
+ const startTime = Date.now();
388
+ const ldapSinks = ir.base.taint.sinks.filter(s => s.type === 'ldap_injection');
389
+ const sources = ir.base.taint.sources;
390
+ for (const sink of ldapSinks) {
391
+ const hasSourceInSameMethod = sources.some(src => src.line < sink.line && findContainingMethod(src.line, ir) === findContainingMethod(sink.line, ir));
392
+ if (hasSourceInSameMethod) {
393
+ findings.push({
394
+ id: `ldap-${sink.line}`,
395
+ type: 'ldap-injection',
396
+ message: `Potential LDAP injection at line ${sink.line}. User input may flow to LDAP query.`,
397
+ severity: 'high',
398
+ confidence: 0.85,
399
+ cwe: 'CWE-90',
400
+ owasp: 'A03:2021',
401
+ location: {
402
+ file: ir.filePath,
403
+ line: sink.line,
404
+ },
405
+ sink: { line: sink.line, type: sink.type },
406
+ remediation: 'Escape special LDAP characters or use parameterized LDAP queries.',
407
+ });
408
+ }
409
+ }
410
+ return {
411
+ agentId: ldapInjectionAgent.id,
412
+ agentName: ldapInjectionAgent.name,
413
+ category: 'security',
414
+ success: true,
415
+ findings,
416
+ processingTimeMs: Date.now() - startTime,
417
+ };
418
+ },
419
+ };
420
+ // ============================================================================
421
+ // XPath Injection Agent
422
+ // ============================================================================
423
+ export const xpathInjectionAgent = {
424
+ id: 'security.xpath-injection',
425
+ name: 'XPath Injection Detector',
426
+ description: 'Detects XPath injection vulnerabilities',
427
+ category: 'security',
428
+ async analyze(ir, options) {
429
+ const findings = [];
430
+ const startTime = Date.now();
431
+ const xpathSinks = ir.base.taint.sinks.filter(s => s.type === 'xpath_injection');
432
+ const sources = ir.base.taint.sources;
433
+ for (const sink of xpathSinks) {
434
+ const hasSourceInSameMethod = sources.some(src => src.line < sink.line && findContainingMethod(src.line, ir) === findContainingMethod(sink.line, ir));
435
+ if (hasSourceInSameMethod) {
436
+ findings.push({
437
+ id: `xpath-${sink.line}`,
438
+ type: 'xpath-injection',
439
+ message: `Potential XPath injection at line ${sink.line}. User input may flow to XPath query.`,
440
+ severity: 'high',
441
+ confidence: 0.85,
442
+ cwe: 'CWE-643',
443
+ owasp: 'A03:2021',
444
+ location: {
445
+ file: ir.filePath,
446
+ line: sink.line,
447
+ },
448
+ sink: { line: sink.line, type: sink.type },
449
+ remediation: 'Use parameterized XPath queries or escape special characters.',
450
+ });
451
+ }
452
+ }
453
+ return {
454
+ agentId: xpathInjectionAgent.id,
455
+ agentName: xpathInjectionAgent.name,
456
+ category: 'security',
457
+ success: true,
458
+ findings,
459
+ processingTimeMs: Date.now() - startTime,
460
+ };
461
+ },
462
+ };
463
+ // ============================================================================
464
+ // SSRF Agent
465
+ // ============================================================================
466
+ export const ssrfAgent = {
467
+ id: 'security.ssrf',
468
+ name: 'SSRF Detector',
469
+ description: 'Detects Server-Side Request Forgery vulnerabilities',
470
+ category: 'security',
471
+ async analyze(ir, options) {
472
+ const findings = [];
473
+ const startTime = Date.now();
474
+ const ssrfSinks = ir.base.taint.sinks.filter(s => s.type === 'ssrf');
475
+ const sources = ir.base.taint.sources;
476
+ for (const sink of ssrfSinks) {
477
+ const hasSourceInSameMethod = sources.some(src => src.line < sink.line && findContainingMethod(src.line, ir) === findContainingMethod(sink.line, ir));
478
+ if (hasSourceInSameMethod) {
479
+ findings.push({
480
+ id: `ssrf-${sink.line}`,
481
+ type: 'ssrf',
482
+ message: `Potential SSRF at line ${sink.line}. User input may control outbound request URL.`,
483
+ severity: 'high',
484
+ confidence: 0.85,
485
+ cwe: 'CWE-918',
486
+ owasp: 'A10:2021',
487
+ location: {
488
+ file: ir.filePath,
489
+ line: sink.line,
490
+ },
491
+ sink: { line: sink.line, type: sink.type },
492
+ remediation: 'Validate and allowlist destination URLs. Block internal/private IP ranges.',
493
+ });
494
+ }
495
+ }
496
+ // Check for URL patterns in strings with sources
497
+ const urlStrings = ir.strings.filter(s => s.pattern === 'url');
498
+ for (const str of urlStrings) {
499
+ const method = str.inMethod;
500
+ const hasSourceInMethod = sources.some(src => findContainingMethod(src.line, ir) === method);
501
+ if (hasSourceInMethod && str.context === 'argument') {
502
+ findings.push({
503
+ id: `ssrf-url-${str.line}`,
504
+ type: 'ssrf',
505
+ message: `URL construction at line ${str.line} in method with user input. Verify SSRF protections.`,
506
+ severity: 'medium',
507
+ confidence: 0.6,
508
+ cwe: 'CWE-918',
509
+ location: {
510
+ file: ir.filePath,
511
+ line: str.line,
512
+ },
513
+ remediation: 'Validate URLs against an allowlist of permitted hosts.',
514
+ });
515
+ }
516
+ }
517
+ return {
518
+ agentId: ssrfAgent.id,
519
+ agentName: ssrfAgent.name,
520
+ category: 'security',
521
+ success: true,
522
+ findings,
523
+ processingTimeMs: Date.now() - startTime,
524
+ };
525
+ },
526
+ };
527
+ // ============================================================================
528
+ // Code Injection Agent
529
+ // ============================================================================
530
+ export const codeInjectionAgent = {
531
+ id: 'security.code-injection',
532
+ name: 'Code Injection Detector',
533
+ description: 'Detects code injection and expression language injection vulnerabilities',
534
+ category: 'security',
535
+ async analyze(ir, options) {
536
+ const findings = [];
537
+ const startTime = Date.now();
538
+ const codeSinks = ir.base.taint.sinks.filter(s => s.type === 'code_injection');
539
+ const sources = ir.base.taint.sources;
540
+ for (const sink of codeSinks) {
541
+ const hasSourceInSameMethod = sources.some(src => src.line < sink.line && findContainingMethod(src.line, ir) === findContainingMethod(sink.line, ir));
542
+ if (hasSourceInSameMethod) {
543
+ findings.push({
544
+ id: `code-${sink.line}`,
545
+ type: 'code-injection',
546
+ message: `Potential code injection at line ${sink.line}. User input may be executed as code.`,
547
+ severity: 'critical',
548
+ confidence: 0.9,
549
+ cwe: 'CWE-94',
550
+ owasp: 'A03:2021',
551
+ location: {
552
+ file: ir.filePath,
553
+ line: sink.line,
554
+ },
555
+ sink: { line: sink.line, type: sink.type },
556
+ remediation: 'Avoid dynamic code execution with user input. Use sandboxing if necessary.',
557
+ });
558
+ }
559
+ }
560
+ // Check for dangerous method calls
561
+ for (const call of ir.base.calls || []) {
562
+ if (/eval|ScriptEngine\.eval|GroovyShell\.evaluate|SpEL/.test(call.method_name)) {
563
+ findings.push({
564
+ id: `code-eval-${call.location.line}`,
565
+ type: 'code-injection',
566
+ message: `Dynamic code execution at line ${call.location.line}: ${call.method_name}`,
567
+ severity: 'high',
568
+ confidence: 0.8,
569
+ cwe: 'CWE-94',
570
+ location: {
571
+ file: ir.filePath,
572
+ line: call.location.line,
573
+ },
574
+ remediation: 'Review dynamic code execution. Ensure user input cannot reach this call.',
575
+ });
576
+ }
577
+ }
578
+ return {
579
+ agentId: codeInjectionAgent.id,
580
+ agentName: codeInjectionAgent.name,
581
+ category: 'security',
582
+ success: true,
583
+ findings,
584
+ processingTimeMs: Date.now() - startTime,
585
+ };
586
+ },
587
+ };
588
+ // ============================================================================
589
+ // Hardcoded Secrets Agent
590
+ // ============================================================================
591
+ export const hardcodedSecretsAgent = {
592
+ id: 'security.hardcoded-secrets',
593
+ name: 'Hardcoded Secrets Detector',
594
+ description: 'Detects hardcoded passwords, API keys, and other secrets',
595
+ category: 'security',
596
+ async analyze(ir, options) {
597
+ const findings = [];
598
+ const startTime = Date.now();
599
+ // Patterns for detecting secrets
600
+ const secretPatterns = [
601
+ { pattern: /password\s*=\s*["'][^"']+["']/i, type: 'hardcoded-password', severity: 'high' },
602
+ { pattern: /api[_-]?key\s*=\s*["'][^"']+["']/i, type: 'hardcoded-api-key', severity: 'high' },
603
+ { pattern: /secret\s*=\s*["'][^"']+["']/i, type: 'hardcoded-secret', severity: 'high' },
604
+ { pattern: /token\s*=\s*["'][A-Za-z0-9_\-]{20,}["']/i, type: 'hardcoded-token', severity: 'high' },
605
+ { pattern: /private[_-]?key/i, type: 'hardcoded-private-key', severity: 'critical' },
606
+ { pattern: /-----BEGIN (RSA |EC |DSA )?PRIVATE KEY-----/, type: 'embedded-private-key', severity: 'critical' },
607
+ { pattern: /aws[_-]?(access[_-]?key|secret)/i, type: 'aws-credentials', severity: 'critical' },
608
+ ];
609
+ // Check strings for secret patterns
610
+ for (const str of ir.strings) {
611
+ for (const { pattern, type, severity } of secretPatterns) {
612
+ if (pattern.test(str.raw) || pattern.test(str.value)) {
613
+ findings.push({
614
+ id: `secret-${type}-${str.line}`,
615
+ type,
616
+ message: `Potential ${type.replace(/-/g, ' ')} detected at line ${str.line}.`,
617
+ severity,
618
+ confidence: 0.8,
619
+ cwe: 'CWE-798',
620
+ owasp: 'A07:2021',
621
+ location: {
622
+ file: ir.filePath,
623
+ line: str.line,
624
+ column: str.column,
625
+ },
626
+ remediation: 'Move secrets to environment variables or a secrets manager.',
627
+ });
628
+ break; // Only one finding per string
629
+ }
630
+ }
631
+ }
632
+ // Note: Field-level checks skipped - FieldInfo doesn't include line numbers.
633
+ // The string literal checks above catch most hardcoded secrets.
634
+ return {
635
+ agentId: hardcodedSecretsAgent.id,
636
+ agentName: hardcodedSecretsAgent.name,
637
+ category: 'security',
638
+ success: true,
639
+ findings,
640
+ processingTimeMs: Date.now() - startTime,
641
+ };
642
+ },
643
+ };
644
+ // ============================================================================
645
+ // Insecure Crypto Agent
646
+ // ============================================================================
647
+ export const insecureCryptoAgent = {
648
+ id: 'security.insecure-crypto',
649
+ name: 'Insecure Cryptography Detector',
650
+ description: 'Detects use of weak or broken cryptographic algorithms',
651
+ category: 'security',
652
+ async analyze(ir, options) {
653
+ const findings = [];
654
+ const startTime = Date.now();
655
+ // Weak algorithms to detect
656
+ const weakAlgorithms = [
657
+ { pattern: /MD5|md5/, name: 'MD5', cwe: 'CWE-328' },
658
+ { pattern: /SHA-?1(?![0-9])|sha1/i, name: 'SHA-1', cwe: 'CWE-328' },
659
+ { pattern: /DES(?!ede)|des(?!ede)/i, name: 'DES', cwe: 'CWE-327' },
660
+ { pattern: /RC4|rc4|ARCFOUR/i, name: 'RC4', cwe: 'CWE-327' },
661
+ { pattern: /Blowfish/i, name: 'Blowfish', cwe: 'CWE-327' },
662
+ { pattern: /ECB/, name: 'ECB mode', cwe: 'CWE-327' },
663
+ ];
664
+ // Check strings for weak algorithm references
665
+ for (const str of ir.strings) {
666
+ for (const { pattern, name, cwe } of weakAlgorithms) {
667
+ if (pattern.test(str.value)) {
668
+ findings.push({
669
+ id: `crypto-weak-${str.line}`,
670
+ type: 'weak-cryptography',
671
+ message: `Weak cryptographic algorithm "${name}" used at line ${str.line}.`,
672
+ severity: 'medium',
673
+ confidence: 0.85,
674
+ cwe,
675
+ owasp: 'A02:2021',
676
+ location: {
677
+ file: ir.filePath,
678
+ line: str.line,
679
+ },
680
+ remediation: `Replace ${name} with a stronger algorithm (e.g., SHA-256, AES-GCM).`,
681
+ });
682
+ break;
683
+ }
684
+ }
685
+ }
686
+ // Check for insecure random
687
+ for (const call of ir.base.calls || []) {
688
+ if (call.receiver === 'Random' || call.method_name === 'Random') {
689
+ findings.push({
690
+ id: `crypto-random-${call.location.line}`,
691
+ type: 'insecure-random',
692
+ message: `java.util.Random used at line ${call.location.line}. Not cryptographically secure.`,
693
+ severity: 'medium',
694
+ confidence: 0.7,
695
+ cwe: 'CWE-330',
696
+ location: {
697
+ file: ir.filePath,
698
+ line: call.location.line,
699
+ },
700
+ remediation: 'Use SecureRandom for security-sensitive randomness.',
701
+ });
702
+ }
703
+ }
704
+ return {
705
+ agentId: insecureCryptoAgent.id,
706
+ agentName: insecureCryptoAgent.name,
707
+ category: 'security',
708
+ success: true,
709
+ findings,
710
+ processingTimeMs: Date.now() - startTime,
711
+ };
712
+ },
713
+ };
714
+ // ============================================================================
715
+ // Endpoint Security Agent
716
+ // ============================================================================
717
+ export const endpointSecurityAgent = {
718
+ id: 'security.endpoint',
719
+ name: 'Endpoint Security Analyzer',
720
+ description: 'Analyzes API endpoints for security issues',
721
+ category: 'security',
722
+ async analyze(ir, options) {
723
+ const findings = [];
724
+ const startTime = Date.now();
725
+ for (const endpoint of ir.endpoints) {
726
+ // Check for endpoints without authentication annotations
727
+ const handlerType = ir.base.types.find(t => t.name === endpoint.handlerClass);
728
+ if (handlerType) {
729
+ const method = handlerType.methods?.find(m => m.name === endpoint.handlerMethod);
730
+ const annotations = [...(handlerType.annotations || []), ...(method?.annotations || [])];
731
+ const hasAuthAnnotation = annotations.some(a => /PreAuthorize|Secured|RolesAllowed|RequiresAuthentication/.test(a));
732
+ if (!hasAuthAnnotation) {
733
+ findings.push({
734
+ id: `endpoint-noauth-${endpoint.line}`,
735
+ type: 'missing-authentication',
736
+ message: `Endpoint ${endpoint.method} ${endpoint.path} may lack authentication.`,
737
+ severity: 'medium',
738
+ confidence: 0.7,
739
+ cwe: 'CWE-306',
740
+ owasp: 'A07:2021',
741
+ location: {
742
+ file: ir.filePath,
743
+ line: endpoint.line,
744
+ },
745
+ metadata: {
746
+ endpoint: `${endpoint.method} ${endpoint.path}`,
747
+ handler: `${endpoint.handlerClass}.${endpoint.handlerMethod}`,
748
+ },
749
+ remediation: 'Add authentication annotation like @PreAuthorize or @Secured.',
750
+ });
751
+ }
752
+ }
753
+ // Check for endpoints accepting arbitrary input
754
+ const hasUnvalidatedInput = endpoint.params.some(p => !p.type.includes('Valid') && (p.type === 'String' || p.type === 'Object'));
755
+ if (hasUnvalidatedInput) {
756
+ findings.push({
757
+ id: `endpoint-validation-${endpoint.line}`,
758
+ type: 'missing-validation',
759
+ message: `Endpoint ${endpoint.method} ${endpoint.path} has unvalidated String/Object parameters.`,
760
+ severity: 'low',
761
+ confidence: 0.6,
762
+ cwe: 'CWE-20',
763
+ location: {
764
+ file: ir.filePath,
765
+ line: endpoint.line,
766
+ },
767
+ metadata: {
768
+ endpoint: `${endpoint.method} ${endpoint.path}`,
769
+ params: endpoint.params.map(p => p.name),
770
+ },
771
+ remediation: 'Add @Valid annotation and define validation constraints on DTOs.',
772
+ });
773
+ }
774
+ }
775
+ return {
776
+ agentId: endpointSecurityAgent.id,
777
+ agentName: endpointSecurityAgent.name,
778
+ category: 'security',
779
+ success: true,
780
+ findings,
781
+ processingTimeMs: Date.now() - startTime,
782
+ };
783
+ },
784
+ };
785
+ // ============================================================================
786
+ // Helper Functions
787
+ // ============================================================================
788
+ /**
789
+ * Find the method containing a given line.
790
+ */
791
+ function findContainingMethod(lineNum, ir) {
792
+ for (const type of ir.base.types) {
793
+ for (const method of type.methods || []) {
794
+ if (lineNum >= method.start_line && lineNum <= method.end_line) {
795
+ return `${type.name}.${method.name}`;
796
+ }
797
+ }
798
+ }
799
+ return undefined;
800
+ }
801
+ // ============================================================================
802
+ // Registration
803
+ // ============================================================================
804
+ /**
805
+ * All security agents.
806
+ */
807
+ export const securityAgents = [
808
+ sqlInjectionAgent,
809
+ xssAgent,
810
+ commandInjectionAgent,
811
+ pathTraversalAgent,
812
+ deserializationAgent,
813
+ xxeAgent,
814
+ ldapInjectionAgent,
815
+ xpathInjectionAgent,
816
+ ssrfAgent,
817
+ codeInjectionAgent,
818
+ hardcodedSecretsAgent,
819
+ insecureCryptoAgent,
820
+ endpointSecurityAgent,
821
+ ];
822
+ /**
823
+ * Register all security agents with the runner.
824
+ */
825
+ export function registerSecurityAgents() {
826
+ for (const agent of securityAgents) {
827
+ registerAgent(agent);
828
+ }
829
+ }
830
+ //# sourceMappingURL=security.js.map