kirograph 0.19.0 → 0.20.1

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 (690) hide show
  1. package/README.md +10 -8
  2. package/dist/architecture/layers/dart.d.ts +10 -0
  3. package/dist/architecture/layers/dart.d.ts.map +1 -0
  4. package/dist/architecture/layers/elixir.d.ts +6 -0
  5. package/dist/architecture/layers/elixir.d.ts.map +1 -0
  6. package/dist/architecture/layers/index.d.ts.map +1 -1
  7. package/dist/architecture/layers/ocaml.d.ts +6 -0
  8. package/dist/architecture/layers/ocaml.d.ts.map +1 -0
  9. package/dist/architecture/layers/scala.d.ts +6 -0
  10. package/dist/architecture/layers/scala.d.ts.map +1 -0
  11. package/dist/architecture/layers/solidity.d.ts +6 -0
  12. package/dist/architecture/layers/solidity.d.ts.map +1 -0
  13. package/dist/architecture/layers/vue.d.ts +6 -0
  14. package/dist/architecture/layers/vue.d.ts.map +1 -0
  15. package/dist/architecture/manifest/elm.d.ts +3 -0
  16. package/dist/architecture/manifest/elm.d.ts.map +1 -0
  17. package/dist/architecture/manifest/index.d.ts.map +1 -1
  18. package/dist/architecture/manifest/ocaml.d.ts +3 -0
  19. package/dist/architecture/manifest/ocaml.d.ts.map +1 -0
  20. package/dist/architecture/manifest/scala.d.ts +3 -0
  21. package/dist/architecture/manifest/scala.d.ts.map +1 -0
  22. package/dist/bin/banner.d.ts.map +1 -1
  23. package/dist/bin/commands/affected.d.ts.map +1 -1
  24. package/dist/bin/commands/attack-surface.d.ts +3 -0
  25. package/dist/bin/commands/attack-surface.d.ts.map +1 -0
  26. package/dist/bin/commands/attack-surface.js +7 -0
  27. package/dist/bin/commands/attack-surface.js.map +2 -2
  28. package/dist/bin/commands/benchmark.d.ts +9 -0
  29. package/dist/bin/commands/benchmark.d.ts.map +1 -0
  30. package/dist/bin/commands/budget.d.ts +6 -0
  31. package/dist/bin/commands/budget.d.ts.map +1 -0
  32. package/dist/bin/commands/caveman.d.ts +7 -0
  33. package/dist/bin/commands/caveman.d.ts.map +1 -0
  34. package/dist/bin/commands/communities.d.ts +3 -0
  35. package/dist/bin/commands/communities.d.ts.map +1 -0
  36. package/dist/bin/commands/compression.d.ts +7 -0
  37. package/dist/bin/commands/compression.d.ts.map +1 -0
  38. package/dist/bin/commands/context.d.ts.map +1 -1
  39. package/dist/bin/commands/data.d.ts +3 -0
  40. package/dist/bin/commands/data.d.ts.map +1 -0
  41. package/dist/bin/commands/dead-code.d.ts +3 -0
  42. package/dist/bin/commands/dead-code.d.ts.map +1 -0
  43. package/dist/bin/commands/dep-confusion.d.ts +3 -0
  44. package/dist/bin/commands/dep-confusion.d.ts.map +1 -0
  45. package/dist/bin/commands/docs.d.ts +3 -0
  46. package/dist/bin/commands/docs.d.ts.map +1 -0
  47. package/dist/bin/commands/exec.d.ts +11 -0
  48. package/dist/bin/commands/exec.d.ts.map +1 -0
  49. package/dist/bin/commands/export.d.ts +3 -0
  50. package/dist/bin/commands/export.d.ts.map +1 -0
  51. package/dist/bin/commands/flows.d.ts +3 -0
  52. package/dist/bin/commands/flows.d.ts.map +1 -0
  53. package/dist/bin/commands/gain.d.ts +6 -0
  54. package/dist/bin/commands/gain.d.ts.map +1 -0
  55. package/dist/bin/commands/help.d.ts +7 -0
  56. package/dist/bin/commands/help.d.ts.map +1 -1
  57. package/dist/bin/commands/help.js +20 -3
  58. package/dist/bin/commands/help.js.map +2 -2
  59. package/dist/bin/commands/hotspots.d.ts +3 -0
  60. package/dist/bin/commands/hotspots.d.ts.map +1 -0
  61. package/dist/bin/commands/hotspots.js +94 -1
  62. package/dist/bin/commands/hotspots.js.map +3 -3
  63. package/dist/bin/commands/install.d.ts.map +1 -1
  64. package/dist/bin/commands/install.js +3 -3
  65. package/dist/bin/commands/install.js.map +2 -2
  66. package/dist/bin/commands/licenses.d.ts +3 -0
  67. package/dist/bin/commands/licenses.d.ts.map +1 -0
  68. package/dist/bin/commands/memory.d.ts +16 -0
  69. package/dist/bin/commands/memory.d.ts.map +1 -0
  70. package/dist/bin/commands/memory.js +151 -4
  71. package/dist/bin/commands/memory.js.map +2 -2
  72. package/dist/bin/commands/path.d.ts +3 -0
  73. package/dist/bin/commands/path.d.ts.map +1 -0
  74. package/dist/bin/commands/pattern.d.ts +3 -0
  75. package/dist/bin/commands/pattern.d.ts.map +1 -0
  76. package/dist/bin/commands/pattern.js +592 -0
  77. package/dist/bin/commands/pattern.js.map +7 -0
  78. package/dist/bin/commands/query.d.ts.map +1 -1
  79. package/dist/bin/commands/reachability.d.ts +3 -0
  80. package/dist/bin/commands/reachability.d.ts.map +1 -0
  81. package/dist/bin/commands/read.d.ts +6 -0
  82. package/dist/bin/commands/read.d.ts.map +1 -0
  83. package/dist/bin/commands/refactor.d.ts +3 -0
  84. package/dist/bin/commands/refactor.d.ts.map +1 -0
  85. package/dist/bin/commands/remediation.d.ts +3 -0
  86. package/dist/bin/commands/remediation.d.ts.map +1 -0
  87. package/dist/bin/commands/sbom.d.ts +3 -0
  88. package/dist/bin/commands/sbom.d.ts.map +1 -0
  89. package/dist/bin/commands/security-ci-report.d.ts +9 -0
  90. package/dist/bin/commands/security-ci-report.d.ts.map +1 -0
  91. package/dist/bin/commands/security-export.d.ts +2 -0
  92. package/dist/bin/commands/security-export.d.ts.map +1 -0
  93. package/dist/bin/commands/security-flows.d.ts +3 -0
  94. package/dist/bin/commands/security-flows.d.ts.map +1 -0
  95. package/dist/bin/commands/security-secrets.d.ts +3 -0
  96. package/dist/bin/commands/security-secrets.d.ts.map +1 -0
  97. package/dist/bin/commands/security.d.ts +3 -0
  98. package/dist/bin/commands/security.d.ts.map +1 -0
  99. package/dist/bin/commands/security.js +15 -0
  100. package/dist/bin/commands/security.js.map +2 -2
  101. package/dist/bin/commands/snapshot.d.ts +3 -0
  102. package/dist/bin/commands/snapshot.d.ts.map +1 -0
  103. package/dist/bin/commands/staleness.d.ts +3 -0
  104. package/dist/bin/commands/staleness.d.ts.map +1 -0
  105. package/dist/bin/commands/status.d.ts.map +1 -1
  106. package/dist/bin/commands/status.js +27 -0
  107. package/dist/bin/commands/status.js.map +2 -2
  108. package/dist/bin/commands/supply-chain.d.ts +3 -0
  109. package/dist/bin/commands/supply-chain.d.ts.map +1 -0
  110. package/dist/bin/commands/surprising.d.ts +3 -0
  111. package/dist/bin/commands/surprising.d.ts.map +1 -0
  112. package/dist/bin/commands/sync.d.ts.map +1 -1
  113. package/dist/bin/commands/uninit.d.ts.map +1 -1
  114. package/dist/bin/commands/utils.d.ts +5 -0
  115. package/dist/bin/commands/utils.d.ts.map +1 -1
  116. package/dist/bin/commands/vex.d.ts +3 -0
  117. package/dist/bin/commands/vex.d.ts.map +1 -0
  118. package/dist/bin/commands/vuln-suppress.d.ts +3 -0
  119. package/dist/bin/commands/vuln-suppress.d.ts.map +1 -0
  120. package/dist/bin/commands/vulns.d.ts +3 -0
  121. package/dist/bin/commands/vulns.d.ts.map +1 -0
  122. package/dist/bin/installer/archive.d.ts +47 -0
  123. package/dist/bin/installer/archive.d.ts.map +1 -0
  124. package/dist/bin/installer/auto-detect.d.ts +16 -0
  125. package/dist/bin/installer/auto-detect.d.ts.map +1 -0
  126. package/dist/bin/installer/caveman.d.ts +12 -0
  127. package/dist/bin/installer/caveman.d.ts.map +1 -0
  128. package/dist/bin/installer/cli-agent.d.ts +7 -2
  129. package/dist/bin/installer/cli-agent.d.ts.map +1 -1
  130. package/dist/bin/installer/cli-agent.js +6 -2
  131. package/dist/bin/installer/cli-agent.js.map +2 -2
  132. package/dist/bin/installer/common.d.ts +36 -0
  133. package/dist/bin/installer/common.d.ts.map +1 -0
  134. package/dist/bin/installer/common.js +2 -1
  135. package/dist/bin/installer/common.js.map +2 -2
  136. package/dist/bin/installer/config-prompt.d.ts +1 -1
  137. package/dist/bin/installer/config-prompt.d.ts.map +1 -1
  138. package/dist/bin/installer/config-prompt.js +74 -2
  139. package/dist/bin/installer/config-prompt.js.map +2 -2
  140. package/dist/bin/installer/dashboard.d.ts.map +1 -1
  141. package/dist/bin/installer/detect.d.ts +30 -0
  142. package/dist/bin/installer/detect.d.ts.map +1 -0
  143. package/dist/bin/installer/hooks.d.ts +4 -1
  144. package/dist/bin/installer/hooks.d.ts.map +1 -1
  145. package/dist/bin/installer/hooks.js +34 -0
  146. package/dist/bin/installer/hooks.js.map +2 -2
  147. package/dist/bin/installer/index.d.ts +5 -4
  148. package/dist/bin/installer/index.d.ts.map +1 -1
  149. package/dist/bin/installer/index.js +67 -8
  150. package/dist/bin/installer/index.js.map +2 -2
  151. package/dist/bin/installer/instructions.d.ts +14 -0
  152. package/dist/bin/installer/instructions.d.ts.map +1 -0
  153. package/dist/bin/installer/instructions.js +15 -1
  154. package/dist/bin/installer/instructions.js.map +2 -2
  155. package/dist/bin/installer/mcp.d.ts.map +1 -1
  156. package/dist/bin/installer/prompts.d.ts +17 -0
  157. package/dist/bin/installer/prompts.d.ts.map +1 -1
  158. package/dist/bin/installer/qdrant-dashboard.d.ts.map +1 -1
  159. package/dist/bin/installer/steering.d.ts +14 -2
  160. package/dist/bin/installer/steering.d.ts.map +1 -1
  161. package/dist/bin/installer/steering.js +81 -0
  162. package/dist/bin/installer/steering.js.map +2 -2
  163. package/dist/bin/installer/targets/aider.d.ts +6 -0
  164. package/dist/bin/installer/targets/aider.d.ts.map +1 -0
  165. package/dist/bin/installer/targets/aider.js +3 -3
  166. package/dist/bin/installer/targets/aider.js.map +2 -2
  167. package/dist/bin/installer/targets/amp.d.ts +6 -0
  168. package/dist/bin/installer/targets/amp.d.ts.map +1 -0
  169. package/dist/bin/installer/targets/amp.js +3 -3
  170. package/dist/bin/installer/targets/amp.js.map +2 -2
  171. package/dist/bin/installer/targets/antigravity.d.ts +13 -0
  172. package/dist/bin/installer/targets/antigravity.d.ts.map +1 -0
  173. package/dist/bin/installer/targets/antigravity.js +2 -2
  174. package/dist/bin/installer/targets/antigravity.js.map +2 -2
  175. package/dist/bin/installer/targets/augment.d.ts +6 -0
  176. package/dist/bin/installer/targets/augment.d.ts.map +1 -0
  177. package/dist/bin/installer/targets/augment.js +3 -3
  178. package/dist/bin/installer/targets/augment.js.map +2 -2
  179. package/dist/bin/installer/targets/claude.d.ts +6 -0
  180. package/dist/bin/installer/targets/claude.d.ts.map +1 -0
  181. package/dist/bin/installer/targets/claude.js +2 -2
  182. package/dist/bin/installer/targets/claude.js.map +2 -2
  183. package/dist/bin/installer/targets/cline.d.ts +13 -0
  184. package/dist/bin/installer/targets/cline.d.ts.map +1 -0
  185. package/dist/bin/installer/targets/cline.js +2 -2
  186. package/dist/bin/installer/targets/cline.js.map +2 -2
  187. package/dist/bin/installer/targets/codex.d.ts +6 -0
  188. package/dist/bin/installer/targets/codex.d.ts.map +1 -0
  189. package/dist/bin/installer/targets/codex.js +2 -2
  190. package/dist/bin/installer/targets/codex.js.map +2 -2
  191. package/dist/bin/installer/targets/continue.d.ts +12 -0
  192. package/dist/bin/installer/targets/continue.d.ts.map +1 -0
  193. package/dist/bin/installer/targets/continue.js +2 -2
  194. package/dist/bin/installer/targets/continue.js.map +2 -2
  195. package/dist/bin/installer/targets/copilot-cli.d.ts +12 -0
  196. package/dist/bin/installer/targets/copilot-cli.d.ts.map +1 -0
  197. package/dist/bin/installer/targets/copilot-cli.js +2 -2
  198. package/dist/bin/installer/targets/copilot-cli.js.map +2 -2
  199. package/dist/bin/installer/targets/copilot.d.ts +6 -0
  200. package/dist/bin/installer/targets/copilot.d.ts.map +1 -0
  201. package/dist/bin/installer/targets/copilot.js +2 -2
  202. package/dist/bin/installer/targets/copilot.js.map +2 -2
  203. package/dist/bin/installer/targets/cursor.d.ts +6 -0
  204. package/dist/bin/installer/targets/cursor.d.ts.map +1 -0
  205. package/dist/bin/installer/targets/cursor.js +2 -2
  206. package/dist/bin/installer/targets/cursor.js.map +2 -2
  207. package/dist/bin/installer/targets/devin.d.ts +13 -0
  208. package/dist/bin/installer/targets/devin.d.ts.map +1 -0
  209. package/dist/bin/installer/targets/devin.js +2 -2
  210. package/dist/bin/installer/targets/devin.js.map +2 -2
  211. package/dist/bin/installer/targets/gemini-cli.d.ts +16 -0
  212. package/dist/bin/installer/targets/gemini-cli.d.ts.map +1 -0
  213. package/dist/bin/installer/targets/gemini-cli.js +2 -2
  214. package/dist/bin/installer/targets/gemini-cli.js.map +2 -2
  215. package/dist/bin/installer/targets/generic.d.ts +59 -0
  216. package/dist/bin/installer/targets/generic.d.ts.map +1 -0
  217. package/dist/bin/installer/targets/generic.js +2 -2
  218. package/dist/bin/installer/targets/generic.js.map +2 -2
  219. package/dist/bin/installer/targets/goose.d.ts +6 -0
  220. package/dist/bin/installer/targets/goose.d.ts.map +1 -0
  221. package/dist/bin/installer/targets/goose.js +3 -3
  222. package/dist/bin/installer/targets/goose.js.map +2 -2
  223. package/dist/bin/installer/targets/index.d.ts +11 -0
  224. package/dist/bin/installer/targets/index.d.ts.map +1 -0
  225. package/dist/bin/installer/targets/index.js.map +1 -1
  226. package/dist/bin/installer/targets/junie.d.ts +13 -0
  227. package/dist/bin/installer/targets/junie.d.ts.map +1 -0
  228. package/dist/bin/installer/targets/junie.js +2 -2
  229. package/dist/bin/installer/targets/junie.js.map +2 -2
  230. package/dist/bin/installer/targets/kilo.d.ts +12 -0
  231. package/dist/bin/installer/targets/kilo.d.ts.map +1 -0
  232. package/dist/bin/installer/targets/kilo.js +2 -2
  233. package/dist/bin/installer/targets/kilo.js.map +2 -2
  234. package/dist/bin/installer/targets/kiro.d.ts +5 -0
  235. package/dist/bin/installer/targets/kiro.d.ts.map +1 -0
  236. package/dist/bin/installer/targets/kiro.js +4 -4
  237. package/dist/bin/installer/targets/kiro.js.map +2 -2
  238. package/dist/bin/installer/targets/opencode.d.ts +13 -0
  239. package/dist/bin/installer/targets/opencode.d.ts.map +1 -0
  240. package/dist/bin/installer/targets/opencode.js +2 -2
  241. package/dist/bin/installer/targets/opencode.js.map +2 -2
  242. package/dist/bin/installer/targets/openhands.d.ts +6 -0
  243. package/dist/bin/installer/targets/openhands.d.ts.map +1 -0
  244. package/dist/bin/installer/targets/openhands.js +3 -3
  245. package/dist/bin/installer/targets/openhands.js.map +2 -2
  246. package/dist/bin/installer/targets/qoder.d.ts +12 -0
  247. package/dist/bin/installer/targets/qoder.d.ts.map +1 -0
  248. package/dist/bin/installer/targets/qoder.js +2 -2
  249. package/dist/bin/installer/targets/qoder.js.map +2 -2
  250. package/dist/bin/installer/targets/qwen.d.ts +12 -0
  251. package/dist/bin/installer/targets/qwen.d.ts.map +1 -0
  252. package/dist/bin/installer/targets/qwen.js +2 -2
  253. package/dist/bin/installer/targets/qwen.js.map +2 -2
  254. package/dist/bin/installer/targets/replit.d.ts +6 -0
  255. package/dist/bin/installer/targets/replit.d.ts.map +1 -0
  256. package/dist/bin/installer/targets/replit.js +3 -3
  257. package/dist/bin/installer/targets/replit.js.map +2 -2
  258. package/dist/bin/installer/targets/roo.d.ts +13 -0
  259. package/dist/bin/installer/targets/roo.d.ts.map +1 -0
  260. package/dist/bin/installer/targets/roo.js +2 -2
  261. package/dist/bin/installer/targets/roo.js.map +2 -2
  262. package/dist/bin/installer/targets/tabnine.d.ts +6 -0
  263. package/dist/bin/installer/targets/tabnine.d.ts.map +1 -0
  264. package/dist/bin/installer/targets/tabnine.js +3 -3
  265. package/dist/bin/installer/targets/tabnine.js.map +2 -2
  266. package/dist/bin/installer/targets/trae.d.ts +6 -0
  267. package/dist/bin/installer/targets/trae.d.ts.map +1 -0
  268. package/dist/bin/installer/targets/trae.js +3 -3
  269. package/dist/bin/installer/targets/trae.js.map +2 -2
  270. package/dist/bin/installer/targets/warp.d.ts +12 -0
  271. package/dist/bin/installer/targets/warp.d.ts.map +1 -0
  272. package/dist/bin/installer/targets/warp.js +2 -2
  273. package/dist/bin/installer/targets/warp.js.map +2 -2
  274. package/dist/bin/installer/targets/windsurf.d.ts +13 -0
  275. package/dist/bin/installer/targets/windsurf.d.ts.map +1 -0
  276. package/dist/bin/installer/targets/windsurf.js +2 -2
  277. package/dist/bin/installer/targets/windsurf.js.map +2 -2
  278. package/dist/bin/kirograph.js +3 -1
  279. package/dist/bin/kirograph.js.map +3 -3
  280. package/dist/bin/progress.d.ts +16 -1
  281. package/dist/bin/progress.d.ts.map +1 -1
  282. package/dist/compression/filters/aws.d.ts +9 -0
  283. package/dist/compression/filters/aws.d.ts.map +1 -0
  284. package/dist/compression/filters/docker.d.ts +6 -0
  285. package/dist/compression/filters/docker.d.ts.map +1 -0
  286. package/dist/compression/filters/files.d.ts +6 -0
  287. package/dist/compression/filters/files.d.ts.map +1 -0
  288. package/dist/compression/filters/generic.d.ts +7 -0
  289. package/dist/compression/filters/generic.d.ts.map +1 -0
  290. package/dist/compression/filters/git.d.ts +6 -0
  291. package/dist/compression/filters/git.d.ts.map +1 -0
  292. package/dist/compression/filters/github.d.ts +6 -0
  293. package/dist/compression/filters/github.d.ts.map +1 -0
  294. package/dist/compression/filters/lint.d.ts +6 -0
  295. package/dist/compression/filters/lint.d.ts.map +1 -0
  296. package/dist/compression/filters/misc.d.ts +6 -0
  297. package/dist/compression/filters/misc.d.ts.map +1 -0
  298. package/dist/compression/filters/package.d.ts +6 -0
  299. package/dist/compression/filters/package.d.ts.map +1 -0
  300. package/dist/compression/filters/test.d.ts +6 -0
  301. package/dist/compression/filters/test.d.ts.map +1 -0
  302. package/dist/compression/index.d.ts +29 -0
  303. package/dist/compression/index.d.ts.map +1 -0
  304. package/dist/compression/naive-cost.d.ts +26 -0
  305. package/dist/compression/naive-cost.d.ts.map +1 -0
  306. package/dist/compression/tracker.d.ts +155 -0
  307. package/dist/compression/tracker.d.ts.map +1 -0
  308. package/dist/compression/types.d.ts +49 -0
  309. package/dist/compression/types.d.ts.map +1 -0
  310. package/dist/config.d.ts +90 -0
  311. package/dist/config.d.ts.map +1 -1
  312. package/dist/config.js +55 -1
  313. package/dist/config.js.map +2 -2
  314. package/dist/core/lock-manager.d.ts +2 -0
  315. package/dist/core/lock-manager.d.ts.map +1 -1
  316. package/dist/core/pipeline.d.ts +4 -1
  317. package/dist/core/pipeline.d.ts.map +1 -1
  318. package/dist/core/pipeline.js +42 -0
  319. package/dist/core/pipeline.js.map +2 -2
  320. package/dist/core/snapshot.d.ts +58 -0
  321. package/dist/core/snapshot.d.ts.map +1 -0
  322. package/dist/data/filters.d.ts +23 -0
  323. package/dist/data/filters.d.ts.map +1 -0
  324. package/dist/data/indexer.d.ts +25 -0
  325. package/dist/data/indexer.d.ts.map +1 -0
  326. package/dist/data/linker.d.ts +37 -0
  327. package/dist/data/linker.d.ts.map +1 -0
  328. package/dist/data/lint.d.ts +27 -0
  329. package/dist/data/lint.d.ts.map +1 -0
  330. package/dist/data/parsers/csv.d.ts +11 -0
  331. package/dist/data/parsers/csv.d.ts.map +1 -0
  332. package/dist/data/parsers/excel.d.ts +10 -0
  333. package/dist/data/parsers/excel.d.ts.map +1 -0
  334. package/dist/data/parsers/index.d.ts +28 -0
  335. package/dist/data/parsers/index.d.ts.map +1 -0
  336. package/dist/data/parsers/json-array.d.ts +9 -0
  337. package/dist/data/parsers/json-array.d.ts.map +1 -0
  338. package/dist/data/parsers/jsonl.d.ts +9 -0
  339. package/dist/data/parsers/jsonl.d.ts.map +1 -0
  340. package/dist/data/parsers/parquet.d.ts +10 -0
  341. package/dist/data/parsers/parquet.d.ts.map +1 -0
  342. package/dist/data/profiler.d.ts +29 -0
  343. package/dist/data/profiler.d.ts.map +1 -0
  344. package/dist/data/queries.d.ts +95 -0
  345. package/dist/data/queries.d.ts.map +1 -0
  346. package/dist/data/types.d.ts +103 -0
  347. package/dist/data/types.d.ts.map +1 -0
  348. package/dist/db/database.d.ts +57 -0
  349. package/dist/db/database.d.ts.map +1 -1
  350. package/dist/db/database.js +19 -0
  351. package/dist/db/database.js.map +2 -2
  352. package/dist/db/patterns-schema.sql +23 -0
  353. package/dist/docs/formats/asciidoc.d.ts +9 -0
  354. package/dist/docs/formats/asciidoc.d.ts.map +1 -0
  355. package/dist/docs/formats/html.d.ts +10 -0
  356. package/dist/docs/formats/html.d.ts.map +1 -0
  357. package/dist/docs/formats/index.d.ts +31 -0
  358. package/dist/docs/formats/index.d.ts.map +1 -0
  359. package/dist/docs/formats/markdown.d.ts +11 -0
  360. package/dist/docs/formats/markdown.d.ts.map +1 -0
  361. package/dist/docs/formats/openapi.d.ts +17 -0
  362. package/dist/docs/formats/openapi.d.ts.map +1 -0
  363. package/dist/docs/formats/org.d.ts +9 -0
  364. package/dist/docs/formats/org.d.ts.map +1 -0
  365. package/dist/docs/formats/plaintext.d.ts +11 -0
  366. package/dist/docs/formats/plaintext.d.ts.map +1 -0
  367. package/dist/docs/formats/rdoc.d.ts +10 -0
  368. package/dist/docs/formats/rdoc.d.ts.map +1 -0
  369. package/dist/docs/formats/rst.d.ts +11 -0
  370. package/dist/docs/formats/rst.d.ts.map +1 -0
  371. package/dist/docs/indexer.d.ts +49 -0
  372. package/dist/docs/indexer.d.ts.map +1 -0
  373. package/dist/docs/linker.d.ts +30 -0
  374. package/dist/docs/linker.d.ts.map +1 -0
  375. package/dist/docs/lint.d.ts +27 -0
  376. package/dist/docs/lint.d.ts.map +1 -0
  377. package/dist/docs/queries.d.ts +78 -0
  378. package/dist/docs/queries.d.ts.map +1 -0
  379. package/dist/docs/section-id.d.ts +48 -0
  380. package/dist/docs/section-id.d.ts.map +1 -0
  381. package/dist/docs/summarizer.d.ts +13 -0
  382. package/dist/docs/summarizer.d.ts.map +1 -0
  383. package/dist/docs/types.d.ts +71 -0
  384. package/dist/docs/types.d.ts.map +1 -0
  385. package/dist/docs/vectors.d.ts +54 -0
  386. package/dist/docs/vectors.d.ts.map +1 -0
  387. package/dist/extraction/extractor.d.ts +1 -1
  388. package/dist/extraction/extractor.d.ts.map +1 -1
  389. package/dist/extraction/extractor.js +26 -3
  390. package/dist/extraction/extractor.js.map +2 -2
  391. package/dist/extraction/grammars.d.ts +6 -0
  392. package/dist/extraction/grammars.d.ts.map +1 -1
  393. package/dist/extraction/grammars.js +1 -0
  394. package/dist/extraction/grammars.js.map +2 -2
  395. package/dist/extraction/languages.d.ts.map +1 -1
  396. package/dist/extraction/languages.js +5 -1
  397. package/dist/extraction/languages.js.map +2 -2
  398. package/dist/extraction/notebook.d.ts +14 -0
  399. package/dist/extraction/notebook.d.ts.map +1 -0
  400. package/dist/frameworks/amplify.d.ts +9 -0
  401. package/dist/frameworks/amplify.d.ts.map +1 -0
  402. package/dist/frameworks/angular.d.ts +9 -0
  403. package/dist/frameworks/angular.d.ts.map +1 -0
  404. package/dist/frameworks/ansible.d.ts +8 -0
  405. package/dist/frameworks/ansible.d.ts.map +1 -0
  406. package/dist/frameworks/cloudformation.d.ts +9 -0
  407. package/dist/frameworks/cloudformation.d.ts.map +1 -0
  408. package/dist/frameworks/docker.d.ts +9 -0
  409. package/dist/frameworks/docker.d.ts.map +1 -0
  410. package/dist/frameworks/elixir.d.ts +6 -0
  411. package/dist/frameworks/elixir.d.ts.map +1 -0
  412. package/dist/frameworks/flutter.d.ts +12 -0
  413. package/dist/frameworks/flutter.d.ts.map +1 -0
  414. package/dist/frameworks/iac.d.ts +10 -0
  415. package/dist/frameworks/iac.d.ts.map +1 -0
  416. package/dist/frameworks/index.d.ts +14 -0
  417. package/dist/frameworks/index.d.ts.map +1 -1
  418. package/dist/frameworks/kubernetes.d.ts +9 -0
  419. package/dist/frameworks/kubernetes.d.ts.map +1 -0
  420. package/dist/frameworks/pulumi.d.ts +9 -0
  421. package/dist/frameworks/pulumi.d.ts.map +1 -0
  422. package/dist/frameworks/scala.d.ts +6 -0
  423. package/dist/frameworks/scala.d.ts.map +1 -0
  424. package/dist/frameworks/solidity.d.ts +6 -0
  425. package/dist/frameworks/solidity.d.ts.map +1 -0
  426. package/dist/frameworks/terraform.d.ts +14 -0
  427. package/dist/frameworks/terraform.d.ts.map +1 -0
  428. package/dist/frameworks/vue.d.ts +7 -0
  429. package/dist/frameworks/vue.d.ts.map +1 -0
  430. package/dist/graph/communities.d.ts +43 -0
  431. package/dist/graph/communities.d.ts.map +1 -0
  432. package/dist/graph/flows.d.ts +55 -0
  433. package/dist/graph/flows.d.ts.map +1 -0
  434. package/dist/graph/refactor.d.ts +43 -0
  435. package/dist/graph/refactor.d.ts.map +1 -0
  436. package/dist/index.d.ts +36 -4
  437. package/dist/index.d.ts.map +1 -1
  438. package/dist/mcp/cache.d.ts +69 -0
  439. package/dist/mcp/cache.d.ts.map +1 -0
  440. package/dist/mcp/read-modes.d.ts +31 -0
  441. package/dist/mcp/read-modes.d.ts.map +1 -0
  442. package/dist/mcp/server.d.ts +1 -0
  443. package/dist/mcp/server.d.ts.map +1 -1
  444. package/dist/mcp/server.js +15 -2
  445. package/dist/mcp/server.js.map +2 -2
  446. package/dist/mcp/tool-names.d.ts +2 -0
  447. package/dist/mcp/tool-names.d.ts.map +1 -0
  448. package/dist/mcp/tool-names.js +4 -1
  449. package/dist/mcp/tool-names.js.map +2 -2
  450. package/dist/mcp/tools.d.ts +12 -0
  451. package/dist/mcp/tools.d.ts.map +1 -1
  452. package/dist/mcp/tools.js +397 -0
  453. package/dist/mcp/tools.js.map +2 -2
  454. package/dist/memory/compress.d.ts +19 -0
  455. package/dist/memory/compress.d.ts.map +1 -0
  456. package/dist/memory/database.d.ts +92 -0
  457. package/dist/memory/database.d.ts.map +1 -0
  458. package/dist/memory/database.js +38 -0
  459. package/dist/memory/database.js.map +2 -2
  460. package/dist/memory/index.d.ts +71 -0
  461. package/dist/memory/index.d.ts.map +1 -0
  462. package/dist/memory/index.js +12 -2
  463. package/dist/memory/index.js.map +2 -2
  464. package/dist/memory/symbols.d.ts +21 -0
  465. package/dist/memory/symbols.d.ts.map +1 -0
  466. package/dist/memory/types.d.ts +78 -0
  467. package/dist/memory/types.d.ts.map +1 -0
  468. package/dist/memory/types.js.map +1 -1
  469. package/dist/memory/vectors.d.ts +43 -0
  470. package/dist/memory/vectors.d.ts.map +1 -0
  471. package/dist/patterns/graph.d.ts +16 -0
  472. package/dist/patterns/graph.d.ts.map +1 -0
  473. package/dist/patterns/graph.js +45 -0
  474. package/dist/patterns/graph.js.map +7 -0
  475. package/dist/patterns/index.d.ts +4 -0
  476. package/dist/patterns/index.d.ts.map +1 -0
  477. package/dist/patterns/index.js +39 -0
  478. package/dist/patterns/index.js.map +7 -0
  479. package/dist/patterns/indexer.d.ts +15 -0
  480. package/dist/patterns/indexer.d.ts.map +1 -0
  481. package/dist/patterns/indexer.js +97 -0
  482. package/dist/patterns/indexer.js.map +7 -0
  483. package/dist/patterns/library/code-eval-elixir.yaml +11 -0
  484. package/dist/patterns/library/command-injection-c.yaml +11 -0
  485. package/dist/patterns/library/command-injection-go.yaml +29 -0
  486. package/dist/patterns/library/command-injection-kotlin.yaml +10 -0
  487. package/dist/patterns/library/command-injection-php.yaml +11 -0
  488. package/dist/patterns/library/command-injection-ruby.yaml +11 -0
  489. package/dist/patterns/library/command-injection-rust.yaml +11 -0
  490. package/dist/patterns/library/dangerous-eval-bash.yaml +11 -0
  491. package/dist/patterns/library/dangerous-eval-js.yaml +14 -0
  492. package/dist/patterns/library/dangerous-eval-php.yaml +11 -0
  493. package/dist/patterns/library/dangerous-eval-ruby.yaml +11 -0
  494. package/dist/patterns/library/dangerous-exec-py.yaml +13 -0
  495. package/dist/patterns/library/dangerous-reflection-java.yaml +8 -0
  496. package/dist/patterns/library/dynamic-load-lua.yaml +10 -0
  497. package/dist/patterns/library/os-cmd-elixir.yaml +16 -0
  498. package/dist/patterns/library/os-execute-lua.yaml +10 -0
  499. package/dist/patterns/library/path-traversal-go.yaml +11 -0
  500. package/dist/patterns/library/path-traversal-py.yaml +12 -0
  501. package/dist/patterns/library/path-traversal-readfile-js.yaml +14 -0
  502. package/dist/patterns/library/process-launch-swift.yaml +11 -0
  503. package/dist/patterns/library/process-run-dart.yaml +15 -0
  504. package/dist/patterns/library/prototype-pollution-js.yaml +12 -0
  505. package/dist/patterns/library/source-injection-bash.yaml +11 -0
  506. package/dist/patterns/library/sql-injection-concat-js.yaml +12 -0
  507. package/dist/patterns/library/sql-injection-dart.yaml +9 -0
  508. package/dist/patterns/library/sql-injection-java.yaml +13 -0
  509. package/dist/patterns/library/sql-injection-kotlin.yaml +11 -0
  510. package/dist/patterns/library/sql-injection-php.yaml +9 -0
  511. package/dist/patterns/library/sql-injection-py.yaml +12 -0
  512. package/dist/patterns/library/sql-injection-swift.yaml +11 -0
  513. package/dist/patterns/library/sql-injection-template-js.yaml +13 -0
  514. package/dist/patterns/library/subshell-injection-ruby.yaml +8 -0
  515. package/dist/patterns/library/unsafe-block-rust.yaml +8 -0
  516. package/dist/patterns/library/unsafe-string-c.yaml +11 -0
  517. package/dist/patterns/library/weak-crypto-md5-js.yaml +13 -0
  518. package/dist/patterns/library/weak-crypto-py.yaml +13 -0
  519. package/dist/patterns/loader.d.ts +18 -0
  520. package/dist/patterns/loader.d.ts.map +1 -0
  521. package/dist/patterns/loader.js +277 -0
  522. package/dist/patterns/loader.js.map +7 -0
  523. package/dist/patterns/runner.d.ts +42 -0
  524. package/dist/patterns/runner.d.ts.map +1 -0
  525. package/dist/patterns/runner.js +295 -0
  526. package/dist/patterns/runner.js.map +7 -0
  527. package/dist/patterns/types.d.ts +27 -0
  528. package/dist/patterns/types.d.ts.map +1 -0
  529. package/dist/patterns/types.js +34 -0
  530. package/dist/patterns/types.js.map +7 -0
  531. package/dist/resolution/bridges/android-rn.d.ts +13 -0
  532. package/dist/resolution/bridges/android-rn.d.ts.map +1 -0
  533. package/dist/resolution/bridges/expo-modules.d.ts +10 -0
  534. package/dist/resolution/bridges/expo-modules.d.ts.map +1 -0
  535. package/dist/resolution/bridges/flutter-channel.d.ts +14 -0
  536. package/dist/resolution/bridges/flutter-channel.d.ts.map +1 -0
  537. package/dist/resolution/bridges/index.d.ts +40 -0
  538. package/dist/resolution/bridges/index.d.ts.map +1 -0
  539. package/dist/resolution/bridges/native-events.d.ts +10 -0
  540. package/dist/resolution/bridges/native-events.d.ts.map +1 -0
  541. package/dist/resolution/bridges/native-views.d.ts +13 -0
  542. package/dist/resolution/bridges/native-views.d.ts.map +1 -0
  543. package/dist/resolution/bridges/react-native.d.ts +9 -0
  544. package/dist/resolution/bridges/react-native.d.ts.map +1 -0
  545. package/dist/resolution/bridges/swift-objc.d.ts +14 -0
  546. package/dist/resolution/bridges/swift-objc.d.ts.map +1 -0
  547. package/dist/resolution/bridges/turbomodules.d.ts +10 -0
  548. package/dist/resolution/bridges/turbomodules.d.ts.map +1 -0
  549. package/dist/resolution/index.d.ts +28 -3
  550. package/dist/resolution/index.d.ts.map +1 -1
  551. package/dist/security/attack-surface.d.ts +46 -0
  552. package/dist/security/attack-surface.d.ts.map +1 -0
  553. package/dist/security/attack-surface.js +43 -1
  554. package/dist/security/attack-surface.js.map +2 -2
  555. package/dist/security/context-warnings.d.ts +40 -0
  556. package/dist/security/context-warnings.d.ts.map +1 -0
  557. package/dist/security/data-flows.d.ts +33 -0
  558. package/dist/security/data-flows.d.ts.map +1 -0
  559. package/dist/security/data-flows.js +65 -7
  560. package/dist/security/data-flows.js.map +2 -2
  561. package/dist/security/dep-confusion.d.ts +23 -0
  562. package/dist/security/dep-confusion.d.ts.map +1 -0
  563. package/dist/security/errors.d.ts +16 -0
  564. package/dist/security/errors.d.ts.map +1 -0
  565. package/dist/security/export/fix-suggestions.d.ts +21 -0
  566. package/dist/security/export/fix-suggestions.d.ts.map +1 -0
  567. package/dist/security/export/sbom.d.ts +33 -0
  568. package/dist/security/export/sbom.d.ts.map +1 -0
  569. package/dist/security/export/serialization.d.ts +62 -0
  570. package/dist/security/export/serialization.d.ts.map +1 -0
  571. package/dist/security/export/vex.d.ts +58 -0
  572. package/dist/security/export/vex.d.ts.map +1 -0
  573. package/dist/security/index.d.ts +21 -0
  574. package/dist/security/index.d.ts.map +1 -0
  575. package/dist/security/integrator.d.ts +63 -0
  576. package/dist/security/integrator.d.ts.map +1 -0
  577. package/dist/security/integrator.js +8 -8
  578. package/dist/security/integrator.js.map +2 -2
  579. package/dist/security/license.d.ts +33 -0
  580. package/dist/security/license.d.ts.map +1 -0
  581. package/dist/security/manifest/adapter.d.ts +92 -0
  582. package/dist/security/manifest/adapter.d.ts.map +1 -0
  583. package/dist/security/manifest/parser.d.ts +73 -0
  584. package/dist/security/manifest/parser.d.ts.map +1 -0
  585. package/dist/security/manifest/plugins/cargo.d.ts +11 -0
  586. package/dist/security/manifest/plugins/cargo.d.ts.map +1 -0
  587. package/dist/security/manifest/plugins/composer.d.ts +11 -0
  588. package/dist/security/manifest/plugins/composer.d.ts.map +1 -0
  589. package/dist/security/manifest/plugins/go.d.ts +12 -0
  590. package/dist/security/manifest/plugins/go.d.ts.map +1 -0
  591. package/dist/security/manifest/plugins/gradle.d.ts +12 -0
  592. package/dist/security/manifest/plugins/gradle.d.ts.map +1 -0
  593. package/dist/security/manifest/plugins/hex.d.ts +11 -0
  594. package/dist/security/manifest/plugins/hex.d.ts.map +1 -0
  595. package/dist/security/manifest/plugins/maven.d.ts +11 -0
  596. package/dist/security/manifest/plugins/maven.d.ts.map +1 -0
  597. package/dist/security/manifest/plugins/npm.d.ts +11 -0
  598. package/dist/security/manifest/plugins/npm.d.ts.map +1 -0
  599. package/dist/security/manifest/plugins/nuget.d.ts +12 -0
  600. package/dist/security/manifest/plugins/nuget.d.ts.map +1 -0
  601. package/dist/security/manifest/plugins/pip.d.ts +11 -0
  602. package/dist/security/manifest/plugins/pip.d.ts.map +1 -0
  603. package/dist/security/manifest/plugins/pubspec.d.ts +11 -0
  604. package/dist/security/manifest/plugins/pubspec.d.ts.map +1 -0
  605. package/dist/security/manifest/plugins/pyproject.d.ts +3 -0
  606. package/dist/security/manifest/plugins/pyproject.d.ts.map +1 -0
  607. package/dist/security/manifest/plugins/rubygems.d.ts +11 -0
  608. package/dist/security/manifest/plugins/rubygems.d.ts.map +1 -0
  609. package/dist/security/manifest/plugins/swift.d.ts +11 -0
  610. package/dist/security/manifest/plugins/swift.d.ts.map +1 -0
  611. package/dist/security/owasp.d.ts +16 -0
  612. package/dist/security/owasp.d.ts.map +1 -0
  613. package/dist/security/pipeline.d.ts +37 -0
  614. package/dist/security/pipeline.d.ts.map +1 -0
  615. package/dist/security/reachability.d.ts +67 -0
  616. package/dist/security/reachability.d.ts.map +1 -0
  617. package/dist/security/remediation.d.ts +51 -0
  618. package/dist/security/remediation.d.ts.map +1 -0
  619. package/dist/security/secrets.d.ts +38 -0
  620. package/dist/security/secrets.d.ts.map +1 -0
  621. package/dist/security/staleness.d.ts +43 -0
  622. package/dist/security/staleness.d.ts.map +1 -0
  623. package/dist/security/supply-chain.d.ts +34 -0
  624. package/dist/security/supply-chain.d.ts.map +1 -0
  625. package/dist/security/suppressions.d.ts +18 -0
  626. package/dist/security/suppressions.d.ts.map +1 -0
  627. package/dist/security/types.d.ts +144 -0
  628. package/dist/security/types.d.ts.map +1 -0
  629. package/dist/security/vuln/client.d.ts +90 -0
  630. package/dist/security/vuln/client.d.ts.map +1 -0
  631. package/dist/security/vuln/client.js.map +2 -2
  632. package/dist/security/vuln/epss-client.d.ts +26 -0
  633. package/dist/security/vuln/epss-client.d.ts.map +1 -0
  634. package/dist/security/vuln/index.d.ts +6 -0
  635. package/dist/security/vuln/index.d.ts.map +1 -0
  636. package/dist/security/vuln/osv-adapter.d.ts +58 -0
  637. package/dist/security/vuln/osv-adapter.d.ts.map +1 -0
  638. package/dist/security/vuln/types.d.ts +29 -0
  639. package/dist/security/vuln/types.d.ts.map +1 -0
  640. package/dist/sync/index.d.ts +4 -2
  641. package/dist/sync/index.d.ts.map +1 -1
  642. package/dist/types.d.ts +10 -4
  643. package/dist/types.d.ts.map +1 -1
  644. package/dist/types.js.map +2 -2
  645. package/dist/vectors/index.d.ts +11 -3
  646. package/dist/vectors/index.d.ts.map +1 -1
  647. package/dist/vectors/qdrant-index.d.ts +10 -3
  648. package/dist/vectors/qdrant-index.d.ts.map +1 -1
  649. package/dist/vectors/turboquant-index.js +261 -0
  650. package/dist/vectors/turboquant-index.js.map +7 -0
  651. package/dist/vectors/typesense-index.d.ts.map +1 -1
  652. package/dist/watchmen/index.js +83 -0
  653. package/dist/watchmen/index.js.map +7 -0
  654. package/dist/watchmen/synthesize.js +475 -0
  655. package/dist/watchmen/synthesize.js.map +7 -0
  656. package/package.json +24 -2
  657. package/dist/security/context-warnings.test.js +0 -300
  658. package/dist/security/context-warnings.test.js.map +0 -7
  659. package/dist/security/export/fix-suggestions.test.js +0 -74
  660. package/dist/security/export/fix-suggestions.test.js.map +0 -7
  661. package/dist/security/export/sbom.test.js +0 -288
  662. package/dist/security/export/sbom.test.js.map +0 -7
  663. package/dist/security/export/serialization.test.js +0 -310
  664. package/dist/security/export/serialization.test.js.map +0 -7
  665. package/dist/security/export/vex.test.js +0 -278
  666. package/dist/security/export/vex.test.js.map +0 -7
  667. package/dist/security/integrator-transitives.test.js +0 -359
  668. package/dist/security/integrator-transitives.test.js.map +0 -7
  669. package/dist/security/integrator.test.js +0 -237
  670. package/dist/security/integrator.test.js.map +0 -7
  671. package/dist/security/manifest/adapter.test.js +0 -272
  672. package/dist/security/manifest/adapter.test.js.map +0 -7
  673. package/dist/security/manifest/parser.test.js +0 -110
  674. package/dist/security/manifest/parser.test.js.map +0 -7
  675. package/dist/security/manifest/plugins/cargo.test.js +0 -304
  676. package/dist/security/manifest/plugins/cargo.test.js.map +0 -7
  677. package/dist/security/manifest/plugins/go.test.js +0 -341
  678. package/dist/security/manifest/plugins/go.test.js.map +0 -7
  679. package/dist/security/manifest/plugins/maven.test.js +0 -389
  680. package/dist/security/manifest/plugins/maven.test.js.map +0 -7
  681. package/dist/security/manifest/plugins/npm.test.js +0 -298
  682. package/dist/security/manifest/plugins/npm.test.js.map +0 -7
  683. package/dist/security/manifest/plugins/pip.test.js +0 -208
  684. package/dist/security/manifest/plugins/pip.test.js.map +0 -7
  685. package/dist/security/reachability.test.js +0 -394
  686. package/dist/security/reachability.test.js.map +0 -7
  687. package/dist/security/vuln/client.test.js +0 -288
  688. package/dist/security/vuln/client.test.js.map +0 -7
  689. package/dist/security/vuln/osv-adapter.test.js +0 -391
  690. package/dist/security/vuln/osv-adapter.test.js.map +0 -7
@@ -6,22 +6,26 @@
6
6
  */
7
7
  import type { GraphDatabase } from '../db/database';
8
8
  import type { KiroGraphConfig } from '../config';
9
+ import { type BridgeResolutionResult } from './bridges';
9
10
  export interface ResolutionResult {
10
11
  resolved: number;
11
12
  unresolved: number;
12
13
  total: number;
13
14
  durationMs: number;
15
+ bridgeResult?: BridgeResolutionResult;
14
16
  }
15
17
  export declare class ReferenceResolver {
16
18
  private db;
17
19
  private config;
20
+ private projectRoot;
18
21
  private nameCache;
19
22
  private qualifiedNameCache;
20
23
  private kindCache;
21
24
  private lowerNameCache;
22
25
  private nodeByIdCache;
26
+ private namespacePrefixCache;
23
27
  private cacheWarmed;
24
- constructor(db: GraphDatabase, config: KiroGraphConfig);
28
+ constructor(db: GraphDatabase, config: KiroGraphConfig, projectRoot?: string);
25
29
  /**
26
30
  * Pre-load all nodes into Maps for O(1) lookup.
27
31
  * Must be called before resolveUnresolvedRefs() for best performance.
@@ -44,13 +48,34 @@ export declare class ReferenceResolver {
44
48
  */
45
49
  invalidateFile(filePath: string): void;
46
50
  /**
47
- * Resolve a relative import path to the ID of the first node in the target file.
48
- * Returns null if no indexed file matches.
51
+ * Resolve an import path to a node ID.
52
+ *
53
+ * Handles three cases:
54
+ * 1. Relative paths (JS/TS/Go/…) — resolved via the file tree.
55
+ * 2. Fully-qualified type imports (Java `import com.example.Foo`) — exact qualifiedName lookup,
56
+ * then name+namespace-prefix match.
57
+ * 3. Namespace-level imports (C# `using MyApp.Services`) — namespace node lookup, then
58
+ * namespace prefix cache (O(1)) to find any class in that namespace.
49
59
  */
50
60
  private _resolveImportPath;
61
+ /**
62
+ * Resolve a bare type name to a node ID.
63
+ * Used for extends/implements refs where we have only the unqualified type name.
64
+ * Prefers class/interface/trait/protocol nodes over other kinds.
65
+ */
66
+ private _resolveTypeName;
51
67
  /**
52
68
  * Convert a raw DB row to a Node object.
53
69
  */
54
70
  private _rowToNode;
71
+ /**
72
+ * Run cross-language bridge resolvers to synthesize edges between
73
+ * symbols in different languages (Swift ↔ ObjC, JS ↔ Native, etc.).
74
+ */
75
+ private _runBridgeResolvers;
76
+ /**
77
+ * Build a ResolutionContext for bridge resolvers using the warm caches.
78
+ */
79
+ private _buildBridgeContext;
55
80
  }
56
81
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resolution/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAMjD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAID,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,MAAM,CAAkB;IAGhC,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,kBAAkB,CAAgC;IAC1D,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,cAAc,CAAkC;IACxD,OAAO,CAAC,aAAa,CAAgC;IAErD,OAAO,CAAC,WAAW,CAAS;gBAEhB,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,eAAe;IAKtD;;;OAGG;IACH,UAAU,IAAI,IAAI;IA2ClB;;;;OAIG;IACG,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAsBlG;;;OAGG;IACG,qBAAqB,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IAkHnG;;;OAGG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IA6DtC;;;OAGG;IACH,OAAO,CAAC,kBAAkB;IAgC1B;;OAEG;IACH,OAAO,CAAC,UAAU;CAwBnB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resolution/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGjD,OAAO,EAAsB,KAAK,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAI5E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,sBAAsB,CAAC;CACvC;AAID,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAAgB;IAC1B,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,WAAW,CAAS;IAG5B,OAAO,CAAC,SAAS,CAAkC;IACnD,OAAO,CAAC,kBAAkB,CAAgC;IAC1D,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,cAAc,CAAkC;IACxD,OAAO,CAAC,aAAa,CAAgC;IAErD,OAAO,CAAC,oBAAoB,CAAkC;IAE9D,OAAO,CAAC,WAAW,CAAS;gBAEhB,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,eAAe,EAAE,WAAW,CAAC,EAAE,MAAM;IAM5E;;;OAGG;IACH,UAAU,IAAI,IAAI;IA2DlB;;;;OAIG;IACG,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA6BlG;;;OAGG;IACG,qBAAqB,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC;IA+InG;;;OAGG;IACH,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IA6DtC;;;;;;;;;OASG;IACH,OAAO,CAAC,kBAAkB;IA0D1B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;OAEG;IACH,OAAO,CAAC,UAAU;IA2BlB;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAK3B;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAyC5B"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * KiroGraph-Sec Attack Surface Analyzer
3
+ *
4
+ * Maps all route nodes in the knowledge graph to their reachable vulnerable
5
+ * dependencies, computing exposure levels and risk scores per route.
6
+ */
7
+ import type { GraphDatabase } from '../db/database';
8
+ export interface AttackSurfaceEntry {
9
+ route: string;
10
+ nodeId: string;
11
+ filePath: string;
12
+ isAuthenticated: boolean;
13
+ exposureLevel: 'public' | 'authenticated' | 'internal' | 'unknown';
14
+ vulnerableDeps: Array<{
15
+ cveId: string;
16
+ packageName: string;
17
+ severity: number | null;
18
+ epssScore: number | null;
19
+ riskScore: number | null;
20
+ verdict: string | null;
21
+ hopCount: number;
22
+ }>;
23
+ patternMatches: Array<{
24
+ patternId: string;
25
+ severity: string;
26
+ line: number;
27
+ symbolNodeId: string;
28
+ symbolName: string;
29
+ }>;
30
+ patternRiskLevel: 'none' | 'low' | 'medium' | 'high' | 'critical';
31
+ riskScore: number;
32
+ }
33
+ export interface AttackSurfaceResult {
34
+ totalRoutes: number;
35
+ publicRoutes: number;
36
+ authenticatedRoutes: number;
37
+ routesWithVulns: number;
38
+ criticalPaths: AttackSurfaceEntry[];
39
+ allRoutes: AttackSurfaceEntry[];
40
+ }
41
+ export declare class AttackSurfaceAnalyzer {
42
+ private readonly db;
43
+ constructor(db: GraphDatabase);
44
+ analyze(): Promise<AttackSurfaceResult>;
45
+ }
46
+ //# sourceMappingURL=attack-surface.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attack-surface.d.ts","sourceRoot":"","sources":["../../src/security/attack-surface.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAsBpD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,OAAO,CAAC;IACzB,aAAa,EAAE,QAAQ,GAAG,eAAe,GAAG,UAAU,GAAG,SAAS,CAAC;IACnE,cAAc,EAAE,KAAK,CAAC;QACpB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IACH,cAAc,EAAE,KAAK,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,gBAAgB,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IAClE,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,kBAAkB,EAAE,CAAC;IACpC,SAAS,EAAE,kBAAkB,EAAE,CAAC;CACjC;AAED,qBAAa,qBAAqB;IACpB,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,aAAa;IAExC,OAAO,IAAI,OAAO,CAAC,mBAAmB,CAAC;CAgN9C"}
@@ -95,6 +95,38 @@ class AttackSurfaceAnalyzer {
95
95
  });
96
96
  }
97
97
  }
98
+ const routeNodeId = route.id;
99
+ let patternRows = [];
100
+ try {
101
+ patternRows = rawDb.all(
102
+ `WITH RECURSIVE reachable(node_id, depth) AS (
103
+ SELECT target, 1 FROM edges WHERE source = ? AND kind IN ('calls', 'imports', 'references')
104
+ UNION
105
+ SELECT e.target, r.depth + 1
106
+ FROM edges e
107
+ JOIN reachable r ON e.source = r.node_id
108
+ WHERE r.depth < 5 AND e.kind IN ('calls', 'imports', 'references')
109
+ )
110
+ SELECT DISTINCT pm.symbol_node_id, n.name as symbol_name, pm.pattern_id, pm.severity, pm.line
111
+ FROM reachable r
112
+ JOIN pattern_matches pm ON pm.symbol_node_id = r.node_id
113
+ JOIN nodes n ON n.id = pm.symbol_node_id
114
+ WHERE pm.symbol_node_id IS NOT NULL
115
+ ORDER BY CASE pm.severity WHEN 'critical' THEN 4 WHEN 'high' THEN 3 WHEN 'medium' THEN 2 ELSE 1 END DESC
116
+ LIMIT 10`,
117
+ [routeNodeId]
118
+ );
119
+ } catch {
120
+ patternRows = [];
121
+ }
122
+ const patternMatches = patternRows.map((r) => ({
123
+ patternId: r.pattern_id,
124
+ severity: r.severity,
125
+ line: r.line,
126
+ symbolNodeId: r.symbol_node_id,
127
+ symbolName: r.symbol_name
128
+ }));
129
+ const patternRiskLevel = patternMatches.length === 0 ? "none" : patternMatches[0].severity;
98
130
  const pathNodeNames = rawDb.all(
99
131
  `WITH RECURSIVE reachable(node_id, depth) AS (
100
132
  SELECT target, 1 FROM edges WHERE source = ? AND kind IN ('calls', 'imports', 'references')
@@ -126,10 +158,18 @@ class AttackSurfaceAnalyzer {
126
158
  exposureLevel = "unknown";
127
159
  }
128
160
  const affectedVulns = vulnerableDeps.filter((v) => v.verdict === "affected" || v.verdict === "under_investigation");
129
- const riskScore = affectedVulns.reduce((max, v) => {
161
+ const baseRiskScore = affectedVulns.reduce((max, v) => {
130
162
  if (v.riskScore != null && v.riskScore > max) return v.riskScore;
131
163
  return max;
132
164
  }, 0);
165
+ const patternBonus = {
166
+ none: 0,
167
+ low: 0.3,
168
+ medium: 0.6,
169
+ high: 0.8,
170
+ critical: 1
171
+ };
172
+ const riskScore = Math.min(10, baseRiskScore + (patternBonus[patternRiskLevel] ?? 0));
133
173
  entries.push({
134
174
  route: route.name ?? route.id,
135
175
  nodeId: route.id,
@@ -137,6 +177,8 @@ class AttackSurfaceAnalyzer {
137
177
  isAuthenticated,
138
178
  exposureLevel,
139
179
  vulnerableDeps,
180
+ patternMatches,
181
+ patternRiskLevel,
140
182
  riskScore
141
183
  });
142
184
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/security/attack-surface.ts"],
4
- "sourcesContent": ["/**\n * KiroGraph-Sec Attack Surface Analyzer\n *\n * Maps all route nodes in the knowledge graph to their reachable vulnerable\n * dependencies, computing exposure levels and risk scores per route.\n */\n\nimport type { GraphDatabase } from '../db/database';\n\n/** Auth-related name patterns for heuristic isAuthenticated detection. */\nconst AUTH_PATTERNS = [\n 'auth',\n 'authenticate',\n 'middleware',\n 'guard',\n 'protect',\n 'requirelogin',\n 'isloggedin',\n 'verifytoken',\n 'checkauth',\n 'ensureauth',\n] as const;\n\n/** Route path patterns that indicate a public-facing API. */\nconst PUBLIC_ROUTE_PATTERNS = ['/api/', '/v1/', '/v2/', '/v3/', '/graphql', '/rest/'];\n\n/** Route path patterns that indicate an internal/admin route. */\nconst INTERNAL_ROUTE_PATTERNS = ['/internal/', '/admin/'];\n\nexport interface AttackSurfaceEntry {\n route: string;\n nodeId: string;\n filePath: string;\n isAuthenticated: boolean;\n exposureLevel: 'public' | 'authenticated' | 'internal' | 'unknown';\n vulnerableDeps: Array<{\n cveId: string;\n packageName: string;\n severity: number | null;\n epssScore: number | null;\n riskScore: number | null;\n verdict: string | null;\n hopCount: number;\n }>;\n riskScore: number;\n}\n\nexport interface AttackSurfaceResult {\n totalRoutes: number;\n publicRoutes: number;\n authenticatedRoutes: number;\n routesWithVulns: number;\n criticalPaths: AttackSurfaceEntry[];\n allRoutes: AttackSurfaceEntry[];\n}\n\nexport class AttackSurfaceAnalyzer {\n constructor(private readonly db: GraphDatabase) {}\n\n async analyze(): Promise<AttackSurfaceResult> {\n const rawDb = this.db.getRawDb();\n\n // Step 1: Query all route nodes\n const routeRows: Array<{ id: string; name: string; file_path: string }> = rawDb.all(\n `SELECT id, name, file_path FROM nodes WHERE kind = 'route'`,\n );\n\n if (routeRows.length === 0) {\n return {\n totalRoutes: 0,\n publicRoutes: 0,\n authenticatedRoutes: 0,\n routesWithVulns: 0,\n criticalPaths: [],\n allRoutes: [],\n };\n }\n\n const entries: AttackSurfaceEntry[] = [];\n\n for (const route of routeRows) {\n // Step 2: BFS via SQL to find reachable dependency nodes (max 5 hops)\n const reachableDeps: Array<{\n node_id: string;\n package_name: string;\n hop_count: number;\n }> = rawDb.all(\n `WITH RECURSIVE reachable(node_id, depth) AS (\n SELECT target, 1 FROM edges WHERE source = ? AND kind IN ('calls', 'imports', 'references')\n UNION\n SELECT e.target, r.depth + 1\n FROM edges e\n JOIN reachable r ON e.source = r.node_id\n WHERE r.depth < 5 AND e.kind IN ('calls', 'imports', 'references')\n )\n SELECT d.node_id, d.package_name, MIN(r.depth) as hop_count\n FROM reachable r\n JOIN sec_dependencies d ON d.node_id = r.node_id\n GROUP BY d.node_id, d.package_name`,\n [route.id],\n );\n\n // Step 3: For each reachable dep, find affected/under_investigation vulns\n const vulnerableDeps: AttackSurfaceEntry['vulnerableDeps'] = [];\n\n for (const dep of reachableDeps) {\n const vulnRows: Array<{\n cve_id: string;\n package_name: string;\n severity_score: number | null;\n epss_score: number | null;\n risk_score: number | null;\n verdict: string | null;\n }> = rawDb.all(\n `SELECT v.cve_id, d.package_name, v.severity_score, v.epss_score, v.risk_score, r.verdict\n FROM sec_vulnerabilities v\n JOIN edges e ON e.target = v.node_id AND e.kind = 'has_vulnerability'\n JOIN sec_dependencies d ON d.node_id = e.source\n LEFT JOIN sec_reachability r ON r.vulnerability_node_id = v.node_id\n WHERE d.node_id = ?\n AND (r.verdict IN ('affected', 'under_investigation') OR r.verdict IS NULL)`,\n [dep.node_id],\n );\n\n for (const vuln of vulnRows) {\n vulnerableDeps.push({\n cveId: vuln.cve_id,\n packageName: vuln.package_name ?? dep.package_name,\n severity: vuln.severity_score,\n epssScore: vuln.epss_score,\n riskScore: vuln.risk_score,\n verdict: vuln.verdict,\n hopCount: dep.hop_count,\n });\n }\n }\n\n // Step 4: Heuristic \u2014 isAuthenticated via path node names\n const pathNodeNames: Array<{ name: string }> = rawDb.all(\n `WITH RECURSIVE reachable(node_id, depth) AS (\n SELECT target, 1 FROM edges WHERE source = ? AND kind IN ('calls', 'imports', 'references')\n UNION\n SELECT e.target, r.depth + 1\n FROM edges e\n JOIN reachable r ON e.source = r.node_id\n WHERE r.depth < 5 AND e.kind IN ('calls', 'imports', 'references')\n )\n SELECT DISTINCT n.name\n FROM reachable r\n JOIN nodes n ON n.id = r.node_id\n WHERE n.name IS NOT NULL`,\n [route.id],\n );\n\n const isAuthenticated = pathNodeNames.some(row => {\n const lowerName = (row.name ?? '').toLowerCase();\n return AUTH_PATTERNS.some(pattern => lowerName.includes(pattern));\n });\n\n // Step 5: Determine exposure level\n const routeName = (route.name ?? '').toLowerCase();\n let exposureLevel: AttackSurfaceEntry['exposureLevel'];\n\n if (INTERNAL_ROUTE_PATTERNS.some(p => routeName.includes(p))) {\n exposureLevel = 'internal';\n } else if (isAuthenticated) {\n exposureLevel = 'authenticated';\n } else if (PUBLIC_ROUTE_PATTERNS.some(p => routeName.includes(p))) {\n exposureLevel = 'public';\n } else {\n exposureLevel = 'unknown';\n }\n\n // Step 6: riskScore = max risk_score of reachable affected vulns\n const affectedVulns = vulnerableDeps.filter(v => v.verdict === 'affected' || v.verdict === 'under_investigation');\n const riskScore = affectedVulns.reduce((max, v) => {\n if (v.riskScore != null && v.riskScore > max) return v.riskScore;\n return max;\n }, 0);\n\n entries.push({\n route: route.name ?? route.id,\n nodeId: route.id,\n filePath: route.file_path ?? '',\n isAuthenticated,\n exposureLevel,\n vulnerableDeps,\n riskScore,\n });\n }\n\n // Compute summary stats\n const publicRoutes = entries.filter(e => e.exposureLevel === 'public').length;\n const authenticatedRoutes = entries.filter(\n e => e.exposureLevel === 'authenticated' || e.exposureLevel === 'internal',\n ).length;\n const routesWithVulns = entries.filter(e => e.vulnerableDeps.length > 0).length;\n\n // Critical paths: routes with affected/under_investigation vulns, sorted by riskScore desc\n const criticalPaths = entries\n .filter(e => e.vulnerableDeps.length > 0)\n .sort((a, b) => b.riskScore - a.riskScore);\n\n const allRoutes = entries.sort((a, b) => b.riskScore - a.riskScore);\n\n return {\n totalRoutes: entries.length,\n publicRoutes,\n authenticatedRoutes,\n routesWithVulns,\n criticalPaths,\n allRoutes,\n };\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * KiroGraph-Sec Attack Surface Analyzer\n *\n * Maps all route nodes in the knowledge graph to their reachable vulnerable\n * dependencies, computing exposure levels and risk scores per route.\n */\n\nimport type { GraphDatabase } from '../db/database';\n\n/** Auth-related name patterns for heuristic isAuthenticated detection. */\nconst AUTH_PATTERNS = [\n 'auth',\n 'authenticate',\n 'middleware',\n 'guard',\n 'protect',\n 'requirelogin',\n 'isloggedin',\n 'verifytoken',\n 'checkauth',\n 'ensureauth',\n] as const;\n\n/** Route path patterns that indicate a public-facing API. */\nconst PUBLIC_ROUTE_PATTERNS = ['/api/', '/v1/', '/v2/', '/v3/', '/graphql', '/rest/'];\n\n/** Route path patterns that indicate an internal/admin route. */\nconst INTERNAL_ROUTE_PATTERNS = ['/internal/', '/admin/'];\n\nexport interface AttackSurfaceEntry {\n route: string;\n nodeId: string;\n filePath: string;\n isAuthenticated: boolean;\n exposureLevel: 'public' | 'authenticated' | 'internal' | 'unknown';\n vulnerableDeps: Array<{\n cveId: string;\n packageName: string;\n severity: number | null;\n epssScore: number | null;\n riskScore: number | null;\n verdict: string | null;\n hopCount: number;\n }>;\n patternMatches: Array<{\n patternId: string;\n severity: string;\n line: number;\n symbolNodeId: string;\n symbolName: string;\n }>;\n patternRiskLevel: 'none' | 'low' | 'medium' | 'high' | 'critical';\n riskScore: number;\n}\n\nexport interface AttackSurfaceResult {\n totalRoutes: number;\n publicRoutes: number;\n authenticatedRoutes: number;\n routesWithVulns: number;\n criticalPaths: AttackSurfaceEntry[];\n allRoutes: AttackSurfaceEntry[];\n}\n\nexport class AttackSurfaceAnalyzer {\n constructor(private readonly db: GraphDatabase) {}\n\n async analyze(): Promise<AttackSurfaceResult> {\n const rawDb = this.db.getRawDb();\n\n // Step 1: Query all route nodes\n const routeRows: Array<{ id: string; name: string; file_path: string }> = rawDb.all(\n `SELECT id, name, file_path FROM nodes WHERE kind = 'route'`,\n );\n\n if (routeRows.length === 0) {\n return {\n totalRoutes: 0,\n publicRoutes: 0,\n authenticatedRoutes: 0,\n routesWithVulns: 0,\n criticalPaths: [],\n allRoutes: [],\n };\n }\n\n const entries: AttackSurfaceEntry[] = [];\n\n for (const route of routeRows) {\n // Step 2: BFS via SQL to find reachable dependency nodes (max 5 hops)\n const reachableDeps: Array<{\n node_id: string;\n package_name: string;\n hop_count: number;\n }> = rawDb.all(\n `WITH RECURSIVE reachable(node_id, depth) AS (\n SELECT target, 1 FROM edges WHERE source = ? AND kind IN ('calls', 'imports', 'references')\n UNION\n SELECT e.target, r.depth + 1\n FROM edges e\n JOIN reachable r ON e.source = r.node_id\n WHERE r.depth < 5 AND e.kind IN ('calls', 'imports', 'references')\n )\n SELECT d.node_id, d.package_name, MIN(r.depth) as hop_count\n FROM reachable r\n JOIN sec_dependencies d ON d.node_id = r.node_id\n GROUP BY d.node_id, d.package_name`,\n [route.id],\n );\n\n // Step 3: For each reachable dep, find affected/under_investigation vulns\n const vulnerableDeps: AttackSurfaceEntry['vulnerableDeps'] = [];\n\n for (const dep of reachableDeps) {\n const vulnRows: Array<{\n cve_id: string;\n package_name: string;\n severity_score: number | null;\n epss_score: number | null;\n risk_score: number | null;\n verdict: string | null;\n }> = rawDb.all(\n `SELECT v.cve_id, d.package_name, v.severity_score, v.epss_score, v.risk_score, r.verdict\n FROM sec_vulnerabilities v\n JOIN edges e ON e.target = v.node_id AND e.kind = 'has_vulnerability'\n JOIN sec_dependencies d ON d.node_id = e.source\n LEFT JOIN sec_reachability r ON r.vulnerability_node_id = v.node_id\n WHERE d.node_id = ?\n AND (r.verdict IN ('affected', 'under_investigation') OR r.verdict IS NULL)`,\n [dep.node_id],\n );\n\n for (const vuln of vulnRows) {\n vulnerableDeps.push({\n cveId: vuln.cve_id,\n packageName: vuln.package_name ?? dep.package_name,\n severity: vuln.severity_score,\n epssScore: vuln.epss_score,\n riskScore: vuln.risk_score,\n verdict: vuln.verdict,\n hopCount: dep.hop_count,\n });\n }\n }\n\n // Step 3b: Find pattern matches on the call path (table may not exist)\n const routeNodeId = route.id;\n let patternRows: Array<{\n symbol_node_id: string;\n symbol_name: string;\n pattern_id: string;\n severity: string;\n line: number;\n }> = [];\n try {\n patternRows = rawDb.all(\n `WITH RECURSIVE reachable(node_id, depth) AS (\n SELECT target, 1 FROM edges WHERE source = ? AND kind IN ('calls', 'imports', 'references')\n UNION\n SELECT e.target, r.depth + 1\n FROM edges e\n JOIN reachable r ON e.source = r.node_id\n WHERE r.depth < 5 AND e.kind IN ('calls', 'imports', 'references')\n )\n SELECT DISTINCT pm.symbol_node_id, n.name as symbol_name, pm.pattern_id, pm.severity, pm.line\n FROM reachable r\n JOIN pattern_matches pm ON pm.symbol_node_id = r.node_id\n JOIN nodes n ON n.id = pm.symbol_node_id\n WHERE pm.symbol_node_id IS NOT NULL\n ORDER BY CASE pm.severity WHEN 'critical' THEN 4 WHEN 'high' THEN 3 WHEN 'medium' THEN 2 ELSE 1 END DESC\n LIMIT 10`,\n [routeNodeId],\n );\n } catch {\n // pattern_matches table does not exist yet \u2014 degrade silently\n patternRows = [];\n }\n\n const patternMatches: AttackSurfaceEntry['patternMatches'] = patternRows.map(r => ({\n patternId: r.pattern_id,\n severity: r.severity,\n line: r.line,\n symbolNodeId: r.symbol_node_id,\n symbolName: r.symbol_name,\n }));\n\n const patternRiskLevel: AttackSurfaceEntry['patternRiskLevel'] =\n patternMatches.length === 0\n ? 'none'\n : (patternMatches[0].severity as AttackSurfaceEntry['patternRiskLevel']);\n\n // Step 4: Heuristic \u2014 isAuthenticated via path node names\n const pathNodeNames: Array<{ name: string }> = rawDb.all(\n `WITH RECURSIVE reachable(node_id, depth) AS (\n SELECT target, 1 FROM edges WHERE source = ? AND kind IN ('calls', 'imports', 'references')\n UNION\n SELECT e.target, r.depth + 1\n FROM edges e\n JOIN reachable r ON e.source = r.node_id\n WHERE r.depth < 5 AND e.kind IN ('calls', 'imports', 'references')\n )\n SELECT DISTINCT n.name\n FROM reachable r\n JOIN nodes n ON n.id = r.node_id\n WHERE n.name IS NOT NULL`,\n [route.id],\n );\n\n const isAuthenticated = pathNodeNames.some(row => {\n const lowerName = (row.name ?? '').toLowerCase();\n return AUTH_PATTERNS.some(pattern => lowerName.includes(pattern));\n });\n\n // Step 5: Determine exposure level\n const routeName = (route.name ?? '').toLowerCase();\n let exposureLevel: AttackSurfaceEntry['exposureLevel'];\n\n if (INTERNAL_ROUTE_PATTERNS.some(p => routeName.includes(p))) {\n exposureLevel = 'internal';\n } else if (isAuthenticated) {\n exposureLevel = 'authenticated';\n } else if (PUBLIC_ROUTE_PATTERNS.some(p => routeName.includes(p))) {\n exposureLevel = 'public';\n } else {\n exposureLevel = 'unknown';\n }\n\n // Step 6: riskScore = max risk_score of reachable affected vulns, plus pattern bonus\n const affectedVulns = vulnerableDeps.filter(v => v.verdict === 'affected' || v.verdict === 'under_investigation');\n const baseRiskScore = affectedVulns.reduce((max, v) => {\n if (v.riskScore != null && v.riskScore > max) return v.riskScore;\n return max;\n }, 0);\n\n const patternBonus: Record<AttackSurfaceEntry['patternRiskLevel'], number> = {\n none: 0, low: 0.3, medium: 0.6, high: 0.8, critical: 1.0,\n };\n const riskScore = Math.min(10, baseRiskScore + (patternBonus[patternRiskLevel] ?? 0));\n\n entries.push({\n route: route.name ?? route.id,\n nodeId: route.id,\n filePath: route.file_path ?? '',\n isAuthenticated,\n exposureLevel,\n vulnerableDeps,\n patternMatches,\n patternRiskLevel,\n riskScore,\n });\n }\n\n // Compute summary stats\n const publicRoutes = entries.filter(e => e.exposureLevel === 'public').length;\n const authenticatedRoutes = entries.filter(\n e => e.exposureLevel === 'authenticated' || e.exposureLevel === 'internal',\n ).length;\n const routesWithVulns = entries.filter(e => e.vulnerableDeps.length > 0).length;\n\n // Critical paths: routes with affected/under_investigation vulns, sorted by riskScore desc\n const criticalPaths = entries\n .filter(e => e.vulnerableDeps.length > 0)\n .sort((a, b) => b.riskScore - a.riskScore);\n\n const allRoutes = entries.sort((a, b) => b.riskScore - a.riskScore);\n\n return {\n totalRoutes: entries.length,\n publicRoutes,\n authenticatedRoutes,\n routesWithVulns,\n criticalPaths,\n allRoutes,\n };\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Security Context Warnings
3
+ *
4
+ * Queries pre-computed reachability data to find vulnerabilities
5
+ * reachable from symbols included in a context response.
6
+ * Used by kirograph_context to append security warnings.
7
+ */
8
+ export interface SecurityWarning {
9
+ cveId: string;
10
+ severityScore: number | null;
11
+ epssScore: number | null;
12
+ epssPercentile: number | null;
13
+ packageName: string;
14
+ ecosystem: string;
15
+ fixedVersion: string | null;
16
+ entryPoints: string[];
17
+ }
18
+ /**
19
+ * Query the pre-computed reachability data to find vulnerabilities
20
+ * reachable from the given node IDs.
21
+ *
22
+ * This is a lightweight query joining sec_reachability + sec_vulnerabilities + sec_dependencies
23
+ * where the reachability paths include any of the context nodes. No graph traversal needed
24
+ * since reachability is pre-computed by the SecurityPipeline.
25
+ *
26
+ * @param rawDb - The raw SQLite database handle
27
+ * @param nodeIds - Node IDs from the context response (entry points + related symbols)
28
+ * @returns Array of SecurityWarning objects for affected vulnerabilities
29
+ */
30
+ export declare function getSecurityWarningsForNodes(rawDb: any, nodeIds: string[]): SecurityWarning[];
31
+ /**
32
+ * Format security warnings into a text section for the context output.
33
+ * Shows max 3 vulnerabilities with a note about remaining ones.
34
+ *
35
+ * @param warnings - Array of SecurityWarning objects
36
+ * @param nodeNames - Map of node IDs to human-readable names (for entry point display)
37
+ * @returns Formatted string section, or empty string if no warnings
38
+ */
39
+ export declare function formatSecurityWarnings(warnings: SecurityWarning[], nodeNames: Map<string, string>): string;
40
+ //# sourceMappingURL=context-warnings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-warnings.d.ts","sourceRoot":"","sources":["../../src/security/context-warnings.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,eAAe,EAAE,CA6F5F;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,eAAe,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAmC1G"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * KiroGraph SAST-lite: Dangerous Data Flow Detection
3
+ *
4
+ * Detects dangerous patterns by analysing call edges in the graph database.
5
+ * Uses symbol names and callee chains rather than full AST traversal.
6
+ */
7
+ import type { GraphDatabase } from '../db/database';
8
+ import type { OwaspCategory } from './owasp';
9
+ export interface DataFlowFinding {
10
+ type: 'sql-injection' | 'path-traversal' | 'xss' | 'dangerous-eval' | 'unsafe-deserialize' | 'hardcoded-crypto';
11
+ severity: 'critical' | 'high' | 'medium';
12
+ owaspCategory: OwaspCategory;
13
+ filePath: string;
14
+ line: number;
15
+ symbol: string;
16
+ description: string;
17
+ recommendation: string;
18
+ }
19
+ export declare class DataFlowAnalyzer {
20
+ private readonly db;
21
+ constructor(db: GraphDatabase);
22
+ analyze(): Promise<DataFlowFinding[]>;
23
+ private analyzeFromPatternMatches;
24
+ private _patternIdToType;
25
+ private _findEnclosingSymbol;
26
+ private _getRecommendation;
27
+ private _detectDangerousEval;
28
+ private _detectUnsafeDeserialize;
29
+ private _detectHardcodedCrypto;
30
+ private _detectSqlInjection;
31
+ private _detectPathTraversal;
32
+ }
33
+ //# sourceMappingURL=data-flows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-flows.d.ts","sourceRoot":"","sources":["../../src/security/data-flows.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAI7C,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,eAAe,GAAG,gBAAgB,GAAG,KAAK,GAAG,gBAAgB,GAAG,oBAAoB,GAAG,kBAAkB,CAAC;IAChH,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;IACzC,aAAa,EAAE,aAAa,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAyBD,qBAAa,gBAAgB;IACf,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,aAAa;IAExC,OAAO,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAwB3C,OAAO,CAAC,yBAAyB;IA8BjC,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,oBAAoB;IAQ5B,OAAO,CAAC,kBAAkB;IAc1B,OAAO,CAAC,oBAAoB;IAyB5B,OAAO,CAAC,wBAAwB;IA8BhC,OAAO,CAAC,sBAAsB;IA0C9B,OAAO,CAAC,mBAAmB;IAoE3B,OAAO,CAAC,oBAAoB;CA8C7B"}
@@ -21,19 +21,77 @@ __export(data_flows_exports, {
21
21
  DataFlowAnalyzer: () => DataFlowAnalyzer
22
22
  });
23
23
  module.exports = __toCommonJS(data_flows_exports);
24
+ function hasPatternsData(rawDb) {
25
+ try {
26
+ const result = rawDb.get("SELECT COUNT(*) as cnt FROM pattern_matches");
27
+ return (result?.cnt ?? 0) > 0;
28
+ } catch {
29
+ return false;
30
+ }
31
+ }
24
32
  class DataFlowAnalyzer {
25
33
  constructor(db) {
26
34
  this.db = db;
27
35
  }
28
36
  async analyze() {
29
37
  const rawDb = this.db.getRawDb();
30
- const findings = [];
31
- findings.push(...this._detectDangerousEval(rawDb));
32
- findings.push(...this._detectUnsafeDeserialize(rawDb));
33
- findings.push(...this._detectHardcodedCrypto(rawDb));
34
- findings.push(...this._detectSqlInjection(rawDb));
35
- findings.push(...this._detectPathTraversal(rawDb));
36
- return findings;
38
+ const sqlFindings = [
39
+ ...this._detectDangerousEval(rawDb),
40
+ ...this._detectUnsafeDeserialize(rawDb),
41
+ ...this._detectHardcodedCrypto(rawDb),
42
+ ...this._detectSqlInjection(rawDb),
43
+ ...this._detectPathTraversal(rawDb)
44
+ ];
45
+ if (hasPatternsData(rawDb)) {
46
+ const astFindings = this.analyzeFromPatternMatches(rawDb);
47
+ const astKeys = new Set(astFindings.map((f) => `${f.filePath}:${f.line}`));
48
+ const filteredSql = sqlFindings.filter((f) => !astKeys.has(`${f.filePath}:${f.line}`));
49
+ return [...astFindings, ...filteredSql];
50
+ }
51
+ return sqlFindings;
52
+ }
53
+ analyzeFromPatternMatches(rawDb) {
54
+ const rows = rawDb.all("SELECT file_path, pattern_id, line, col, match_text, severity, owasp_category, language FROM pattern_matches");
55
+ return rows.map((row) => {
56
+ const type = this._patternIdToType(row.pattern_id);
57
+ const symbol = this._findEnclosingSymbol(rawDb, row.file_path, row.line);
58
+ return {
59
+ type,
60
+ severity: row.severity,
61
+ owaspCategory: row.owasp_category,
62
+ filePath: row.file_path,
63
+ line: row.line,
64
+ symbol: symbol ?? row.pattern_id,
65
+ description: `[AST pattern: ${row.pattern_id}] ${row.match_text.slice(0, 100)}`,
66
+ recommendation: this._getRecommendation(type)
67
+ };
68
+ });
69
+ }
70
+ _patternIdToType(patternId) {
71
+ if (patternId.startsWith("sql-injection")) return "sql-injection";
72
+ if (patternId.startsWith("dangerous-eval") || patternId.startsWith("dangerous-exec")) return "dangerous-eval";
73
+ if (patternId.startsWith("path-traversal")) return "path-traversal";
74
+ if (patternId.startsWith("prototype-pollution")) return "unsafe-deserialize";
75
+ if (patternId.startsWith("weak-crypto")) return "hardcoded-crypto";
76
+ return "dangerous-eval";
77
+ }
78
+ _findEnclosingSymbol(rawDb, filePath, line) {
79
+ const row = rawDb.get(
80
+ `SELECT name FROM nodes WHERE file_path = ? AND start_line <= ? AND end_line >= ? AND kind IN ('function', 'method', 'class') ORDER BY (end_line - start_line) ASC LIMIT 1`,
81
+ [filePath, line, line]
82
+ );
83
+ return row?.name ?? null;
84
+ }
85
+ _getRecommendation(type) {
86
+ const recs = {
87
+ "sql-injection": "Use parameterized queries. Never concatenate user input into SQL strings.",
88
+ "dangerous-eval": "Remove eval()/exec(). Use structured alternatives.",
89
+ "path-traversal": "Use path.resolve() and verify result is within an allowed base directory.",
90
+ "unsafe-deserialize": "Validate object keys before merge. Avoid untrusted deserialization.",
91
+ "hardcoded-crypto": "Use SHA-256+ for hashing. Use bcrypt/argon2 for passwords.",
92
+ "xss": "Sanitize output. Use a trusted template engine with auto-escaping."
93
+ };
94
+ return recs[type] ?? "Review and fix this security issue.";
37
95
  }
38
96
  // ── Detection: dangerous eval / exec ────────────────────────────────────────
39
97
  _detectDangerousEval(rawDb) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/security/data-flows.ts"],
4
- "sourcesContent": ["/**\n * KiroGraph SAST-lite: Dangerous Data Flow Detection\n *\n * Detects dangerous patterns by analysing call edges in the graph database.\n * Uses symbol names and callee chains rather than full AST traversal.\n */\n\nimport type { GraphDatabase } from '../db/database';\nimport type { OwaspCategory } from './owasp';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface DataFlowFinding {\n type: 'sql-injection' | 'path-traversal' | 'xss' | 'dangerous-eval' | 'unsafe-deserialize' | 'hardcoded-crypto';\n severity: 'critical' | 'high' | 'medium';\n owaspCategory: OwaspCategory;\n filePath: string;\n line: number;\n symbol: string;\n description: string;\n recommendation: string;\n}\n\n// \u2500\u2500 Internal row type returned by the DB queries \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface CallEdgeRow {\n caller: string;\n file_path: string;\n start_line: number;\n callee: string;\n}\n\n// \u2500\u2500 DataFlowAnalyzer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class DataFlowAnalyzer {\n constructor(private readonly db: GraphDatabase) {}\n\n async analyze(): Promise<DataFlowFinding[]> {\n const rawDb = this.db.getRawDb();\n const findings: DataFlowFinding[] = [];\n\n findings.push(...this._detectDangerousEval(rawDb));\n findings.push(...this._detectUnsafeDeserialize(rawDb));\n findings.push(...this._detectHardcodedCrypto(rawDb));\n findings.push(...this._detectSqlInjection(rawDb));\n findings.push(...this._detectPathTraversal(rawDb));\n\n return findings;\n }\n\n // \u2500\u2500 Detection: dangerous eval / exec \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private _detectDangerousEval(rawDb: any): DataFlowFinding[] {\n const rows: CallEdgeRow[] = rawDb.all(`\n SELECT n.name as caller, n.file_path, n.start_line, n2.name as callee\n FROM edges e\n JOIN nodes n ON n.id = e.source\n JOIN nodes n2 ON n2.id = e.target\n WHERE e.kind = 'calls'\n AND n2.name IN ('eval', 'Function', 'execSync', 'exec', 'spawn', 'spawnSync', 'execFileSync', 'execFile')\n AND n.file_path != ''\n `);\n\n return rows.map((row) => ({\n type: 'dangerous-eval' as const,\n severity: 'critical' as const,\n owaspCategory: 'A03' as const,\n filePath: row.file_path,\n line: row.start_line,\n symbol: row.caller,\n description: `Function '${row.caller}' calls '${row.callee}', which can execute arbitrary code or OS commands.`,\n recommendation: `Avoid '${row.callee}'. Use structured APIs or allowlists for dynamic execution. Validate and sanitize all inputs.`,\n }));\n }\n\n // \u2500\u2500 Detection: unsafe deserialization \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private _detectUnsafeDeserialize(rawDb: any): DataFlowFinding[] {\n const rows: CallEdgeRow[] = rawDb.all(`\n SELECT n.name as caller, n.file_path, n.start_line, n2.name as callee\n FROM edges e\n JOIN nodes n ON n.id = e.source\n JOIN nodes n2 ON n2.id = e.target\n WHERE e.kind = 'calls'\n AND (\n n2.name IN ('unserialize', 'deserialize', 'fromJson', 'loads')\n OR n2.name LIKE '%pickle%'\n OR n2.name LIKE '%marshal%'\n OR n2.name = 'yaml.load'\n )\n AND n.file_path != ''\n `);\n\n return rows.map((row) => ({\n type: 'unsafe-deserialize' as const,\n severity: 'high' as const,\n owaspCategory: 'A08' as const,\n filePath: row.file_path,\n line: row.start_line,\n symbol: row.caller,\n description: `Function '${row.caller}' calls '${row.callee}', which may deserialize untrusted data unsafely.`,\n recommendation: `Validate data before deserialization. Use safe alternatives (e.g. yaml.safe_load, JSON schema validation). Never deserialize data from untrusted sources.`,\n }));\n }\n\n // \u2500\u2500 Detection: hardcoded weak crypto \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private _detectHardcodedCrypto(rawDb: any): DataFlowFinding[] {\n const rows: CallEdgeRow[] = rawDb.all(`\n SELECT n.name as caller, n.file_path, n.start_line, n2.name as callee\n FROM edges e\n JOIN nodes n ON n.id = e.source\n JOIN nodes n2 ON n2.id = e.target\n WHERE e.kind = 'calls'\n AND (\n n2.name LIKE '%md5%'\n OR n2.name LIKE '%sha1%'\n OR n2.name LIKE '%des%'\n OR n2.name LIKE '%rc4%'\n OR n2.name LIKE '%blowfish%'\n )\n AND (\n n.name LIKE '%crypto%'\n OR n.name LIKE '%hash%'\n OR n.name LIKE '%cipher%'\n OR n.name LIKE '%encrypt%'\n OR n.name LIKE '%digest%'\n OR n.file_path LIKE '%crypto%'\n OR n.file_path LIKE '%hash%'\n OR n.file_path LIKE '%cipher%'\n OR n.file_path LIKE '%auth%'\n )\n AND n.file_path != ''\n `);\n\n return rows.map((row) => ({\n type: 'hardcoded-crypto' as const,\n severity: 'medium' as const,\n owaspCategory: 'A02' as const,\n filePath: row.file_path,\n line: row.start_line,\n symbol: row.caller,\n description: `Function '${row.caller}' uses weak or deprecated cryptographic algorithm '${row.callee}'.`,\n recommendation: `Replace with a strong algorithm: SHA-256 or SHA-3 for hashing, AES-256-GCM for symmetric encryption. Avoid MD5 and SHA-1 for security purposes.`,\n }));\n }\n\n // \u2500\u2500 Detection: SQL injection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private _detectSqlInjection(rawDb: any): DataFlowFinding[] {\n // Find functions that:\n // (a) call a known DB query function\n // (b) AND whose name suggests user-input handling (controller/route/request context)\n const rows: CallEdgeRow[] = rawDb.all(`\n SELECT n.name as caller, n.file_path, n.start_line, n2.name as callee\n FROM edges e\n JOIN nodes n ON n.id = e.source\n JOIN nodes n2 ON n2.id = e.target\n WHERE e.kind = 'calls'\n AND n2.name IN ('query', 'execute', 'exec', 'raw', 'runQuery', 'executeQuery', 'runSql', 'executeSql')\n AND (\n n.name LIKE '%handle%'\n OR n.name LIKE '%controller%'\n OR n.name LIKE '%route%'\n OR n.name LIKE '%request%'\n OR n.name LIKE '%req%'\n OR n.name LIKE '%endpoint%'\n OR n.name LIKE '%action%'\n OR n.name LIKE '%handler%'\n )\n AND n.file_path != ''\n `);\n\n // Only report entries that do NOT also have a sanitize/escape call in the same scope\n const sanitizeCallers: Set<string> = new Set<string>(\n (rawDb.all(`\n SELECT DISTINCT n.id\n FROM edges e\n JOIN nodes n ON n.id = e.source\n JOIN nodes n2 ON n2.id = e.target\n WHERE e.kind = 'calls'\n AND (\n n2.name LIKE '%sanitize%'\n OR n2.name LIKE '%escape%'\n OR n2.name LIKE '%parameteriz%'\n OR n2.name LIKE '%prepared%'\n OR n2.name LIKE '%placeholder%'\n )\n `) as Array<{ id: string }>).map((r) => r.id),\n );\n\n // Cross-reference: look up caller node IDs to filter sanitized callers\n const callerIds: Map<string, string> = new Map(\n (rawDb.all(`\n SELECT id, name FROM nodes WHERE kind IN ('function', 'method', 'arrow_function')\n `) as Array<{ id: string; name: string }>).map((r) => [r.name, r.id]),\n );\n\n return rows\n .filter((row) => {\n const callerId = callerIds.get(row.caller);\n return !callerId || !sanitizeCallers.has(callerId);\n })\n .map((row) => ({\n type: 'sql-injection' as const,\n severity: 'critical' as const,\n owaspCategory: 'A03' as const,\n filePath: row.file_path,\n line: row.start_line,\n symbol: row.caller,\n description: `Controller/handler '${row.caller}' calls database function '${row.callee}' without apparent input sanitization.`,\n recommendation: `Use parameterized queries or prepared statements. Never concatenate user input into SQL strings. Consider an ORM with query builders.`,\n }));\n }\n\n // \u2500\u2500 Detection: path traversal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private _detectPathTraversal(rawDb: any): DataFlowFinding[] {\n // Find functions that call file I/O operations and look like they handle requests.\n // Exclusions:\n // - Internal analysis/infrastructure paths (mcp, resolution, security, extraction, graph, architecture)\n // - 'open' is excluded from file ops because KiroGraph.open() (DB) triggers false positives\n // - Class names ending in 'Handler' or 'Server' are excluded (too broad \u2014 use more specific patterns)\n const rows: CallEdgeRow[] = rawDb.all(`\n SELECT n.name as caller, n.file_path, n.start_line, n2.name as callee\n FROM edges e\n JOIN nodes n ON n.id = e.source\n JOIN nodes n2 ON n2.id = e.target\n WHERE e.kind = 'calls'\n AND n2.name IN ('readFile', 'readFileSync', 'writeFile', 'writeFileSync', 'createReadStream', 'createWriteStream', 'openSync', 'unlink', 'unlinkSync')\n AND (\n n.name LIKE '%controller%'\n OR n.name LIKE '%route%'\n OR n.name LIKE '%request%'\n OR n.name LIKE '%download%'\n OR n.name LIKE '%upload%'\n OR n.name LIKE '%get%file%'\n OR n.name LIKE '%fetch%file%'\n OR n.name LIKE '%serve%file%'\n OR n.name LIKE '%handle%file%'\n )\n AND n.file_path != ''\n AND n.file_path NOT LIKE '%/mcp/%'\n AND n.file_path NOT LIKE '%/resolution/%'\n AND n.file_path NOT LIKE '%/security/%'\n AND n.file_path NOT LIKE '%/extraction/%'\n AND n.file_path NOT LIKE '%/graph/%'\n AND n.file_path NOT LIKE '%/architecture/%'\n AND n.file_path NOT LIKE '%/frameworks/%'\n AND n.file_path NOT LIKE '%/bridges/%'\n `);\n\n return rows.map((row) => ({\n type: 'path-traversal' as const,\n severity: 'high' as const,\n owaspCategory: 'A01' as const,\n filePath: row.file_path,\n line: row.start_line,\n symbol: row.caller,\n description: `Handler '${row.caller}' calls file operation '${row.callee}'. Path may be influenced by user input, enabling directory traversal.`,\n recommendation: `Validate and normalize file paths. Use path.resolve() and verify the result is inside an allowed base directory. Reject paths containing '..'.`,\n }));\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * KiroGraph SAST-lite: Dangerous Data Flow Detection\n *\n * Detects dangerous patterns by analysing call edges in the graph database.\n * Uses symbol names and callee chains rather than full AST traversal.\n */\n\nimport type { GraphDatabase } from '../db/database';\nimport type { OwaspCategory } from './owasp';\n\n// \u2500\u2500 Types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport interface DataFlowFinding {\n type: 'sql-injection' | 'path-traversal' | 'xss' | 'dangerous-eval' | 'unsafe-deserialize' | 'hardcoded-crypto';\n severity: 'critical' | 'high' | 'medium';\n owaspCategory: OwaspCategory;\n filePath: string;\n line: number;\n symbol: string;\n description: string;\n recommendation: string;\n}\n\n// \u2500\u2500 Internal row type returned by the DB queries \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\ninterface CallEdgeRow {\n caller: string;\n file_path: string;\n start_line: number;\n callee: string;\n}\n\n// \u2500\u2500 hasPatternsData helper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction hasPatternsData(rawDb: any): boolean {\n try {\n const result = rawDb.get(\"SELECT COUNT(*) as cnt FROM pattern_matches\") as { cnt: number } | undefined;\n return (result?.cnt ?? 0) > 0;\n } catch {\n // Table doesn't exist (enablePatterns never ran)\n return false;\n }\n}\n\n// \u2500\u2500 DataFlowAnalyzer \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class DataFlowAnalyzer {\n constructor(private readonly db: GraphDatabase) {}\n\n async analyze(): Promise<DataFlowFinding[]> {\n const rawDb = (this.db as any).getRawDb();\n\n // Always run existing SQL heuristics (unchanged behavior)\n const sqlFindings = [\n ...this._detectDangerousEval(rawDb),\n ...this._detectUnsafeDeserialize(rawDb),\n ...this._detectHardcodedCrypto(rawDb),\n ...this._detectSqlInjection(rawDb),\n ...this._detectPathTraversal(rawDb),\n ];\n\n // When pattern_matches has data, merge AST findings (more precise)\n if (hasPatternsData(rawDb)) {\n const astFindings = this.analyzeFromPatternMatches(rawDb);\n // Deduplicate: AST entry wins over SQL entry at same (filePath, line)\n const astKeys = new Set(astFindings.map(f => `${f.filePath}:${f.line}`));\n const filteredSql = sqlFindings.filter(f => !astKeys.has(`${f.filePath}:${f.line}`));\n return [...astFindings, ...filteredSql];\n }\n\n return sqlFindings;\n }\n\n private analyzeFromPatternMatches(rawDb: any): DataFlowFinding[] {\n const rows: Array<{\n file_path: string;\n pattern_id: string;\n line: number;\n col: number;\n match_text: string;\n severity: string;\n owasp_category: string;\n language: string;\n }> = rawDb.all('SELECT file_path, pattern_id, line, col, match_text, severity, owasp_category, language FROM pattern_matches');\n\n return rows.map(row => {\n // Map pattern_id prefix to DataFlowFinding type\n const type = this._patternIdToType(row.pattern_id);\n // Look up nearest enclosing symbol\n const symbol = this._findEnclosingSymbol(rawDb, row.file_path, row.line);\n return {\n type,\n severity: row.severity as DataFlowFinding['severity'],\n owaspCategory: row.owasp_category as DataFlowFinding['owaspCategory'],\n filePath: row.file_path,\n line: row.line,\n symbol: symbol ?? row.pattern_id,\n description: `[AST pattern: ${row.pattern_id}] ${row.match_text.slice(0, 100)}`,\n recommendation: this._getRecommendation(type),\n };\n });\n }\n\n private _patternIdToType(patternId: string): DataFlowFinding['type'] {\n if (patternId.startsWith('sql-injection')) return 'sql-injection';\n if (patternId.startsWith('dangerous-eval') || patternId.startsWith('dangerous-exec')) return 'dangerous-eval';\n if (patternId.startsWith('path-traversal')) return 'path-traversal';\n if (patternId.startsWith('prototype-pollution')) return 'unsafe-deserialize';\n if (patternId.startsWith('weak-crypto')) return 'hardcoded-crypto';\n return 'dangerous-eval'; // fallback\n }\n\n private _findEnclosingSymbol(rawDb: any, filePath: string, line: number): string | null {\n const row = rawDb.get(\n `SELECT name FROM nodes WHERE file_path = ? AND start_line <= ? AND end_line >= ? AND kind IN ('function', 'method', 'class') ORDER BY (end_line - start_line) ASC LIMIT 1`,\n [filePath, line, line]\n ) as { name: string } | undefined;\n return row?.name ?? null;\n }\n\n private _getRecommendation(type: DataFlowFinding['type']): string {\n const recs: Record<DataFlowFinding['type'], string> = {\n 'sql-injection': 'Use parameterized queries. Never concatenate user input into SQL strings.',\n 'dangerous-eval': 'Remove eval()/exec(). Use structured alternatives.',\n 'path-traversal': 'Use path.resolve() and verify result is within an allowed base directory.',\n 'unsafe-deserialize': 'Validate object keys before merge. Avoid untrusted deserialization.',\n 'hardcoded-crypto': 'Use SHA-256+ for hashing. Use bcrypt/argon2 for passwords.',\n 'xss': 'Sanitize output. Use a trusted template engine with auto-escaping.',\n };\n return recs[type] ?? 'Review and fix this security issue.';\n }\n\n // \u2500\u2500 Detection: dangerous eval / exec \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private _detectDangerousEval(rawDb: any): DataFlowFinding[] {\n const rows: CallEdgeRow[] = rawDb.all(`\n SELECT n.name as caller, n.file_path, n.start_line, n2.name as callee\n FROM edges e\n JOIN nodes n ON n.id = e.source\n JOIN nodes n2 ON n2.id = e.target\n WHERE e.kind = 'calls'\n AND n2.name IN ('eval', 'Function', 'execSync', 'exec', 'spawn', 'spawnSync', 'execFileSync', 'execFile')\n AND n.file_path != ''\n `);\n\n return rows.map((row) => ({\n type: 'dangerous-eval' as const,\n severity: 'critical' as const,\n owaspCategory: 'A03' as const,\n filePath: row.file_path,\n line: row.start_line,\n symbol: row.caller,\n description: `Function '${row.caller}' calls '${row.callee}', which can execute arbitrary code or OS commands.`,\n recommendation: `Avoid '${row.callee}'. Use structured APIs or allowlists for dynamic execution. Validate and sanitize all inputs.`,\n }));\n }\n\n // \u2500\u2500 Detection: unsafe deserialization \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private _detectUnsafeDeserialize(rawDb: any): DataFlowFinding[] {\n const rows: CallEdgeRow[] = rawDb.all(`\n SELECT n.name as caller, n.file_path, n.start_line, n2.name as callee\n FROM edges e\n JOIN nodes n ON n.id = e.source\n JOIN nodes n2 ON n2.id = e.target\n WHERE e.kind = 'calls'\n AND (\n n2.name IN ('unserialize', 'deserialize', 'fromJson', 'loads')\n OR n2.name LIKE '%pickle%'\n OR n2.name LIKE '%marshal%'\n OR n2.name = 'yaml.load'\n )\n AND n.file_path != ''\n `);\n\n return rows.map((row) => ({\n type: 'unsafe-deserialize' as const,\n severity: 'high' as const,\n owaspCategory: 'A08' as const,\n filePath: row.file_path,\n line: row.start_line,\n symbol: row.caller,\n description: `Function '${row.caller}' calls '${row.callee}', which may deserialize untrusted data unsafely.`,\n recommendation: `Validate data before deserialization. Use safe alternatives (e.g. yaml.safe_load, JSON schema validation). Never deserialize data from untrusted sources.`,\n }));\n }\n\n // \u2500\u2500 Detection: hardcoded weak crypto \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private _detectHardcodedCrypto(rawDb: any): DataFlowFinding[] {\n const rows: CallEdgeRow[] = rawDb.all(`\n SELECT n.name as caller, n.file_path, n.start_line, n2.name as callee\n FROM edges e\n JOIN nodes n ON n.id = e.source\n JOIN nodes n2 ON n2.id = e.target\n WHERE e.kind = 'calls'\n AND (\n n2.name LIKE '%md5%'\n OR n2.name LIKE '%sha1%'\n OR n2.name LIKE '%des%'\n OR n2.name LIKE '%rc4%'\n OR n2.name LIKE '%blowfish%'\n )\n AND (\n n.name LIKE '%crypto%'\n OR n.name LIKE '%hash%'\n OR n.name LIKE '%cipher%'\n OR n.name LIKE '%encrypt%'\n OR n.name LIKE '%digest%'\n OR n.file_path LIKE '%crypto%'\n OR n.file_path LIKE '%hash%'\n OR n.file_path LIKE '%cipher%'\n OR n.file_path LIKE '%auth%'\n )\n AND n.file_path != ''\n `);\n\n return rows.map((row) => ({\n type: 'hardcoded-crypto' as const,\n severity: 'medium' as const,\n owaspCategory: 'A02' as const,\n filePath: row.file_path,\n line: row.start_line,\n symbol: row.caller,\n description: `Function '${row.caller}' uses weak or deprecated cryptographic algorithm '${row.callee}'.`,\n recommendation: `Replace with a strong algorithm: SHA-256 or SHA-3 for hashing, AES-256-GCM for symmetric encryption. Avoid MD5 and SHA-1 for security purposes.`,\n }));\n }\n\n // \u2500\u2500 Detection: SQL injection \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private _detectSqlInjection(rawDb: any): DataFlowFinding[] {\n // Find functions that:\n // (a) call a known DB query function\n // (b) AND whose name suggests user-input handling (controller/route/request context)\n const rows: CallEdgeRow[] = rawDb.all(`\n SELECT n.name as caller, n.file_path, n.start_line, n2.name as callee\n FROM edges e\n JOIN nodes n ON n.id = e.source\n JOIN nodes n2 ON n2.id = e.target\n WHERE e.kind = 'calls'\n AND n2.name IN ('query', 'execute', 'exec', 'raw', 'runQuery', 'executeQuery', 'runSql', 'executeSql')\n AND (\n n.name LIKE '%handle%'\n OR n.name LIKE '%controller%'\n OR n.name LIKE '%route%'\n OR n.name LIKE '%request%'\n OR n.name LIKE '%req%'\n OR n.name LIKE '%endpoint%'\n OR n.name LIKE '%action%'\n OR n.name LIKE '%handler%'\n )\n AND n.file_path != ''\n `);\n\n // Only report entries that do NOT also have a sanitize/escape call in the same scope\n const sanitizeCallers: Set<string> = new Set<string>(\n (rawDb.all(`\n SELECT DISTINCT n.id\n FROM edges e\n JOIN nodes n ON n.id = e.source\n JOIN nodes n2 ON n2.id = e.target\n WHERE e.kind = 'calls'\n AND (\n n2.name LIKE '%sanitize%'\n OR n2.name LIKE '%escape%'\n OR n2.name LIKE '%parameteriz%'\n OR n2.name LIKE '%prepared%'\n OR n2.name LIKE '%placeholder%'\n )\n `) as Array<{ id: string }>).map((r) => r.id),\n );\n\n // Cross-reference: look up caller node IDs to filter sanitized callers\n const callerIds: Map<string, string> = new Map(\n (rawDb.all(`\n SELECT id, name FROM nodes WHERE kind IN ('function', 'method', 'arrow_function')\n `) as Array<{ id: string; name: string }>).map((r) => [r.name, r.id]),\n );\n\n return rows\n .filter((row) => {\n const callerId = callerIds.get(row.caller);\n return !callerId || !sanitizeCallers.has(callerId);\n })\n .map((row) => ({\n type: 'sql-injection' as const,\n severity: 'critical' as const,\n owaspCategory: 'A03' as const,\n filePath: row.file_path,\n line: row.start_line,\n symbol: row.caller,\n description: `Controller/handler '${row.caller}' calls database function '${row.callee}' without apparent input sanitization.`,\n recommendation: `Use parameterized queries or prepared statements. Never concatenate user input into SQL strings. Consider an ORM with query builders.`,\n }));\n }\n\n // \u2500\u2500 Detection: path traversal \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n private _detectPathTraversal(rawDb: any): DataFlowFinding[] {\n // Find functions that call file I/O operations and look like they handle requests.\n // Exclusions:\n // - Internal analysis/infrastructure paths (mcp, resolution, security, extraction, graph, architecture)\n // - 'open' is excluded from file ops because KiroGraph.open() (DB) triggers false positives\n // - Class names ending in 'Handler' or 'Server' are excluded (too broad \u2014 use more specific patterns)\n const rows: CallEdgeRow[] = rawDb.all(`\n SELECT n.name as caller, n.file_path, n.start_line, n2.name as callee\n FROM edges e\n JOIN nodes n ON n.id = e.source\n JOIN nodes n2 ON n2.id = e.target\n WHERE e.kind = 'calls'\n AND n2.name IN ('readFile', 'readFileSync', 'writeFile', 'writeFileSync', 'createReadStream', 'createWriteStream', 'openSync', 'unlink', 'unlinkSync')\n AND (\n n.name LIKE '%controller%'\n OR n.name LIKE '%route%'\n OR n.name LIKE '%request%'\n OR n.name LIKE '%download%'\n OR n.name LIKE '%upload%'\n OR n.name LIKE '%get%file%'\n OR n.name LIKE '%fetch%file%'\n OR n.name LIKE '%serve%file%'\n OR n.name LIKE '%handle%file%'\n )\n AND n.file_path != ''\n AND n.file_path NOT LIKE '%/mcp/%'\n AND n.file_path NOT LIKE '%/resolution/%'\n AND n.file_path NOT LIKE '%/security/%'\n AND n.file_path NOT LIKE '%/extraction/%'\n AND n.file_path NOT LIKE '%/graph/%'\n AND n.file_path NOT LIKE '%/architecture/%'\n AND n.file_path NOT LIKE '%/frameworks/%'\n AND n.file_path NOT LIKE '%/bridges/%'\n `);\n\n return rows.map((row) => ({\n type: 'path-traversal' as const,\n severity: 'high' as const,\n owaspCategory: 'A01' as const,\n filePath: row.file_path,\n line: row.start_line,\n symbol: row.caller,\n description: `Handler '${row.caller}' calls file operation '${row.callee}'. Path may be influenced by user input, enabling directory traversal.`,\n recommendation: `Validate and normalize file paths. Use path.resolve() and verify the result is inside an allowed base directory. Reject paths containing '..'.`,\n }));\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Dependency Confusion Checker
3
+ *
4
+ * Detects internal packages whose names exist in public registries
5
+ * (a supply chain attack vector), and flags typosquatting candidates.
6
+ */
7
+ import type { GraphDatabase } from '../db/database';
8
+ export interface DepConfusionFinding {
9
+ packageName: string;
10
+ ecosystem: string;
11
+ internalSource: string;
12
+ publicExists: boolean;
13
+ publicVersion: string | null;
14
+ publicPublishedAt: string | null;
15
+ riskLevel: 'critical' | 'high' | 'medium';
16
+ explanation: string;
17
+ }
18
+ export declare class DepConfusionChecker {
19
+ private readonly db;
20
+ constructor(db: GraphDatabase);
21
+ check(): Promise<DepConfusionFinding[]>;
22
+ }
23
+ //# sourceMappingURL=dep-confusion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dep-confusion.d.ts","sourceRoot":"","sources":["../../src/security/dep-confusion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAIpD,MAAM,WAAW,mBAAmB;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC;CACrB;AAoKD,qBAAa,mBAAmB;IAClB,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,aAAa;IAExC,KAAK,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;CA0G9C"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * KiroGraph-Sec Error Classes
3
+ *
4
+ * Security-specific error types extending the base KiroGraphError.
5
+ */
6
+ import { KiroGraphError } from '../errors';
7
+ export declare class SecurityError extends KiroGraphError {
8
+ constructor(message: string, context?: Record<string, unknown>);
9
+ }
10
+ export declare class ManifestParseError extends KiroGraphError {
11
+ constructor(message: string, filePath: string, line?: number);
12
+ }
13
+ export declare class VulnDatabaseError extends KiroGraphError {
14
+ constructor(message: string, database: string, httpStatus?: number);
15
+ }
16
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/security/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,qBAAa,aAAc,SAAQ,cAAc;gBACnC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAI/D;AAED,qBAAa,kBAAmB,SAAQ,cAAc;gBACxC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;CAI7D;AAED,qBAAa,iBAAkB,SAAQ,cAAc;gBACvC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAInE"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Fix Suggestion Builder
3
+ *
4
+ * Generates ecosystem-appropriate upgrade commands for vulnerabilities
5
+ * that have a known fixed version. Reusable by CLI and MCP tools.
6
+ */
7
+ /**
8
+ * Build an ecosystem-appropriate fix suggestion command.
9
+ *
10
+ * @param ecosystem - The package ecosystem (npm, maven, go, pypi, cargo)
11
+ * @param packageName - The package name (for maven: groupId:artifactId)
12
+ * @param fixedVersion - The version that fixes the vulnerability
13
+ * @returns A formatted fix command string, or empty string if ecosystem is unknown
14
+ */
15
+ export declare function buildFixSuggestion(ecosystem: string, packageName: string, fixedVersion: string): string;
16
+ /**
17
+ * Format a fix suggestion line for display.
18
+ * Returns the formatted line with the 💡 prefix, or empty string if no fixed version.
19
+ */
20
+ export declare function formatFixSuggestion(ecosystem: string, packageName: string, fixedVersion: string | null | undefined): string;
21
+ //# sourceMappingURL=fix-suggestions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fix-suggestions.d.ts","sourceRoot":"","sources":["../../../src/security/export/fix-suggestions.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAuBvG;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAI3H"}