@zivis/mcp 0.1.8 → 0.1.10

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 (330) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +19 -0
  3. package/dist/api-client.d.ts +2 -24
  4. package/dist/api-client.js +32 -52
  5. package/dist/auth/index.d.ts +1 -22
  6. package/dist/auth/index.js +17 -38
  7. package/dist/auth/jwt.d.ts +0 -16
  8. package/dist/auth/jwt.js +0 -13
  9. package/dist/auth/keychain.d.ts +6 -32
  10. package/dist/auth/keychain.js +83 -114
  11. package/dist/auth/oauth.d.ts +3 -32
  12. package/dist/auth/oauth.js +67 -61
  13. package/dist/auth/sessions.d.ts +5 -25
  14. package/dist/auth/sessions.js +20 -39
  15. package/dist/auth/token-refresh.d.ts +2 -22
  16. package/dist/auth/token-refresh.js +33 -36
  17. package/dist/cli.d.ts +1 -18
  18. package/dist/cli.js +30 -908
  19. package/dist/index.d.ts +0 -6
  20. package/dist/index.js +0 -7
  21. package/dist/lib/inspect-cache.d.ts +10 -0
  22. package/dist/lib/inspect-cache.js +75 -0
  23. package/dist/lib/next-steps.d.ts +27 -0
  24. package/dist/lib/next-steps.js +21 -0
  25. package/dist/matcher/ast-eval.d.ts +8 -0
  26. package/dist/matcher/ast-eval.js +95 -0
  27. package/dist/matcher/finding.d.ts +55 -0
  28. package/dist/matcher/finding.js +1 -0
  29. package/dist/matcher/index.d.ts +8 -0
  30. package/dist/matcher/index.js +202 -0
  31. package/dist/matcher/inference-candidates.d.ts +26 -0
  32. package/dist/matcher/inference-candidates.js +81 -0
  33. package/dist/matcher/walker.d.ts +7 -0
  34. package/dist/matcher/walker.js +71 -0
  35. package/dist/pattern-pack/index.d.ts +125 -0
  36. package/dist/pattern-pack/index.js +189 -0
  37. package/dist/pattern-packs/zivis-public-0.2.0/capsules/agents/privilege-separation.yaml +224 -0
  38. package/dist/pattern-packs/zivis-public-0.2.0/capsules/prompting/self-consistency-no-isolation.yaml +237 -0
  39. package/dist/pattern-packs/zivis-public-0.2.0/capsules/retrieval/context-injection-no-validator.yaml +348 -0
  40. package/dist/pattern-packs/zivis-public-0.2.0/capsules/security/late-org-filter.yaml +266 -0
  41. package/dist/pattern-packs/zivis-public-0.2.0/controls/external_validator_on_facts.yaml +37 -0
  42. package/dist/pattern-packs/zivis-public-0.2.0/controls/fact_validator_present.yaml +68 -0
  43. package/dist/pattern-packs/zivis-public-0.2.0/controls/human_approval_gate.yaml +44 -0
  44. package/dist/pattern-packs/zivis-public-0.2.0/controls/langgraph_state_machine_with_per_node_tools.yaml +35 -0
  45. package/dist/pattern-packs/zivis-public-0.2.0/controls/per_sample_retrieval_diversification.yaml +38 -0
  46. package/dist/pattern-packs/zivis-public-0.2.0/controls/prisma_extension_or_middleware_attaching_org_filter.yaml +31 -0
  47. package/dist/pattern-packs/zivis-public-0.2.0/controls/row_level_security_policy.yaml +37 -0
  48. package/dist/pattern-packs/zivis-public-0.2.0/controls/source_attribution_present.yaml +58 -0
  49. package/dist/pattern-packs/zivis-public-0.2.0/manifest.json +167 -0
  50. package/dist/pattern-packs/zivis-public-0.2.0/prompts/agents/privilege-separation/identify.md +54 -0
  51. package/dist/pattern-packs/zivis-public-0.2.0/prompts/prompting/self-consistency-no-isolation/identify.md +60 -0
  52. package/dist/pattern-packs/zivis-public-0.2.0/prompts/retrieval/context-injection-no-validator/identify.md +109 -0
  53. package/dist/pattern-packs/zivis-public-0.2.0/prompts/security/late-org-filter/identify.md +78 -0
  54. package/dist/project-binding.d.ts +2 -19
  55. package/dist/project-binding.js +38 -21
  56. package/dist/prompts/audit-dependencies.d.ts +2 -0
  57. package/dist/prompts/audit-dependencies.js +47 -0
  58. package/dist/prompts/getting-started.d.ts +2 -0
  59. package/dist/prompts/getting-started.js +37 -0
  60. package/dist/prompts/index.d.ts +2 -0
  61. package/dist/prompts/index.js +6 -0
  62. package/dist/resolve-application-id.d.ts +0 -4
  63. package/dist/resolve-application-id.js +0 -5
  64. package/dist/sanitize.d.ts +1 -21
  65. package/dist/sanitize.js +7 -41
  66. package/dist/server.d.ts +1 -13
  67. package/dist/server.js +142 -265
  68. package/dist/tools/artifacts.d.ts +76 -0
  69. package/dist/tools/artifacts.js +178 -0
  70. package/dist/tools/check-project.d.ts +5 -18
  71. package/dist/tools/check-project.js +122 -110
  72. package/dist/tools/check-repo-trust.d.ts +4 -19
  73. package/dist/tools/check-repo-trust.js +56 -47
  74. package/dist/tools/create-diagram.d.ts +0 -5
  75. package/dist/tools/create-diagram.js +0 -10
  76. package/dist/tools/create-document.d.ts +0 -5
  77. package/dist/tools/create-document.js +3 -9
  78. package/dist/tools/create-finding.d.ts +85 -0
  79. package/dist/tools/create-finding.js +136 -0
  80. package/dist/tools/delete-finding.d.ts +19 -0
  81. package/dist/tools/delete-finding.js +36 -0
  82. package/dist/tools/devx-run.d.ts +88 -0
  83. package/dist/tools/devx-run.js +175 -0
  84. package/dist/tools/discover-local-infra.d.ts +0 -10
  85. package/dist/tools/discover-local-infra.js +3 -73
  86. package/dist/tools/enterprise/get-org-zat.d.ts +0 -5
  87. package/dist/tools/enterprise/get-org-zat.js +0 -6
  88. package/dist/tools/explain-signal-for-diff.d.ts +34 -0
  89. package/dist/tools/explain-signal-for-diff.js +75 -0
  90. package/dist/tools/generate-diagram.d.ts +0 -6
  91. package/dist/tools/generate-diagram.js +21 -13
  92. package/dist/tools/get-application-overview.d.ts +0 -5
  93. package/dist/tools/get-application-overview.js +0 -6
  94. package/dist/tools/get-application.d.ts +0 -5
  95. package/dist/tools/get-application.js +0 -6
  96. package/dist/tools/get-diagram.d.ts +0 -5
  97. package/dist/tools/get-diagram.js +1 -11
  98. package/dist/tools/get-document.d.ts +0 -5
  99. package/dist/tools/get-document.js +0 -6
  100. package/dist/tools/get-oss-zat.d.ts +0 -5
  101. package/dist/tools/get-oss-zat.js +0 -7
  102. package/dist/tools/get-signal.d.ts +24 -0
  103. package/dist/tools/get-signal.js +75 -0
  104. package/dist/tools/get-started.d.ts +18 -0
  105. package/dist/tools/get-started.js +470 -0
  106. package/dist/tools/get-trust-keys.d.ts +0 -5
  107. package/dist/tools/get-trust-keys.js +0 -6
  108. package/dist/tools/import-openapi-endpoints.d.ts +0 -5
  109. package/dist/tools/import-openapi-endpoints.js +0 -6
  110. package/dist/tools/inspect-zat.d.ts +0 -5
  111. package/dist/tools/inspect-zat.js +0 -19
  112. package/dist/tools/inspect.d.ts +21 -0
  113. package/dist/tools/inspect.js +222 -0
  114. package/dist/tools/list-applications.d.ts +1 -6
  115. package/dist/tools/list-applications.js +0 -6
  116. package/dist/tools/list-diagrams.d.ts +0 -5
  117. package/dist/tools/list-diagrams.js +0 -6
  118. package/dist/tools/list-documents.d.ts +0 -5
  119. package/dist/tools/list-documents.js +0 -6
  120. package/dist/tools/list-endpoints.d.ts +1 -6
  121. package/dist/tools/list-endpoints.js +0 -6
  122. package/dist/tools/list-signals.d.ts +37 -0
  123. package/dist/tools/list-signals.js +83 -0
  124. package/dist/tools/manage-application.d.ts +64 -0
  125. package/dist/tools/manage-application.js +129 -0
  126. package/dist/tools/manage-diagram.d.ts +0 -5
  127. package/dist/tools/manage-diagram.js +0 -16
  128. package/dist/tools/manage-endpoint-lifecycle.d.ts +80 -0
  129. package/dist/tools/manage-endpoint-lifecycle.js +180 -0
  130. package/dist/tools/open-in-ide.d.ts +2 -14
  131. package/dist/tools/open-in-ide.js +0 -13
  132. package/dist/tools/review-change.d.ts +34 -0
  133. package/dist/tools/review-change.js +93 -0
  134. package/dist/tools/security-memory.d.ts +76 -0
  135. package/dist/tools/security-memory.js +202 -0
  136. package/dist/tools/security-review.d.ts +1 -21
  137. package/dist/tools/security-review.js +8 -108
  138. package/dist/tools/threat-get-capsule.d.ts +15 -0
  139. package/dist/tools/threat-get-capsule.js +53 -0
  140. package/dist/tools/threat-get-inference-prompt.d.ts +15 -0
  141. package/dist/tools/threat-get-inference-prompt.js +73 -0
  142. package/dist/tools/threat-list-relevant-capsules.d.ts +17 -0
  143. package/dist/tools/threat-list-relevant-capsules.js +158 -0
  144. package/dist/tools/threat-run-matcher.d.ts +17 -0
  145. package/dist/tools/threat-run-matcher.js +145 -0
  146. package/dist/tools/update-document.d.ts +0 -5
  147. package/dist/tools/update-document.js +3 -9
  148. package/dist/tools/update-endpoint.d.ts +1 -6
  149. package/dist/tools/update-endpoint.js +0 -7
  150. package/dist/tools/update-finding.d.ts +61 -0
  151. package/dist/tools/update-finding.js +80 -0
  152. package/dist/tools/update-mermaid-source.d.ts +0 -13
  153. package/dist/tools/update-mermaid-source.js +0 -14
  154. package/dist/tools/verify-trust-mark.d.ts +0 -5
  155. package/dist/tools/verify-trust-mark.js +0 -6
  156. package/dist/types.d.ts +14 -14
  157. package/dist/types.js +22 -28
  158. package/package.json +38 -15
  159. package/dist/api-client.js.map +0 -1
  160. package/dist/auth/index.js.map +0 -1
  161. package/dist/auth/jwt.js.map +0 -1
  162. package/dist/auth/keychain.js.map +0 -1
  163. package/dist/auth/oauth.js.map +0 -1
  164. package/dist/auth/sessions.js.map +0 -1
  165. package/dist/auth/token-refresh.js.map +0 -1
  166. package/dist/cli.js.map +0 -1
  167. package/dist/index.js.map +0 -1
  168. package/dist/project-binding.js.map +0 -1
  169. package/dist/resolve-application-id.js.map +0 -1
  170. package/dist/sanitize.js.map +0 -1
  171. package/dist/server.js.map +0 -1
  172. package/dist/tools/check-project.js.map +0 -1
  173. package/dist/tools/check-repo-trust.js.map +0 -1
  174. package/dist/tools/create-diagram.js.map +0 -1
  175. package/dist/tools/create-document.js.map +0 -1
  176. package/dist/tools/discover-local-infra.js.map +0 -1
  177. package/dist/tools/enterprise/capture-evidence.d.ts +0 -54
  178. package/dist/tools/enterprise/capture-evidence.js +0 -72
  179. package/dist/tools/enterprise/capture-evidence.js.map +0 -1
  180. package/dist/tools/enterprise/create-report-ticket.d.ts +0 -34
  181. package/dist/tools/enterprise/create-report-ticket.js +0 -44
  182. package/dist/tools/enterprise/create-report-ticket.js.map +0 -1
  183. package/dist/tools/enterprise/end-pentest-session.d.ts +0 -33
  184. package/dist/tools/enterprise/end-pentest-session.js +0 -42
  185. package/dist/tools/enterprise/end-pentest-session.js.map +0 -1
  186. package/dist/tools/enterprise/generate-report.d.ts +0 -55
  187. package/dist/tools/enterprise/generate-report.js +0 -111
  188. package/dist/tools/enterprise/generate-report.js.map +0 -1
  189. package/dist/tools/enterprise/get-org-zat.js.map +0 -1
  190. package/dist/tools/enterprise/get-report-status.d.ts +0 -27
  191. package/dist/tools/enterprise/get-report-status.js +0 -38
  192. package/dist/tools/enterprise/get-report-status.js.map +0 -1
  193. package/dist/tools/enterprise/get-threat-model.d.ts +0 -29
  194. package/dist/tools/enterprise/get-threat-model.js +0 -83
  195. package/dist/tools/enterprise/get-threat-model.js.map +0 -1
  196. package/dist/tools/enterprise/list-agents.d.ts +0 -42
  197. package/dist/tools/enterprise/list-agents.js +0 -95
  198. package/dist/tools/enterprise/list-agents.js.map +0 -1
  199. package/dist/tools/enterprise/list-report-issues.d.ts +0 -36
  200. package/dist/tools/enterprise/list-report-issues.js +0 -50
  201. package/dist/tools/enterprise/list-report-issues.js.map +0 -1
  202. package/dist/tools/enterprise/list-threat-models.d.ts +0 -36
  203. package/dist/tools/enterprise/list-threat-models.js +0 -82
  204. package/dist/tools/enterprise/list-threat-models.js.map +0 -1
  205. package/dist/tools/enterprise/manage-actor.d.ts +0 -58
  206. package/dist/tools/enterprise/manage-actor.js +0 -99
  207. package/dist/tools/enterprise/manage-actor.js.map +0 -1
  208. package/dist/tools/enterprise/manage-attack-scenario.d.ts +0 -70
  209. package/dist/tools/enterprise/manage-attack-scenario.js +0 -89
  210. package/dist/tools/enterprise/manage-attack-scenario.js.map +0 -1
  211. package/dist/tools/enterprise/manage-component.d.ts +0 -58
  212. package/dist/tools/enterprise/manage-component.js +0 -90
  213. package/dist/tools/enterprise/manage-component.js.map +0 -1
  214. package/dist/tools/enterprise/manage-data-asset.d.ts +0 -53
  215. package/dist/tools/enterprise/manage-data-asset.js +0 -90
  216. package/dist/tools/enterprise/manage-data-asset.js.map +0 -1
  217. package/dist/tools/enterprise/manage-data-flow.d.ts +0 -57
  218. package/dist/tools/enterprise/manage-data-flow.js +0 -98
  219. package/dist/tools/enterprise/manage-data-flow.js.map +0 -1
  220. package/dist/tools/enterprise/manage-finding.d.ts +0 -69
  221. package/dist/tools/enterprise/manage-finding.js +0 -106
  222. package/dist/tools/enterprise/manage-finding.js.map +0 -1
  223. package/dist/tools/enterprise/manage-security-control.d.ts +0 -59
  224. package/dist/tools/enterprise/manage-security-control.js +0 -96
  225. package/dist/tools/enterprise/manage-security-control.js.map +0 -1
  226. package/dist/tools/enterprise/manage-test-case.d.ts +0 -88
  227. package/dist/tools/enterprise/manage-test-case.js +0 -119
  228. package/dist/tools/enterprise/manage-test-case.js.map +0 -1
  229. package/dist/tools/enterprise/promote-finding-to-issue.d.ts +0 -36
  230. package/dist/tools/enterprise/promote-finding-to-issue.js +0 -65
  231. package/dist/tools/enterprise/promote-finding-to-issue.js.map +0 -1
  232. package/dist/tools/enterprise/publish-report-version.d.ts +0 -34
  233. package/dist/tools/enterprise/publish-report-version.js +0 -75
  234. package/dist/tools/enterprise/publish-report-version.js.map +0 -1
  235. package/dist/tools/enterprise/publish-test-to-library.d.ts +0 -31
  236. package/dist/tools/enterprise/publish-test-to-library.js +0 -40
  237. package/dist/tools/enterprise/publish-test-to-library.js.map +0 -1
  238. package/dist/tools/enterprise/record-test-result.d.ts +0 -67
  239. package/dist/tools/enterprise/record-test-result.js +0 -75
  240. package/dist/tools/enterprise/record-test-result.js.map +0 -1
  241. package/dist/tools/enterprise/start-pentest-session.d.ts +0 -35
  242. package/dist/tools/enterprise/start-pentest-session.js +0 -50
  243. package/dist/tools/enterprise/start-pentest-session.js.map +0 -1
  244. package/dist/tools/enterprise/sync-report-section.d.ts +0 -41
  245. package/dist/tools/enterprise/sync-report-section.js +0 -79
  246. package/dist/tools/enterprise/sync-report-section.js.map +0 -1
  247. package/dist/tools/enterprise/update-report-issue.d.ts +0 -55
  248. package/dist/tools/enterprise/update-report-issue.js +0 -69
  249. package/dist/tools/enterprise/update-report-issue.js.map +0 -1
  250. package/dist/tools/generate-diagram.js.map +0 -1
  251. package/dist/tools/get-agent-test-results.d.ts +0 -41
  252. package/dist/tools/get-agent-test-results.js +0 -86
  253. package/dist/tools/get-agent-test-results.js.map +0 -1
  254. package/dist/tools/get-application-overview.js.map +0 -1
  255. package/dist/tools/get-application.js.map +0 -1
  256. package/dist/tools/get-artifact-content.d.ts +0 -29
  257. package/dist/tools/get-artifact-content.js +0 -86
  258. package/dist/tools/get-artifact-content.js.map +0 -1
  259. package/dist/tools/get-diagram.js.map +0 -1
  260. package/dist/tools/get-document.js.map +0 -1
  261. package/dist/tools/get-finding-details.d.ts +0 -28
  262. package/dist/tools/get-finding-details.js +0 -43
  263. package/dist/tools/get-finding-details.js.map +0 -1
  264. package/dist/tools/get-findings.d.ts +0 -57
  265. package/dist/tools/get-findings.js +0 -103
  266. package/dist/tools/get-findings.js.map +0 -1
  267. package/dist/tools/get-oss-zat.js.map +0 -1
  268. package/dist/tools/get-recon-scan.d.ts +0 -27
  269. package/dist/tools/get-recon-scan.js +0 -46
  270. package/dist/tools/get-recon-scan.js.map +0 -1
  271. package/dist/tools/get-scan-output.d.ts +0 -27
  272. package/dist/tools/get-scan-output.js +0 -64
  273. package/dist/tools/get-scan-output.js.map +0 -1
  274. package/dist/tools/get-scenario-details.d.ts +0 -27
  275. package/dist/tools/get-scenario-details.js +0 -46
  276. package/dist/tools/get-scenario-details.js.map +0 -1
  277. package/dist/tools/get-test-case-results.d.ts +0 -37
  278. package/dist/tools/get-test-case-results.js +0 -66
  279. package/dist/tools/get-test-case-results.js.map +0 -1
  280. package/dist/tools/get-test-details.d.ts +0 -29
  281. package/dist/tools/get-test-details.js +0 -49
  282. package/dist/tools/get-test-details.js.map +0 -1
  283. package/dist/tools/get-trust-keys.js.map +0 -1
  284. package/dist/tools/import-openapi-endpoints.js.map +0 -1
  285. package/dist/tools/inspect-zat.js.map +0 -1
  286. package/dist/tools/list-agent-test-cases.d.ts +0 -41
  287. package/dist/tools/list-agent-test-cases.js +0 -73
  288. package/dist/tools/list-agent-test-cases.js.map +0 -1
  289. package/dist/tools/list-applications.js.map +0 -1
  290. package/dist/tools/list-diagrams.js.map +0 -1
  291. package/dist/tools/list-documents.js.map +0 -1
  292. package/dist/tools/list-endpoints.js.map +0 -1
  293. package/dist/tools/list-recon-scans.d.ts +0 -36
  294. package/dist/tools/list-recon-scans.js +0 -74
  295. package/dist/tools/list-recon-scans.js.map +0 -1
  296. package/dist/tools/list-scan-artifacts.d.ts +0 -41
  297. package/dist/tools/list-scan-artifacts.js +0 -63
  298. package/dist/tools/list-scan-artifacts.js.map +0 -1
  299. package/dist/tools/list-scans.d.ts +0 -44
  300. package/dist/tools/list-scans.js +0 -91
  301. package/dist/tools/list-scans.js.map +0 -1
  302. package/dist/tools/list-test-library.d.ts +0 -44
  303. package/dist/tools/list-test-library.js +0 -83
  304. package/dist/tools/list-test-library.js.map +0 -1
  305. package/dist/tools/list-test-scenarios.d.ts +0 -31
  306. package/dist/tools/list-test-scenarios.js +0 -66
  307. package/dist/tools/list-test-scenarios.js.map +0 -1
  308. package/dist/tools/local-scan.d.ts +0 -40
  309. package/dist/tools/local-scan.js +0 -261
  310. package/dist/tools/local-scan.js.map +0 -1
  311. package/dist/tools/manage-diagram.js.map +0 -1
  312. package/dist/tools/open-in-ide.js.map +0 -1
  313. package/dist/tools/run-test-scenario.d.ts +0 -37
  314. package/dist/tools/run-test-scenario.js +0 -70
  315. package/dist/tools/run-test-scenario.js.map +0 -1
  316. package/dist/tools/scan-pr.d.ts +0 -27
  317. package/dist/tools/scan-pr.js +0 -51
  318. package/dist/tools/scan-pr.js.map +0 -1
  319. package/dist/tools/security-review.js.map +0 -1
  320. package/dist/tools/setup-red-team-target.d.ts +0 -79
  321. package/dist/tools/setup-red-team-target.js +0 -430
  322. package/dist/tools/setup-red-team-target.js.map +0 -1
  323. package/dist/tools/triage-finding.d.ts +0 -47
  324. package/dist/tools/triage-finding.js +0 -116
  325. package/dist/tools/triage-finding.js.map +0 -1
  326. package/dist/tools/update-document.js.map +0 -1
  327. package/dist/tools/update-endpoint.js.map +0 -1
  328. package/dist/tools/update-mermaid-source.js.map +0 -1
  329. package/dist/tools/verify-trust-mark.js.map +0 -1
  330. package/dist/types.js.map +0 -1
@@ -0,0 +1,71 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as path from "node:path";
3
+ const HARD_SKIP_DIRS = new Set([
4
+ "node_modules",
5
+ ".git",
6
+ ".yarn",
7
+ ".pnpm",
8
+ "dist",
9
+ "build",
10
+ "out",
11
+ ".next",
12
+ ".nuxt",
13
+ ".turbo",
14
+ ".cache",
15
+ "coverage",
16
+ "vendor",
17
+ "__pycache__",
18
+ ".venv",
19
+ "target",
20
+ ]);
21
+ const MAX_FILES = 50_000;
22
+ const LANG_EXTENSIONS = {
23
+ typescript: [".ts", ".tsx"],
24
+ javascript: [".js", ".jsx", ".mjs", ".cjs"],
25
+ python: [".py"],
26
+ go: [".go"],
27
+ };
28
+ export async function walkLanguageFiles(rootDir, languages) {
29
+ const extToLang = new Map();
30
+ for (const lang of languages) {
31
+ for (const ext of LANG_EXTENSIONS[lang])
32
+ extToLang.set(ext, lang);
33
+ }
34
+ const filesByLanguage = new Map();
35
+ for (const lang of languages)
36
+ filesByLanguage.set(lang, []);
37
+ let filesScanned = 0;
38
+ let filesSkipped = 0;
39
+ const total = () => Array.from(filesByLanguage.values()).reduce((n, l) => n + l.length, 0);
40
+ async function visit(dirAbs) {
41
+ if (total() >= MAX_FILES)
42
+ return;
43
+ let entries;
44
+ try {
45
+ entries = await fs.readdir(dirAbs, { withFileTypes: true });
46
+ }
47
+ catch {
48
+ return;
49
+ }
50
+ for (const entry of entries) {
51
+ if (entry.isDirectory()) {
52
+ if (HARD_SKIP_DIRS.has(entry.name) || entry.name.startsWith(".")) {
53
+ filesSkipped++;
54
+ continue;
55
+ }
56
+ await visit(path.join(dirAbs, entry.name));
57
+ continue;
58
+ }
59
+ if (!entry.isFile() && !entry.isSymbolicLink())
60
+ continue;
61
+ filesScanned++;
62
+ const ext = path.extname(entry.name).toLowerCase();
63
+ const lang = extToLang.get(ext);
64
+ if (lang) {
65
+ filesByLanguage.get(lang).push(path.join(dirAbs, entry.name));
66
+ }
67
+ }
68
+ }
69
+ await visit(rootDir);
70
+ return { filesByLanguage, filesScanned, filesSkipped };
71
+ }
@@ -0,0 +1,125 @@
1
+ export interface PackManifest {
2
+ schema_version: "1.0.0";
3
+ pack_id: string;
4
+ pack_name: string;
5
+ version: string;
6
+ built_at: string;
7
+ tier: "public_teaser" | "public" | "customer_safe";
8
+ description?: string;
9
+ capsules: ManifestCapsuleEntry[];
10
+ prompts: ManifestPromptEntry[];
11
+ controls?: ManifestControlEntry[];
12
+ }
13
+ export interface ManifestCapsuleEntry {
14
+ id: string;
15
+ version: string;
16
+ path: string;
17
+ sha256: string;
18
+ category?: string;
19
+ lifecycle?: string;
20
+ applicable_languages?: string[];
21
+ }
22
+ export interface ManifestPromptEntry {
23
+ path: string;
24
+ sha256: string;
25
+ capsule_id?: string;
26
+ }
27
+ export interface ManifestControlEntry {
28
+ id: string;
29
+ path: string;
30
+ sha256: string;
31
+ applicable_languages?: string[];
32
+ }
33
+ export interface ControlDetectionRule {
34
+ language: "typescript" | "javascript" | "python" | "go";
35
+ rule: unknown;
36
+ }
37
+ export interface Control {
38
+ id: string;
39
+ description?: string;
40
+ applicable_languages: string[];
41
+ detection: ControlDetectionRule[];
42
+ lifecycle?: string;
43
+ owner?: string;
44
+ }
45
+ export interface RelevanceTerm {
46
+ dependency?: string;
47
+ direct_only?: boolean;
48
+ language?: string;
49
+ framework?: string;
50
+ evidence?: string;
51
+ }
52
+ export interface RelevanceFilter {
53
+ any_of?: RelevanceTerm[];
54
+ all_of?: RelevanceTerm[];
55
+ none_of?: RelevanceTerm[];
56
+ }
57
+ export interface Capsule {
58
+ id: string;
59
+ slug: string;
60
+ version: string;
61
+ category: string;
62
+ title?: string;
63
+ headline?: string;
64
+ description?: string;
65
+ detection_tier: "public" | "proprietary";
66
+ scoring_tier: "public" | "proprietary";
67
+ applicable_languages: string[];
68
+ relevance_filter?: RelevanceFilter;
69
+ strategies: unknown[];
70
+ required_evidence_count: number;
71
+ threats?: unknown[];
72
+ lifecycle: "draft" | "active" | "deprecated";
73
+ sensitivity_level?: "public_teaser" | "customer_safe" | "zivis_confidential";
74
+ safe_summary?: string;
75
+ detect_when?: string;
76
+ risk_hints?: string[];
77
+ architectural_signals?: string[];
78
+ model_task_prompt_ref?: string;
79
+ expected_output_schema?: unknown;
80
+ minimum_context_required?: {
81
+ lines?: number;
82
+ symbols?: string[];
83
+ };
84
+ related_patterns?: string[];
85
+ repair_contract?: {
86
+ allowed?: string[];
87
+ forbidden?: string[];
88
+ };
89
+ validation_contract?: {
90
+ requires_tests_pass?: boolean;
91
+ requires_static_rules?: string[];
92
+ };
93
+ }
94
+ export interface PackHandle {
95
+ manifest: PackManifest;
96
+ rootDir: string;
97
+ }
98
+ export interface GraphArtifactView {
99
+ scope: {
100
+ languages?: string[];
101
+ };
102
+ nodes: Array<{
103
+ type: string;
104
+ evidence: Array<{
105
+ kind: string;
106
+ }>;
107
+ attributes?: {
108
+ package?: string;
109
+ };
110
+ }>;
111
+ }
112
+ export declare function loadActivePack(packId?: string): Promise<PackHandle>;
113
+ export declare function getCapsule(handle: PackHandle, capsuleId: string): Promise<Capsule>;
114
+ export declare function getInferencePrompt(handle: PackHandle, ref: string): Promise<string>;
115
+ export declare function listCapsuleIds(handle: PackHandle): Promise<string[]>;
116
+ export declare function listControlIds(handle: PackHandle): Promise<string[]>;
117
+ export declare function getControl(handle: PackHandle, controlId: string): Promise<Control>;
118
+ export declare function findRelevantCapsules(handle: PackHandle, artifact: GraphArtifactView): Promise<Capsule[]>;
119
+ interface EvalContext {
120
+ packageNames: Set<string>;
121
+ languages: Set<string>;
122
+ evidenceKinds: Set<string>;
123
+ }
124
+ export declare function matchesRelevance(cap: Capsule, ctx: EvalContext): boolean;
125
+ export {};
@@ -0,0 +1,189 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as fssync from "node:fs";
3
+ import * as os from "node:os";
4
+ import * as path from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import * as crypto from "node:crypto";
7
+ import * as yaml from "js-yaml";
8
+ function userCacheRoot() {
9
+ const home = os.homedir();
10
+ if (process.platform === "darwin") {
11
+ return path.join(home, "Library", "Caches", "zivis");
12
+ }
13
+ if (process.platform === "win32") {
14
+ const localAppData = process.env.LOCALAPPDATA ?? path.join(home, "AppData", "Local");
15
+ return path.join(localAppData, "zivis", "Cache");
16
+ }
17
+ const xdg = process.env.XDG_CACHE_HOME;
18
+ return path.join(xdg ?? path.join(home, ".cache"), "zivis");
19
+ }
20
+ function userPackRoot() {
21
+ return path.join(userCacheRoot(), "pattern-packs");
22
+ }
23
+ function bundledPackRoot() {
24
+ const here = path.dirname(fileURLToPath(import.meta.url));
25
+ return path.resolve(here, "../pattern-packs");
26
+ }
27
+ const DEFAULT_PACK_ID = "zivis-public";
28
+ export async function loadActivePack(packId = DEFAULT_PACK_ID) {
29
+ if (process.env.ZIVIS_PACK_DIR) {
30
+ return readManifest(process.env.ZIVIS_PACK_DIR);
31
+ }
32
+ const cached = await findCachedPack(packId);
33
+ if (cached) {
34
+ return readManifest(cached);
35
+ }
36
+ const bundledDir = await findBundledPack(packId);
37
+ if (!bundledDir) {
38
+ throw new Error(`No pattern pack found. Looked in user cache (${userPackRoot()}) and bundled location (${bundledPackRoot()}). ` +
39
+ `Set ZIVIS_PACK_DIR to override.`);
40
+ }
41
+ const handle = await readManifest(bundledDir);
42
+ const cacheDir = path.join(userPackRoot(), `${handle.manifest.pack_id}-${handle.manifest.version}`);
43
+ await copyDir(bundledDir, cacheDir);
44
+ return { manifest: handle.manifest, rootDir: cacheDir };
45
+ }
46
+ async function findCachedPack(packId) {
47
+ const root = userPackRoot();
48
+ if (!fssync.existsSync(root))
49
+ return undefined;
50
+ const entries = await fs.readdir(root, { withFileTypes: true });
51
+ const candidates = entries
52
+ .filter((e) => e.isDirectory() && e.name.startsWith(`${packId}-`))
53
+ .map((e) => e.name)
54
+ .sort()
55
+ .reverse();
56
+ for (const name of candidates) {
57
+ const dir = path.join(root, name);
58
+ if (fssync.existsSync(path.join(dir, "manifest.json"))) {
59
+ return dir;
60
+ }
61
+ }
62
+ return undefined;
63
+ }
64
+ async function findBundledPack(packId) {
65
+ const root = bundledPackRoot();
66
+ if (!fssync.existsSync(root))
67
+ return undefined;
68
+ const entries = await fs.readdir(root, { withFileTypes: true });
69
+ const matches = entries
70
+ .filter((e) => e.isDirectory() && e.name.startsWith(`${packId}-`))
71
+ .map((e) => path.join(root, e.name))
72
+ .sort()
73
+ .reverse();
74
+ return matches[0];
75
+ }
76
+ async function readManifest(rootDir) {
77
+ const manifestPath = path.join(rootDir, "manifest.json");
78
+ const raw = await fs.readFile(manifestPath, "utf8");
79
+ const manifest = JSON.parse(raw);
80
+ return { manifest, rootDir };
81
+ }
82
+ async function copyDir(src, dst) {
83
+ await fs.mkdir(dst, { recursive: true });
84
+ const entries = await fs.readdir(src, { withFileTypes: true });
85
+ await Promise.all(entries.map(async (entry) => {
86
+ const s = path.join(src, entry.name);
87
+ const d = path.join(dst, entry.name);
88
+ if (entry.isDirectory())
89
+ await copyDir(s, d);
90
+ else if (entry.isFile())
91
+ await fs.copyFile(s, d);
92
+ }));
93
+ }
94
+ export async function getCapsule(handle, capsuleId) {
95
+ const entry = handle.manifest.capsules.find((c) => c.id === capsuleId);
96
+ if (!entry)
97
+ throw new Error(`Capsule not found in pack: ${capsuleId}`);
98
+ const fullPath = path.join(handle.rootDir, entry.path);
99
+ const raw = await fs.readFile(fullPath, "utf8");
100
+ await verifySha256(raw, entry.sha256, entry.path);
101
+ return yaml.load(raw);
102
+ }
103
+ export async function getInferencePrompt(handle, ref) {
104
+ const entry = handle.manifest.prompts.find((p) => p.path === ref);
105
+ if (!entry)
106
+ throw new Error(`Prompt not found in pack: ${ref}`);
107
+ const fullPath = path.join(handle.rootDir, ref);
108
+ const raw = await fs.readFile(fullPath, "utf8");
109
+ await verifySha256(raw, entry.sha256, ref);
110
+ return raw;
111
+ }
112
+ async function verifySha256(content, expected, label) {
113
+ const actual = crypto.createHash("sha256").update(content).digest("hex");
114
+ if (actual !== expected) {
115
+ throw new Error(`Pack integrity check failed for ${label}: expected ${expected.slice(0, 12)}…, got ${actual.slice(0, 12)}…`);
116
+ }
117
+ }
118
+ export async function listCapsuleIds(handle) {
119
+ return handle.manifest.capsules.map((c) => c.id);
120
+ }
121
+ export async function listControlIds(handle) {
122
+ return (handle.manifest.controls ?? []).map((c) => c.id);
123
+ }
124
+ export async function getControl(handle, controlId) {
125
+ const entry = (handle.manifest.controls ?? []).find((c) => c.id === controlId);
126
+ if (!entry)
127
+ throw new Error(`Control not found in pack: ${controlId}`);
128
+ const fullPath = path.join(handle.rootDir, entry.path);
129
+ const raw = await fs.readFile(fullPath, "utf8");
130
+ await verifySha256(raw, entry.sha256, entry.path);
131
+ return yaml.load(raw);
132
+ }
133
+ export async function findRelevantCapsules(handle, artifact) {
134
+ const out = [];
135
+ const ctx = buildEvalContext(artifact);
136
+ for (const entry of handle.manifest.capsules) {
137
+ const cap = await getCapsule(handle, entry.id);
138
+ if (matchesRelevance(cap, ctx))
139
+ out.push(cap);
140
+ }
141
+ return out;
142
+ }
143
+ function buildEvalContext(artifact) {
144
+ const packageNames = new Set();
145
+ for (const node of artifact.nodes) {
146
+ if (node.type === "external_dependency" && node.attributes?.package) {
147
+ packageNames.add(node.attributes.package);
148
+ }
149
+ }
150
+ const languages = new Set(artifact.scope.languages ?? []);
151
+ const evidenceKinds = new Set();
152
+ for (const node of artifact.nodes) {
153
+ for (const ev of node.evidence)
154
+ evidenceKinds.add(ev.kind);
155
+ }
156
+ return { packageNames, languages, evidenceKinds };
157
+ }
158
+ export function matchesRelevance(cap, ctx) {
159
+ if (cap.applicable_languages.length > 0) {
160
+ const hit = cap.applicable_languages.some((l) => l === "cross" || ctx.languages.has(l));
161
+ if (!hit)
162
+ return false;
163
+ }
164
+ const f = cap.relevance_filter;
165
+ if (!f)
166
+ return true;
167
+ if (f.any_of && f.any_of.length > 0) {
168
+ if (!f.any_of.some((t) => evalTerm(t, ctx)))
169
+ return false;
170
+ }
171
+ if (f.all_of && f.all_of.length > 0) {
172
+ if (!f.all_of.every((t) => evalTerm(t, ctx)))
173
+ return false;
174
+ }
175
+ if (f.none_of && f.none_of.length > 0) {
176
+ if (f.none_of.some((t) => evalTerm(t, ctx)))
177
+ return false;
178
+ }
179
+ return true;
180
+ }
181
+ function evalTerm(term, ctx) {
182
+ if (term.dependency !== undefined)
183
+ return ctx.packageNames.has(term.dependency);
184
+ if (term.language !== undefined)
185
+ return ctx.languages.has(term.language);
186
+ if (term.evidence !== undefined)
187
+ return ctx.evidenceKinds.has(term.evidence);
188
+ return false;
189
+ }
@@ -0,0 +1,224 @@
1
+ # Detection Card: Privilege Separation (absent)
2
+ # Spec: docs/specs/PATTERN-MATCHING-LIBRARY-V1.md
3
+ # Schema: schemas/pattern-detection-card.schema.json
4
+
5
+ id: agents.privilege-separation
6
+ slug: privilege-separation
7
+ version: 0.1.0
8
+ category: agents
9
+ title: Privilege Separation
10
+ headline: Per-Subtask Capability Scoping
11
+ description: >
12
+ Detects agentic codebases where multiple agents share a single tool/capability
13
+ set without per-agent scoping. Absence of privilege separation means one
14
+ compromised agent inherits the full capability surface of the system.
15
+ detection_tier: public
16
+ scoring_tier: proprietary
17
+
18
+ applicable_languages:
19
+ - typescript
20
+ - javascript
21
+ - python
22
+
23
+ # Don't run this pattern unless an agent framework is actually present.
24
+ # Mirrors nuclei-style relevance gating to keep the noise floor low.
25
+ relevance_filter:
26
+ any_of:
27
+ - dependency: "langgraph"
28
+ direct_only: true
29
+ - dependency: "langchain"
30
+ direct_only: true
31
+ - dependency: "@langchain/langgraph"
32
+ direct_only: true
33
+ - dependency: "crewai"
34
+ direct_only: true
35
+ - dependency: "llama-index"
36
+ direct_only: true
37
+ - dependency: "openai-agents"
38
+ direct_only: true
39
+ - dependency: "autogen-agentchat"
40
+ direct_only: true
41
+
42
+ strategies:
43
+ # 1. AST: Find tool list assignments (Python — LangChain/LangGraph idiom).
44
+ - code: AST
45
+ language: python
46
+ expression: |
47
+ rule:
48
+ kind: assignment
49
+ pattern: $TOOLS = [$$$]
50
+ has:
51
+ stopBy: end
52
+ any:
53
+ - pattern: create_react_agent
54
+ - pattern: bind_tools
55
+ - pattern: AgentExecutor
56
+ evidence_fields: [file_path, line_span, symbol]
57
+ confidence_weight: 0.25
58
+
59
+ # 2. AST: TypeScript/JavaScript equivalent.
60
+ - code: AST
61
+ language: typescript
62
+ expression: |
63
+ rule:
64
+ any:
65
+ - pattern: const $TOOLS = [$$$]
66
+ - pattern: bindTools($$$)
67
+ - pattern: createReactAgent($$$)
68
+ evidence_fields: [file_path, line_span, symbol]
69
+ confidence_weight: 0.25
70
+
71
+ # 3. GRAPH: Two or more agent declarations share the same tool set.
72
+ # Predicate evaluated against extractor output (components/edges).
73
+ - code: GRAPH
74
+ expression: |
75
+ count(distinct agent_declaration) >= 2
76
+ AND any_pair(agents, lambda a, b: a.tool_set == b.tool_set)
77
+ evidence_fields: [graph_path, file_spans, node_ids]
78
+ confidence_weight: 0.35
79
+
80
+ # 4. META: Absence of per-agent capability scope OR explicit authz layer.
81
+ - code: META
82
+ expression:
83
+ none_of_controls:
84
+ - langgraph_state_machine_with_per_node_tools
85
+ evidence_fields: [missing_controls]
86
+ confidence_weight: 0.30
87
+
88
+ # 5. INFER: Last-resort semantic check; never alone proves a finding.
89
+ - code: INFER
90
+ expression: "prompt_id:agents.privilege-separation.identify"
91
+ evidence_fields: [llm_rationale]
92
+ confidence_weight: 0.15
93
+ trusted: false
94
+
95
+ required_evidence_count: 3
96
+
97
+ # Presence of any of these controls downgrades or eliminates the finding.
98
+ control_negations:
99
+ - "presence_of(per_agent_tool_filter)"
100
+ - "presence_of(capability_token_check)"
101
+ - "presence_of(langgraph_state_machine_with_per_node_tools)"
102
+
103
+ threats:
104
+ - title: Compromised planner inherits executor capabilities
105
+ stride: [tampering, elevation_of_privilege]
106
+ description: >
107
+ A prompt-injection compromise of any agent escalates to the full set of
108
+ tools available to all agents in the system, including high-impact tools
109
+ like code execution, email, or file write.
110
+ remediation: >
111
+ Bind only the minimum tools required to each agent. In LangGraph, define
112
+ tools per node rather than globally. Add a capability token or
113
+ authorization layer that validates tool dispatch against agent identity.
114
+ - title: Lateral compromise via shared tool registry
115
+ stride: [elevation_of_privilege, information_disclosure]
116
+ description: >
117
+ Any tool callable from one agent is callable from every agent. There is
118
+ no blast-radius reduction even if one agent is otherwise constrained.
119
+
120
+ fixtures:
121
+ positive:
122
+ - "fixtures/positive/privilege-separation/langgraph_shared_tools_python"
123
+ - "fixtures/positive/privilege-separation/langchain_shared_tools_typescript"
124
+ negative:
125
+ - "fixtures/negative/privilege-separation/langgraph_per_node_tools"
126
+ - "fixtures/negative/privilege-separation/non_agentic_repo"
127
+
128
+ lifecycle: draft
129
+ owner: platform-threat-modeling
130
+ tags:
131
+ - agentic-ai
132
+ - least-privilege
133
+ - blast-radius
134
+
135
+ # Capsule fields — added in Phase 2A so the pack builder can ship this card
136
+ # as a runnable customer-safe capsule (deterministic strategies + inference prompt).
137
+ sensitivity_level: customer_safe
138
+ allowed_execution_modes:
139
+ - local_only
140
+ - local_model
141
+ - hybrid_cloud_eval
142
+
143
+ safe_summary: >
144
+ Multi-agent systems often share a single tool registry across agents. When that
145
+ happens, a prompt-injection compromise of any one agent inherits the full
146
+ capability surface of the system — including high-impact tools like code
147
+ execution, email, or filesystem write. Privilege separation means each agent
148
+ is bound only to the minimum tools required for its role.
149
+
150
+ detect_when: >
151
+ Two or more agent declarations are wired to the same tool list, or a single
152
+ shared tool array is referenced by every agent factory call, with no per-agent
153
+ capability scoping or authorization layer between agent and tool dispatch.
154
+
155
+ risk_hints:
156
+ - Any tool callable from one agent becomes callable from every agent
157
+ - Compromise of the weakest-prompted agent escalates to the most-privileged tool
158
+ - LangGraph's per-node tool binding is the idiomatic fix; AgentExecutor with a flat tool list is the anti-pattern
159
+
160
+ architectural_signals:
161
+ - Shared TOOLS array reused across multiple agent constructors
162
+ - No capability_token / authorization_layer between planner and tool dispatch
163
+ - LangGraph used without per-node tool binding
164
+
165
+ model_task_prompt_ref: prompts/agents/privilege-separation/identify.md
166
+
167
+ expected_output_schema:
168
+ type: object
169
+ required: [verdict, rationale, evidence_spans]
170
+ properties:
171
+ verdict:
172
+ type: string
173
+ enum: [present, absent, unclear]
174
+ description: present = privilege separation IS implemented; absent = the anti-pattern fires; unclear = needs human review
175
+ confidence:
176
+ type: number
177
+ minimum: 0
178
+ maximum: 1
179
+ rationale:
180
+ type: string
181
+ description: One paragraph, cites specific code constructs.
182
+ evidence_spans:
183
+ type: array
184
+ items:
185
+ type: object
186
+ required: [file]
187
+ properties:
188
+ file: { type: string }
189
+ start_line: { type: integer }
190
+ end_line: { type: integer }
191
+ note: { type: string }
192
+
193
+ minimum_context_required:
194
+ lines: 120
195
+ symbols:
196
+ - bind_tools
197
+ - bindTools
198
+ - create_react_agent
199
+ - createReactAgent
200
+ - AgentExecutor
201
+
202
+ related_patterns:
203
+ - agents.goal-decomposition-attack-surface
204
+ - agents.tool-call-without-authorization
205
+
206
+ repair_contract:
207
+ allowed:
208
+ - Bind a per-agent tool subset at construction time
209
+ - Introduce a capability-token or authorization layer between agent and tool dispatch
210
+ - Migrate to LangGraph state machines with per-node tools
211
+ forbidden:
212
+ - Removing tools entirely without functional replacement
213
+ - Centralizing tools further (the opposite direction)
214
+ - Disabling agent execution to "fix" the finding
215
+
216
+ validation_contract:
217
+ requires_tests_pass: false
218
+ requires_static_rules:
219
+ - no_shared_tool_registry_after_patch
220
+
221
+ unsafe_to_expose_fields:
222
+ - internal_rubric
223
+ - golden_transcripts
224
+ - exploit_templates