@zivis/mcp 0.1.0-alpha.9 → 0.1.6
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.
- package/LICENSE +201 -0
- package/README.md +19 -0
- package/dist/api-client.d.ts +1 -31
- package/dist/api-client.js +26 -66
- package/dist/auth/index.d.ts +1 -22
- package/dist/auth/index.js +15 -46
- package/dist/auth/jwt.d.ts +0 -16
- package/dist/auth/jwt.js +0 -13
- package/dist/auth/keychain.d.ts +6 -32
- package/dist/auth/keychain.js +83 -114
- package/dist/auth/oauth.d.ts +1 -42
- package/dist/auth/oauth.js +22 -64
- package/dist/auth/sessions.d.ts +5 -25
- package/dist/auth/sessions.js +20 -39
- package/dist/auth/token-refresh.d.ts +2 -22
- package/dist/auth/token-refresh.js +12 -47
- package/dist/cli.d.ts +1 -18
- package/dist/cli.js +30 -908
- package/dist/index.d.ts +0 -6
- package/dist/index.js +0 -7
- package/dist/lib/inspect-cache.d.ts +10 -0
- package/dist/lib/inspect-cache.js +75 -0
- package/dist/lib/next-steps.d.ts +27 -0
- package/dist/lib/next-steps.js +21 -0
- package/dist/matcher/ast-eval.d.ts +8 -0
- package/dist/matcher/ast-eval.js +95 -0
- package/dist/matcher/finding.d.ts +55 -0
- package/dist/matcher/finding.js +1 -0
- package/dist/matcher/index.d.ts +8 -0
- package/dist/matcher/index.js +202 -0
- package/dist/matcher/inference-candidates.d.ts +26 -0
- package/dist/matcher/inference-candidates.js +81 -0
- package/dist/matcher/walker.d.ts +7 -0
- package/dist/matcher/walker.js +71 -0
- package/dist/pattern-pack/index.d.ts +125 -0
- package/dist/pattern-pack/index.js +189 -0
- package/dist/pattern-packs/zivis-public-0.2.0/capsules/agents/privilege-separation.yaml +224 -0
- package/dist/pattern-packs/zivis-public-0.2.0/capsules/prompting/self-consistency-no-isolation.yaml +237 -0
- package/dist/pattern-packs/zivis-public-0.2.0/capsules/retrieval/context-injection-no-validator.yaml +348 -0
- package/dist/pattern-packs/zivis-public-0.2.0/capsules/security/late-org-filter.yaml +266 -0
- package/dist/pattern-packs/zivis-public-0.2.0/controls/external_validator_on_facts.yaml +37 -0
- package/dist/pattern-packs/zivis-public-0.2.0/controls/fact_validator_present.yaml +68 -0
- package/dist/pattern-packs/zivis-public-0.2.0/controls/human_approval_gate.yaml +44 -0
- package/dist/pattern-packs/zivis-public-0.2.0/controls/langgraph_state_machine_with_per_node_tools.yaml +35 -0
- package/dist/pattern-packs/zivis-public-0.2.0/controls/per_sample_retrieval_diversification.yaml +38 -0
- package/dist/pattern-packs/zivis-public-0.2.0/controls/prisma_extension_or_middleware_attaching_org_filter.yaml +31 -0
- package/dist/pattern-packs/zivis-public-0.2.0/controls/row_level_security_policy.yaml +37 -0
- package/dist/pattern-packs/zivis-public-0.2.0/controls/source_attribution_present.yaml +58 -0
- package/dist/pattern-packs/zivis-public-0.2.0/manifest.json +167 -0
- package/dist/pattern-packs/zivis-public-0.2.0/prompts/agents/privilege-separation/identify.md +54 -0
- package/dist/pattern-packs/zivis-public-0.2.0/prompts/prompting/self-consistency-no-isolation/identify.md +60 -0
- package/dist/pattern-packs/zivis-public-0.2.0/prompts/retrieval/context-injection-no-validator/identify.md +109 -0
- package/dist/pattern-packs/zivis-public-0.2.0/prompts/security/late-org-filter/identify.md +78 -0
- package/dist/project-binding.d.ts +2 -19
- package/dist/project-binding.js +38 -21
- package/dist/prompts/audit-dependencies.d.ts +2 -0
- package/dist/prompts/audit-dependencies.js +47 -0
- package/dist/prompts/getting-started.d.ts +2 -0
- package/dist/prompts/getting-started.js +37 -0
- package/dist/prompts/index.d.ts +2 -0
- package/dist/prompts/index.js +6 -0
- package/dist/resolve-application-id.d.ts +0 -4
- package/dist/resolve-application-id.js +0 -5
- package/dist/sanitize.d.ts +1 -21
- package/dist/sanitize.js +7 -41
- package/dist/server.d.ts +1 -13
- package/dist/server.js +134 -253
- package/dist/tools/artifacts.d.ts +76 -0
- package/dist/tools/artifacts.js +178 -0
- package/dist/tools/check-project.d.ts +5 -18
- package/dist/tools/check-project.js +120 -111
- package/dist/tools/check-repo-trust.d.ts +4 -19
- package/dist/tools/check-repo-trust.js +56 -47
- package/dist/tools/create-diagram.d.ts +0 -5
- package/dist/tools/create-diagram.js +0 -10
- package/dist/tools/create-document.d.ts +0 -5
- package/dist/tools/create-document.js +3 -9
- package/dist/tools/create-finding.d.ts +85 -0
- package/dist/tools/create-finding.js +136 -0
- package/dist/tools/delete-finding.d.ts +19 -0
- package/dist/tools/delete-finding.js +36 -0
- package/dist/tools/discover-local-infra.d.ts +0 -10
- package/dist/tools/discover-local-infra.js +3 -73
- package/dist/tools/enterprise/get-org-zat.d.ts +0 -5
- package/dist/tools/enterprise/get-org-zat.js +0 -6
- package/dist/tools/enterprise/get-threat-model.d.ts +1 -8
- package/dist/tools/enterprise/get-threat-model.js +9 -31
- package/dist/tools/enterprise/list-attack-scenarios.d.ts +24 -0
- package/dist/tools/enterprise/list-attack-scenarios.js +63 -0
- package/dist/tools/enterprise/list-threat-models.d.ts +1 -6
- package/dist/tools/enterprise/list-threat-models.js +1 -9
- package/dist/tools/enterprise/manage-actor.d.ts +2 -7
- package/dist/tools/enterprise/manage-actor.js +13 -7
- package/dist/tools/enterprise/manage-attack-scenario.d.ts +1 -6
- package/dist/tools/enterprise/manage-attack-scenario.js +12 -7
- package/dist/tools/enterprise/manage-data-asset.d.ts +2 -7
- package/dist/tools/enterprise/manage-data-asset.js +16 -7
- package/dist/tools/enterprise/manage-security-control.d.ts +1 -6
- package/dist/tools/enterprise/manage-security-control.js +17 -7
- package/dist/tools/explain-signal-for-diff.d.ts +34 -0
- package/dist/tools/explain-signal-for-diff.js +75 -0
- package/dist/tools/generate-diagram.d.ts +0 -6
- package/dist/tools/generate-diagram.js +21 -13
- package/dist/tools/get-application-overview.d.ts +0 -5
- package/dist/tools/get-application-overview.js +0 -6
- package/dist/tools/get-application.d.ts +0 -5
- package/dist/tools/get-application.js +0 -6
- package/dist/tools/get-diagram.d.ts +0 -5
- package/dist/tools/get-diagram.js +1 -11
- package/dist/tools/get-document.d.ts +0 -5
- package/dist/tools/get-document.js +0 -6
- package/dist/tools/get-oss-zat.d.ts +0 -5
- package/dist/tools/get-oss-zat.js +0 -7
- package/dist/tools/get-signal.d.ts +24 -0
- package/dist/tools/get-signal.js +75 -0
- package/dist/tools/get-started.d.ts +18 -0
- package/dist/tools/get-started.js +470 -0
- package/dist/tools/get-trust-keys.d.ts +0 -5
- package/dist/tools/get-trust-keys.js +0 -6
- package/dist/tools/import-openapi-endpoints.d.ts +0 -5
- package/dist/tools/import-openapi-endpoints.js +0 -6
- package/dist/tools/inspect-zat.d.ts +0 -5
- package/dist/tools/inspect-zat.js +0 -19
- package/dist/tools/inspect.d.ts +21 -0
- package/dist/tools/inspect.js +222 -0
- package/dist/tools/list-applications.d.ts +1 -6
- package/dist/tools/list-applications.js +0 -6
- package/dist/tools/list-diagrams.d.ts +0 -5
- package/dist/tools/list-diagrams.js +0 -6
- package/dist/tools/list-documents.d.ts +0 -5
- package/dist/tools/list-documents.js +0 -6
- package/dist/tools/list-endpoints.d.ts +1 -6
- package/dist/tools/list-endpoints.js +0 -6
- package/dist/tools/list-signals.d.ts +37 -0
- package/dist/tools/list-signals.js +83 -0
- package/dist/tools/manage-application.d.ts +64 -0
- package/dist/tools/manage-application.js +129 -0
- package/dist/tools/manage-diagram.d.ts +0 -5
- package/dist/tools/manage-diagram.js +0 -16
- package/dist/tools/manage-endpoint-lifecycle.d.ts +80 -0
- package/dist/tools/manage-endpoint-lifecycle.js +180 -0
- package/dist/tools/open-in-ide.d.ts +2 -14
- package/dist/tools/open-in-ide.js +0 -13
- package/dist/tools/review-change.d.ts +34 -0
- package/dist/tools/review-change.js +93 -0
- package/dist/tools/security-review.d.ts +0 -16
- package/dist/tools/security-review.js +63 -77
- package/dist/tools/threat-get-capsule.d.ts +15 -0
- package/dist/tools/threat-get-capsule.js +53 -0
- package/dist/tools/threat-get-inference-prompt.d.ts +15 -0
- package/dist/tools/threat-get-inference-prompt.js +73 -0
- package/dist/tools/threat-list-relevant-capsules.d.ts +17 -0
- package/dist/tools/threat-list-relevant-capsules.js +158 -0
- package/dist/tools/threat-run-matcher.d.ts +17 -0
- package/dist/tools/threat-run-matcher.js +145 -0
- package/dist/tools/update-document.d.ts +0 -5
- package/dist/tools/update-document.js +3 -9
- package/dist/tools/update-endpoint.d.ts +1 -6
- package/dist/tools/update-endpoint.js +0 -7
- package/dist/tools/update-finding.d.ts +61 -0
- package/dist/tools/update-finding.js +80 -0
- package/dist/tools/update-mermaid-source.d.ts +0 -13
- package/dist/tools/update-mermaid-source.js +0 -14
- package/dist/tools/verify-trust-mark.d.ts +0 -5
- package/dist/tools/verify-trust-mark.js +0 -6
- package/dist/types.d.ts +13 -13
- package/dist/types.js +22 -28
- package/package.json +28 -5
- package/dist/api-client.js.map +0 -1
- package/dist/auth/index.js.map +0 -1
- package/dist/auth/jwt.js.map +0 -1
- package/dist/auth/keychain.js.map +0 -1
- package/dist/auth/oauth.js.map +0 -1
- package/dist/auth/sessions.js.map +0 -1
- package/dist/auth/token-refresh.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/project-binding.js.map +0 -1
- package/dist/resolve-application-id.js.map +0 -1
- package/dist/sanitize.js.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/tools/check-project.js.map +0 -1
- package/dist/tools/check-repo-trust.js.map +0 -1
- package/dist/tools/create-diagram.js.map +0 -1
- package/dist/tools/create-document.js.map +0 -1
- package/dist/tools/discover-local-infra.js.map +0 -1
- package/dist/tools/enterprise/capture-evidence.d.ts +0 -54
- package/dist/tools/enterprise/capture-evidence.js +0 -72
- package/dist/tools/enterprise/capture-evidence.js.map +0 -1
- package/dist/tools/enterprise/create-report-ticket.d.ts +0 -34
- package/dist/tools/enterprise/create-report-ticket.js +0 -44
- package/dist/tools/enterprise/create-report-ticket.js.map +0 -1
- package/dist/tools/enterprise/end-pentest-session.d.ts +0 -33
- package/dist/tools/enterprise/end-pentest-session.js +0 -42
- package/dist/tools/enterprise/end-pentest-session.js.map +0 -1
- package/dist/tools/enterprise/generate-report.d.ts +0 -55
- package/dist/tools/enterprise/generate-report.js +0 -111
- package/dist/tools/enterprise/generate-report.js.map +0 -1
- package/dist/tools/enterprise/get-org-zat.js.map +0 -1
- package/dist/tools/enterprise/get-report-status.d.ts +0 -27
- package/dist/tools/enterprise/get-report-status.js +0 -38
- package/dist/tools/enterprise/get-report-status.js.map +0 -1
- package/dist/tools/enterprise/get-threat-model.js.map +0 -1
- package/dist/tools/enterprise/list-agents.d.ts +0 -42
- package/dist/tools/enterprise/list-agents.js +0 -95
- package/dist/tools/enterprise/list-agents.js.map +0 -1
- package/dist/tools/enterprise/list-report-issues.d.ts +0 -36
- package/dist/tools/enterprise/list-report-issues.js +0 -50
- package/dist/tools/enterprise/list-report-issues.js.map +0 -1
- package/dist/tools/enterprise/list-threat-models.js.map +0 -1
- package/dist/tools/enterprise/manage-actor.js.map +0 -1
- package/dist/tools/enterprise/manage-attack-scenario.js.map +0 -1
- package/dist/tools/enterprise/manage-component.d.ts +0 -58
- package/dist/tools/enterprise/manage-component.js +0 -90
- package/dist/tools/enterprise/manage-component.js.map +0 -1
- package/dist/tools/enterprise/manage-data-asset.js.map +0 -1
- package/dist/tools/enterprise/manage-data-flow.d.ts +0 -57
- package/dist/tools/enterprise/manage-data-flow.js +0 -98
- package/dist/tools/enterprise/manage-data-flow.js.map +0 -1
- package/dist/tools/enterprise/manage-finding.d.ts +0 -69
- package/dist/tools/enterprise/manage-finding.js +0 -106
- package/dist/tools/enterprise/manage-finding.js.map +0 -1
- package/dist/tools/enterprise/manage-security-control.js.map +0 -1
- package/dist/tools/enterprise/manage-test-case.d.ts +0 -88
- package/dist/tools/enterprise/manage-test-case.js +0 -119
- package/dist/tools/enterprise/manage-test-case.js.map +0 -1
- package/dist/tools/enterprise/promote-finding-to-issue.d.ts +0 -36
- package/dist/tools/enterprise/promote-finding-to-issue.js +0 -65
- package/dist/tools/enterprise/promote-finding-to-issue.js.map +0 -1
- package/dist/tools/enterprise/publish-report-version.d.ts +0 -34
- package/dist/tools/enterprise/publish-report-version.js +0 -75
- package/dist/tools/enterprise/publish-report-version.js.map +0 -1
- package/dist/tools/enterprise/publish-test-to-library.d.ts +0 -31
- package/dist/tools/enterprise/publish-test-to-library.js +0 -40
- package/dist/tools/enterprise/publish-test-to-library.js.map +0 -1
- package/dist/tools/enterprise/record-test-result.d.ts +0 -67
- package/dist/tools/enterprise/record-test-result.js +0 -75
- package/dist/tools/enterprise/record-test-result.js.map +0 -1
- package/dist/tools/enterprise/start-pentest-session.d.ts +0 -35
- package/dist/tools/enterprise/start-pentest-session.js +0 -50
- package/dist/tools/enterprise/start-pentest-session.js.map +0 -1
- package/dist/tools/enterprise/sync-report-section.d.ts +0 -41
- package/dist/tools/enterprise/sync-report-section.js +0 -79
- package/dist/tools/enterprise/sync-report-section.js.map +0 -1
- package/dist/tools/enterprise/update-report-issue.d.ts +0 -55
- package/dist/tools/enterprise/update-report-issue.js +0 -69
- package/dist/tools/enterprise/update-report-issue.js.map +0 -1
- package/dist/tools/generate-diagram.js.map +0 -1
- package/dist/tools/get-agent-test-results.d.ts +0 -41
- package/dist/tools/get-agent-test-results.js +0 -86
- package/dist/tools/get-agent-test-results.js.map +0 -1
- package/dist/tools/get-application-overview.js.map +0 -1
- package/dist/tools/get-application.js.map +0 -1
- package/dist/tools/get-artifact-content.d.ts +0 -29
- package/dist/tools/get-artifact-content.js +0 -86
- package/dist/tools/get-artifact-content.js.map +0 -1
- package/dist/tools/get-diagram.js.map +0 -1
- package/dist/tools/get-document.js.map +0 -1
- package/dist/tools/get-finding-details.d.ts +0 -28
- package/dist/tools/get-finding-details.js +0 -43
- package/dist/tools/get-finding-details.js.map +0 -1
- package/dist/tools/get-findings.d.ts +0 -57
- package/dist/tools/get-findings.js +0 -103
- package/dist/tools/get-findings.js.map +0 -1
- package/dist/tools/get-oss-zat.js.map +0 -1
- package/dist/tools/get-recon-scan.d.ts +0 -27
- package/dist/tools/get-recon-scan.js +0 -46
- package/dist/tools/get-recon-scan.js.map +0 -1
- package/dist/tools/get-scan-output.d.ts +0 -27
- package/dist/tools/get-scan-output.js +0 -64
- package/dist/tools/get-scan-output.js.map +0 -1
- package/dist/tools/get-scenario-details.d.ts +0 -27
- package/dist/tools/get-scenario-details.js +0 -46
- package/dist/tools/get-scenario-details.js.map +0 -1
- package/dist/tools/get-test-case-results.d.ts +0 -37
- package/dist/tools/get-test-case-results.js +0 -66
- package/dist/tools/get-test-case-results.js.map +0 -1
- package/dist/tools/get-test-details.d.ts +0 -29
- package/dist/tools/get-test-details.js +0 -49
- package/dist/tools/get-test-details.js.map +0 -1
- package/dist/tools/get-trust-keys.js.map +0 -1
- package/dist/tools/import-openapi-endpoints.js.map +0 -1
- package/dist/tools/inspect-zat.js.map +0 -1
- package/dist/tools/list-agent-test-cases.d.ts +0 -41
- package/dist/tools/list-agent-test-cases.js +0 -73
- package/dist/tools/list-agent-test-cases.js.map +0 -1
- package/dist/tools/list-applications.js.map +0 -1
- package/dist/tools/list-diagrams.js.map +0 -1
- package/dist/tools/list-documents.js.map +0 -1
- package/dist/tools/list-endpoints.js.map +0 -1
- package/dist/tools/list-recon-scans.d.ts +0 -36
- package/dist/tools/list-recon-scans.js +0 -74
- package/dist/tools/list-recon-scans.js.map +0 -1
- package/dist/tools/list-scan-artifacts.d.ts +0 -41
- package/dist/tools/list-scan-artifacts.js +0 -63
- package/dist/tools/list-scan-artifacts.js.map +0 -1
- package/dist/tools/list-scans.d.ts +0 -44
- package/dist/tools/list-scans.js +0 -91
- package/dist/tools/list-scans.js.map +0 -1
- package/dist/tools/list-test-library.d.ts +0 -44
- package/dist/tools/list-test-library.js +0 -83
- package/dist/tools/list-test-library.js.map +0 -1
- package/dist/tools/list-test-scenarios.d.ts +0 -31
- package/dist/tools/list-test-scenarios.js +0 -66
- package/dist/tools/list-test-scenarios.js.map +0 -1
- package/dist/tools/local-scan.d.ts +0 -40
- package/dist/tools/local-scan.js +0 -261
- package/dist/tools/local-scan.js.map +0 -1
- package/dist/tools/manage-diagram.js.map +0 -1
- package/dist/tools/open-in-ide.js.map +0 -1
- package/dist/tools/run-test-scenario.d.ts +0 -37
- package/dist/tools/run-test-scenario.js +0 -70
- package/dist/tools/run-test-scenario.js.map +0 -1
- package/dist/tools/scan-pr.d.ts +0 -27
- package/dist/tools/scan-pr.js +0 -51
- package/dist/tools/scan-pr.js.map +0 -1
- package/dist/tools/security-review.js.map +0 -1
- package/dist/tools/setup-red-team-target.d.ts +0 -79
- package/dist/tools/setup-red-team-target.js +0 -430
- package/dist/tools/setup-red-team-target.js.map +0 -1
- package/dist/tools/triage-finding.d.ts +0 -47
- package/dist/tools/triage-finding.js +0 -116
- package/dist/tools/triage-finding.js.map +0 -1
- package/dist/tools/update-document.js.map +0 -1
- package/dist/tools/update-endpoint.js.map +0 -1
- package/dist/tools/update-mermaid-source.js.map +0 -1
- package/dist/tools/verify-trust-mark.js.map +0 -1
- package/dist/types.js.map +0 -1
|
@@ -1,20 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* zivis_discover_local_infra — Discover AI infrastructure in a local project
|
|
3
|
-
*
|
|
4
|
-
* Reads Docker, compose, and dependency files to understand the local AI
|
|
5
|
-
* infrastructure. Returns structured recommendations for red team testing
|
|
6
|
-
* via zivis_local_scan.
|
|
7
|
-
*
|
|
8
|
-
* This is a local-only tool — no API calls or authentication required.
|
|
9
|
-
* Env values are always redacted for safety.
|
|
10
|
-
*/
|
|
11
1
|
import { z } from "zod";
|
|
12
2
|
import { readFile, readdir, stat } from "fs/promises";
|
|
13
3
|
import { join } from "path";
|
|
14
4
|
import { exec } from "child_process";
|
|
15
5
|
import { promisify } from "util";
|
|
16
6
|
const execAsync = promisify(exec);
|
|
17
|
-
// ── Constants ──
|
|
18
7
|
export const DISCOVER_LOCAL_INFRA_NAME = "zivis_discover_local_infra";
|
|
19
8
|
export const DISCOVER_LOCAL_INFRA_DESCRIPTION = `Discover AI infrastructure in a local project directory by reading Docker, compose, and dependency files.
|
|
20
9
|
|
|
@@ -45,7 +34,6 @@ export const DISCOVER_LOCAL_INFRA_SCHEMA = {
|
|
|
45
34
|
.optional()
|
|
46
35
|
.describe("Path to the project directory to analyze. Defaults to the current working directory."),
|
|
47
36
|
};
|
|
48
|
-
// ── AI Framework Detection Maps ──
|
|
49
37
|
const NPM_AI_PACKAGES = [
|
|
50
38
|
{ package: "openai", name: "OpenAI SDK" },
|
|
51
39
|
{ package: "@anthropic-ai/sdk", name: "Anthropic SDK" },
|
|
@@ -128,8 +116,7 @@ const INFRA_IMAGES = [
|
|
|
128
116
|
"jaeger",
|
|
129
117
|
"memcached",
|
|
130
118
|
];
|
|
131
|
-
const MAX_FILE_SIZE = 100 * 1024;
|
|
132
|
-
// ── Handler ──
|
|
119
|
+
const MAX_FILE_SIZE = 100 * 1024;
|
|
133
120
|
export function createDiscoverLocalInfraHandler() {
|
|
134
121
|
return async (params) => {
|
|
135
122
|
const projectDir = params.project_dir || process.cwd();
|
|
@@ -142,7 +129,6 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
142
129
|
suggestion: null,
|
|
143
130
|
localScanCommand: null,
|
|
144
131
|
};
|
|
145
|
-
// Step 1: Check Docker daemon
|
|
146
132
|
try {
|
|
147
133
|
const { stdout } = await execAsync("docker version --format '{{.Server.Version}}'", {
|
|
148
134
|
timeout: 5000,
|
|
@@ -152,7 +138,6 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
152
138
|
catch {
|
|
153
139
|
result.docker = { running: false };
|
|
154
140
|
}
|
|
155
|
-
// Step 2: Find and parse compose files (check root and common subdirs)
|
|
156
141
|
const composeFileNames = [
|
|
157
142
|
"docker-compose.yml",
|
|
158
143
|
"docker-compose.yaml",
|
|
@@ -174,10 +159,8 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
174
159
|
}
|
|
175
160
|
}
|
|
176
161
|
}
|
|
177
|
-
// Step 3: Check running containers
|
|
178
162
|
if (result.docker.running && result.compose.found) {
|
|
179
163
|
try {
|
|
180
|
-
// Use the directory containing the compose file
|
|
181
164
|
const composeDir = result.compose.file?.includes("/")
|
|
182
165
|
? join(projectDir, result.compose.file.split("/").slice(0, -1).join("/"))
|
|
183
166
|
: projectDir;
|
|
@@ -192,12 +175,9 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
192
175
|
}
|
|
193
176
|
}
|
|
194
177
|
catch {
|
|
195
|
-
// docker compose ps failed, leave statuses as unknown
|
|
196
178
|
}
|
|
197
179
|
}
|
|
198
|
-
// Step 4: Read dependency files and detect AI frameworks
|
|
199
180
|
const detected = [];
|
|
200
|
-
// package.json
|
|
201
181
|
const pkgJson = await safeReadFile(join(projectDir, "package.json"));
|
|
202
182
|
if (pkgJson) {
|
|
203
183
|
try {
|
|
@@ -218,17 +198,14 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
218
198
|
}
|
|
219
199
|
}
|
|
220
200
|
catch {
|
|
221
|
-
// Invalid JSON, skip
|
|
222
201
|
}
|
|
223
202
|
}
|
|
224
|
-
// Search subdirectories (up to 2 levels deep) for dependency files
|
|
225
203
|
const subdirs = await safeReaddir(projectDir);
|
|
226
204
|
const searchDirs = [""];
|
|
227
205
|
for (const dir of subdirs) {
|
|
228
206
|
if (dir.startsWith(".") || dir === "node_modules" || dir === "vendor")
|
|
229
207
|
continue;
|
|
230
208
|
searchDirs.push(dir);
|
|
231
|
-
// Also check one more level (e.g., demo-app/api/, apps/api/)
|
|
232
209
|
const subSubDirs = await safeReaddir(join(projectDir, dir));
|
|
233
210
|
for (const sub of subSubDirs) {
|
|
234
211
|
if (sub.startsWith(".") || sub === "node_modules" || sub === "vendor")
|
|
@@ -239,7 +216,6 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
239
216
|
for (const dir of searchDirs) {
|
|
240
217
|
const base = dir ? join(projectDir, dir) : projectDir;
|
|
241
218
|
const prefix = dir ? `${dir}/` : "";
|
|
242
|
-
// package.json
|
|
243
219
|
const subPkgJson = await safeReadFile(join(base, "package.json"));
|
|
244
220
|
if (subPkgJson) {
|
|
245
221
|
try {
|
|
@@ -257,10 +233,8 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
257
233
|
}
|
|
258
234
|
}
|
|
259
235
|
catch {
|
|
260
|
-
// Skip
|
|
261
236
|
}
|
|
262
237
|
}
|
|
263
|
-
// requirements.txt
|
|
264
238
|
const reqTxt = await safeReadFile(join(base, "requirements.txt"));
|
|
265
239
|
if (reqTxt) {
|
|
266
240
|
const lines = reqTxt.toLowerCase().split("\n");
|
|
@@ -278,7 +252,6 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
278
252
|
}
|
|
279
253
|
}
|
|
280
254
|
}
|
|
281
|
-
// pyproject.toml
|
|
282
255
|
const pyproject = await safeReadFile(join(base, "pyproject.toml"));
|
|
283
256
|
if (pyproject) {
|
|
284
257
|
for (const ai of PIP_AI_PACKAGES) {
|
|
@@ -295,7 +268,6 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
295
268
|
}
|
|
296
269
|
}
|
|
297
270
|
}
|
|
298
|
-
// go.mod
|
|
299
271
|
const goMod = await safeReadFile(join(base, "go.mod"));
|
|
300
272
|
if (goMod) {
|
|
301
273
|
for (const ai of GO_AI_PACKAGES) {
|
|
@@ -312,10 +284,8 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
312
284
|
}
|
|
313
285
|
}
|
|
314
286
|
result.aiFrameworks.detected = detected;
|
|
315
|
-
// Step 5: Read .env files, redact values, flag AI keys
|
|
316
287
|
const envFileNames = [".env", ".env.local", ".env.development"];
|
|
317
288
|
const envHints = [];
|
|
318
|
-
// Check root and subdirs for .env files
|
|
319
289
|
for (const dir of ["", "infra", "docker"]) {
|
|
320
290
|
for (const envFile of envFileNames) {
|
|
321
291
|
const filePath = dir ? join(projectDir, dir, envFile) : join(projectDir, envFile);
|
|
@@ -335,7 +305,6 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
335
305
|
}
|
|
336
306
|
}
|
|
337
307
|
result.aiFrameworks.envHints = [...new Set(envHints)];
|
|
338
|
-
// Step 6: Scan for Dockerfiles (reuse searchDirs from dependency scan)
|
|
339
308
|
const dockerfiles = [];
|
|
340
309
|
for (const dir of searchDirs) {
|
|
341
310
|
const base = dir ? join(projectDir, dir) : projectDir;
|
|
@@ -352,7 +321,6 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
352
321
|
}
|
|
353
322
|
}
|
|
354
323
|
result.dockerfiles = dockerfiles;
|
|
355
|
-
// Step 7: Check if local runner image exists
|
|
356
324
|
if (result.docker.running) {
|
|
357
325
|
try {
|
|
358
326
|
const { stdout } = await execAsync("docker images ghcr.io/zivisai/zivis-local-runner --format '{{.Tag}}'", { timeout: 5000 });
|
|
@@ -374,7 +342,6 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
374
342
|
};
|
|
375
343
|
}
|
|
376
344
|
}
|
|
377
|
-
// Step 8: Generate suggestion
|
|
378
345
|
result.suggestion = generateSuggestion(result.compose.services, result.aiFrameworks.detected, result.aiFrameworks.envHints, result.dockerfiles);
|
|
379
346
|
if (result.suggestion) {
|
|
380
347
|
const parts = [`target_url="${result.suggestion.target_url}"`];
|
|
@@ -401,7 +368,6 @@ export function createDiscoverLocalInfraHandler() {
|
|
|
401
368
|
};
|
|
402
369
|
};
|
|
403
370
|
}
|
|
404
|
-
// ── Helpers ──
|
|
405
371
|
async function safeReadFile(filePath) {
|
|
406
372
|
try {
|
|
407
373
|
const stats = await stat(filePath);
|
|
@@ -423,16 +389,12 @@ async function safeReaddir(dirPath) {
|
|
|
423
389
|
return [];
|
|
424
390
|
}
|
|
425
391
|
}
|
|
426
|
-
/**
|
|
427
|
-
* Parse a docker-compose file using line-by-line analysis.
|
|
428
|
-
* Extracts service names, images, ports, environment keys, and depends_on.
|
|
429
|
-
*/
|
|
430
392
|
function parseComposeServices(content) {
|
|
431
393
|
const lines = content.split("\n");
|
|
432
394
|
const services = [];
|
|
433
395
|
let inServices = false;
|
|
434
396
|
let currentService = null;
|
|
435
|
-
let currentSection = "";
|
|
397
|
+
let currentSection = "";
|
|
436
398
|
let serviceIndent = -1;
|
|
437
399
|
let sectionIndent = -1;
|
|
438
400
|
for (const line of lines) {
|
|
@@ -441,13 +403,11 @@ function parseComposeServices(content) {
|
|
|
441
403
|
if (trimmed === "" || trimmed.startsWith("#"))
|
|
442
404
|
continue;
|
|
443
405
|
const indent = raw.length - raw.trimStart().length;
|
|
444
|
-
// Top-level "services:" key (indent 0)
|
|
445
406
|
if (indent === 0 && /^services:\s*$/.test(trimmed)) {
|
|
446
407
|
inServices = true;
|
|
447
408
|
serviceIndent = -1;
|
|
448
409
|
continue;
|
|
449
410
|
}
|
|
450
|
-
// Another top-level key ends the services block
|
|
451
411
|
if (inServices && indent === 0) {
|
|
452
412
|
inServices = false;
|
|
453
413
|
if (currentService)
|
|
@@ -457,8 +417,6 @@ function parseComposeServices(content) {
|
|
|
457
417
|
}
|
|
458
418
|
if (!inServices)
|
|
459
419
|
continue;
|
|
460
|
-
// Detect service names: lines at the first indent level under services
|
|
461
|
-
// that end with ":" and contain only word/dash chars
|
|
462
420
|
if (serviceIndent === -1 && /^[\w][\w.-]*:\s*$/.test(trimmed)) {
|
|
463
421
|
serviceIndent = indent;
|
|
464
422
|
}
|
|
@@ -479,9 +437,7 @@ function parseComposeServices(content) {
|
|
|
479
437
|
}
|
|
480
438
|
if (!currentService)
|
|
481
439
|
continue;
|
|
482
|
-
// Service properties (indent > serviceIndent)
|
|
483
440
|
if (indent > serviceIndent) {
|
|
484
|
-
// Check for property keys
|
|
485
441
|
const propMatch = trimmed.match(/^(image|ports|environment|depends_on|build):\s*(.*)/);
|
|
486
442
|
if (propMatch) {
|
|
487
443
|
const key = propMatch[1];
|
|
@@ -499,7 +455,6 @@ function parseComposeServices(content) {
|
|
|
499
455
|
currentSection = "";
|
|
500
456
|
continue;
|
|
501
457
|
}
|
|
502
|
-
// If we're at a deeper indent than section, parse items
|
|
503
458
|
if (currentSection && sectionIndent >= 0 && indent > sectionIndent) {
|
|
504
459
|
if (trimmed.startsWith("-")) {
|
|
505
460
|
const value = trimmed.replace(/^-\s*/, "").replace(/["']/g, "").trim();
|
|
@@ -522,17 +477,14 @@ function parseComposeServices(content) {
|
|
|
522
477
|
}
|
|
523
478
|
}
|
|
524
479
|
else if (currentSection === "environment" && trimmed.includes(":")) {
|
|
525
|
-
// Environment as mapping (KEY: value)
|
|
526
480
|
const envKey = trimmed.split(":")[0].trim();
|
|
527
481
|
if (envKey)
|
|
528
482
|
currentService.environmentKeys.push(envKey);
|
|
529
483
|
}
|
|
530
484
|
}
|
|
531
485
|
else if (indent <= sectionIndent) {
|
|
532
|
-
// Back to service property level, reset section
|
|
533
486
|
currentSection = "";
|
|
534
487
|
sectionIndent = -1;
|
|
535
|
-
// Re-check for property match
|
|
536
488
|
const rePropMatch = trimmed.match(/^(image|ports|environment|depends_on|build):\s*(.*)/);
|
|
537
489
|
if (rePropMatch) {
|
|
538
490
|
const key = rePropMatch[1];
|
|
@@ -554,7 +506,6 @@ function parseComposeServices(content) {
|
|
|
554
506
|
}
|
|
555
507
|
function parseDockerComposePsOutput(stdout) {
|
|
556
508
|
const containers = [];
|
|
557
|
-
// docker compose ps --format json outputs one JSON object per line
|
|
558
509
|
for (const line of stdout.split("\n")) {
|
|
559
510
|
const trimmed = line.trim();
|
|
560
511
|
if (!trimmed)
|
|
@@ -567,7 +518,6 @@ function parseDockerComposePsOutput(stdout) {
|
|
|
567
518
|
});
|
|
568
519
|
}
|
|
569
520
|
catch {
|
|
570
|
-
// Not JSON, skip
|
|
571
521
|
}
|
|
572
522
|
}
|
|
573
523
|
return containers;
|
|
@@ -584,14 +534,12 @@ async function parseDockerfile(dir, filename) {
|
|
|
584
534
|
};
|
|
585
535
|
for (const line of content.split("\n")) {
|
|
586
536
|
const trimmed = line.trim();
|
|
587
|
-
// FROM instruction
|
|
588
537
|
if (/^FROM\s+/i.test(trimmed)) {
|
|
589
538
|
const fromMatch = trimmed.match(/^FROM\s+(\S+)/i);
|
|
590
539
|
if (fromMatch && !info.baseImage) {
|
|
591
540
|
info.baseImage = fromMatch[1];
|
|
592
541
|
}
|
|
593
542
|
}
|
|
594
|
-
// EXPOSE instruction
|
|
595
543
|
if (/^EXPOSE\s+/i.test(trimmed)) {
|
|
596
544
|
const ports = trimmed
|
|
597
545
|
.replace(/^EXPOSE\s+/i, "")
|
|
@@ -600,7 +548,6 @@ async function parseDockerfile(dir, filename) {
|
|
|
600
548
|
.filter((p) => !isNaN(p));
|
|
601
549
|
info.exposedPorts.push(...ports);
|
|
602
550
|
}
|
|
603
|
-
// AI hints from pip install / npm install
|
|
604
551
|
if (trimmed.includes("pip install") || trimmed.includes("pip3 install")) {
|
|
605
552
|
for (const ai of PIP_AI_PACKAGES) {
|
|
606
553
|
if (trimmed.includes(ai.package)) {
|
|
@@ -615,7 +562,6 @@ async function parseDockerfile(dir, filename) {
|
|
|
615
562
|
}
|
|
616
563
|
}
|
|
617
564
|
}
|
|
618
|
-
// Known AI base images
|
|
619
565
|
if (/^FROM\s+/i.test(trimmed)) {
|
|
620
566
|
const image = trimmed.replace(/^FROM\s+/i, "").split(/\s+/)[0].toLowerCase();
|
|
621
567
|
if (image.includes("ollama"))
|
|
@@ -630,12 +576,10 @@ async function parseDockerfile(dir, filename) {
|
|
|
630
576
|
}
|
|
631
577
|
function generateSuggestion(services, frameworks, envHints, dockerfiles) {
|
|
632
578
|
const reasons = [];
|
|
633
|
-
// Filter out infrastructure services
|
|
634
579
|
const appServices = services.filter((svc) => {
|
|
635
580
|
const image = (svc.image || "").toLowerCase();
|
|
636
581
|
return !INFRA_IMAGES.some((infra) => image.includes(infra));
|
|
637
582
|
});
|
|
638
|
-
// Determine target type
|
|
639
583
|
const hasAiFrameworks = frameworks.length > 0;
|
|
640
584
|
const hasAiEnvKeys = envHints.length > 0;
|
|
641
585
|
const targetType = hasAiFrameworks || hasAiEnvKeys ? "ai_chat" : "api";
|
|
@@ -645,26 +589,21 @@ function generateSuggestion(services, frameworks, envHints, dockerfiles) {
|
|
|
645
589
|
if (hasAiEnvKeys) {
|
|
646
590
|
reasons.push(`Found AI-related env vars: ${envHints.join(", ")}`);
|
|
647
591
|
}
|
|
648
|
-
// Find the best service to target
|
|
649
592
|
let targetPort = null;
|
|
650
|
-
// Prefer running app services with ports
|
|
651
593
|
const runningApps = appServices.filter((svc) => svc.status === "running" && svc.ports.length > 0);
|
|
652
594
|
if (runningApps.length > 0) {
|
|
653
|
-
// Pick the first one with a port in the typical app range
|
|
654
595
|
const preferred = runningApps.find((svc) => svc.ports.some((p) => p.host >= 3000 && p.host <= 9000));
|
|
655
596
|
const target = preferred || runningApps[0];
|
|
656
597
|
targetPort = target.ports[0].host;
|
|
657
598
|
reasons.push(`Service "${target.name}" is running on port ${targetPort}`);
|
|
658
599
|
}
|
|
659
600
|
else if (appServices.length > 0) {
|
|
660
|
-
// Use any app service with ports
|
|
661
601
|
const withPorts = appServices.find((svc) => svc.ports.length > 0);
|
|
662
602
|
if (withPorts) {
|
|
663
603
|
targetPort = withPorts.ports[0].host;
|
|
664
604
|
reasons.push(`Service "${withPorts.name}" has port ${targetPort} mapped`);
|
|
665
605
|
}
|
|
666
606
|
}
|
|
667
|
-
// Fallback: check Dockerfiles for EXPOSE
|
|
668
607
|
if (!targetPort) {
|
|
669
608
|
for (const df of dockerfiles) {
|
|
670
609
|
if (df.exposedPorts.length > 0) {
|
|
@@ -674,19 +613,15 @@ function generateSuggestion(services, frameworks, envHints, dockerfiles) {
|
|
|
674
613
|
}
|
|
675
614
|
}
|
|
676
615
|
}
|
|
677
|
-
// If still no port, try common defaults
|
|
678
616
|
if (!targetPort) {
|
|
679
617
|
targetPort = 3000;
|
|
680
618
|
reasons.push("Using default port 3000 (no port mapping found)");
|
|
681
619
|
}
|
|
682
|
-
// Infer chat endpoint from frameworks
|
|
683
620
|
const chatEndpoint = inferChatEndpoint(frameworks);
|
|
684
621
|
if (chatEndpoint) {
|
|
685
622
|
reasons.push(`Inferred endpoint ${chatEndpoint} from framework detection`);
|
|
686
623
|
}
|
|
687
|
-
// Infer request template and response path
|
|
688
624
|
const { requestTemplate, responsePath } = inferRequestFormat(frameworks);
|
|
689
|
-
// Calculate confidence
|
|
690
625
|
let confidence = "low";
|
|
691
626
|
if (hasAiFrameworks && targetPort && runningApps.length > 0) {
|
|
692
627
|
confidence = "high";
|
|
@@ -718,14 +653,12 @@ function inferChatEndpoint(frameworks) {
|
|
|
718
653
|
return "/v1/chat/completions";
|
|
719
654
|
if (names.has("Gradio"))
|
|
720
655
|
return "/api/predict";
|
|
721
|
-
// Default for any detected AI framework
|
|
722
656
|
if (frameworks.length > 0)
|
|
723
657
|
return "/api/chat";
|
|
724
658
|
return undefined;
|
|
725
659
|
}
|
|
726
660
|
function inferRequestFormat(frameworks) {
|
|
727
661
|
const names = new Set(frameworks.map((f) => f.name));
|
|
728
|
-
// OpenAI-compatible APIs
|
|
729
662
|
if (names.has("OpenAI SDK") ||
|
|
730
663
|
names.has("Azure OpenAI") ||
|
|
731
664
|
names.has("vLLM") ||
|
|
@@ -738,16 +671,14 @@ function inferRequestFormat(frameworks) {
|
|
|
738
671
|
responsePath: "choices[0].message.content",
|
|
739
672
|
};
|
|
740
673
|
}
|
|
741
|
-
// Vercel AI SDK
|
|
742
674
|
if (names.has("Vercel AI SDK") || names.has("Vercel AI SDK (OpenAI)") || names.has("Vercel AI SDK (Anthropic)")) {
|
|
743
675
|
return {
|
|
744
676
|
requestTemplate: JSON.stringify({
|
|
745
677
|
messages: [{ role: "user", content: "{{message}}" }],
|
|
746
678
|
}),
|
|
747
|
-
responsePath: undefined,
|
|
679
|
+
responsePath: undefined,
|
|
748
680
|
};
|
|
749
681
|
}
|
|
750
|
-
// Ollama
|
|
751
682
|
if (names.has("Ollama")) {
|
|
752
683
|
return {
|
|
753
684
|
requestTemplate: JSON.stringify({
|
|
@@ -760,4 +691,3 @@ function inferRequestFormat(frameworks) {
|
|
|
760
691
|
}
|
|
761
692
|
return {};
|
|
762
693
|
}
|
|
763
|
-
//# sourceMappingURL=discover-local-infra.js.map
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* zivis_get_org_zat — Get your organization's latest signed attestation token
|
|
3
|
-
*
|
|
4
|
-
* Maps to: GET /api/zat?framework=<optional> (JWT auth required)
|
|
5
|
-
*/
|
|
6
1
|
import { z } from "zod";
|
|
7
2
|
import type { ApiClient } from "../../api-client.js";
|
|
8
3
|
export declare const GET_ORG_ZAT_NAME = "zivis_get_org_zat";
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* zivis_get_org_zat — Get your organization's latest signed attestation token
|
|
3
|
-
*
|
|
4
|
-
* Maps to: GET /api/zat?framework=<optional> (JWT auth required)
|
|
5
|
-
*/
|
|
6
1
|
import { z } from "zod";
|
|
7
2
|
export const GET_ORG_ZAT_NAME = "zivis_get_org_zat";
|
|
8
3
|
export const GET_ORG_ZAT_DESCRIPTION = `Get your organization's latest ZIVIS Attestation Token (ZAT) — a cryptographically signed credential capturing your compliance posture.
|
|
@@ -59,4 +54,3 @@ export function createGetOrgZatHandler(apiClient) {
|
|
|
59
54
|
}
|
|
60
55
|
};
|
|
61
56
|
}
|
|
62
|
-
//# sourceMappingURL=get-org-zat.js.map
|
|
@@ -1,19 +1,12 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* zivis_get_threat_model — Get a threat model with all entities
|
|
3
|
-
*
|
|
4
|
-
* Maps to: GET /api/threat-models/:id
|
|
5
|
-
*/
|
|
6
1
|
import { z } from "zod";
|
|
7
2
|
import type { ApiClient } from "../../api-client.js";
|
|
8
3
|
export declare const GET_THREAT_MODEL_NAME = "zivis_get_threat_model";
|
|
9
|
-
export declare const GET_THREAT_MODEL_DESCRIPTION = "Get a threat model
|
|
4
|
+
export declare const GET_THREAT_MODEL_DESCRIPTION = "Get a threat model \u2014 its metadata, status, owning application, and linked diagrams.\n\nReturns:\n- The threat model row (name, status, application association, timestamps)\n- **Linked Diagrams** (`linked_diagrams`): first-class `Diagram` entities linked to this threat model. Use `zivis_get_diagram` for full content.\n- Threat-model documents are listed via `zivis_list_documents` with `threat_model_id`.\n\nIMPORTANT: The threat_model_id must be a threat model UUID from zivis_list_threat_models, NOT a scan ID or agent instance ID.";
|
|
10
5
|
export declare const GET_THREAT_MODEL_SCHEMA: {
|
|
11
6
|
threat_model_id: z.ZodString;
|
|
12
|
-
include_test_cases: z.ZodDefault<z.ZodBoolean>;
|
|
13
7
|
};
|
|
14
8
|
export declare function createGetThreatModelHandler(apiClient: ApiClient): (params: {
|
|
15
9
|
threat_model_id: string;
|
|
16
|
-
include_test_cases?: boolean;
|
|
17
10
|
}) => Promise<{
|
|
18
11
|
content: {
|
|
19
12
|
type: "text";
|
|
@@ -1,51 +1,30 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* zivis_get_threat_model — Get a threat model with all entities
|
|
3
|
-
*
|
|
4
|
-
* Maps to: GET /api/threat-models/:id
|
|
5
|
-
*/
|
|
6
1
|
import { z } from "zod";
|
|
7
2
|
import { sanitizeResponse } from "../../sanitize.js";
|
|
8
3
|
export const GET_THREAT_MODEL_NAME = "zivis_get_threat_model";
|
|
9
|
-
export const GET_THREAT_MODEL_DESCRIPTION = `Get a threat model
|
|
4
|
+
export const GET_THREAT_MODEL_DESCRIPTION = `Get a threat model — its metadata, status, owning application, and linked diagrams.
|
|
10
5
|
|
|
11
|
-
Returns
|
|
12
|
-
-
|
|
13
|
-
- **
|
|
14
|
-
-
|
|
15
|
-
- **Attack Scenarios**: STRIDE-categorized threats with severity, likelihood, attack vectors
|
|
16
|
-
- **Security Controls**: Existing mitigations (preventive, detective, corrective) with effectiveness
|
|
17
|
-
- **Data Assets**: What sensitive data exists and how it's classified
|
|
18
|
-
- **Test Cases**: Security tests with results (pass/fail/partial/not_tested)
|
|
19
|
-
- **Findings**: Discovered vulnerabilities with severity and remediation recommendations
|
|
20
|
-
- **Linked Diagrams**: Architecture, data flow, trust boundary, and other diagrams associated with this threat model
|
|
6
|
+
Returns:
|
|
7
|
+
- The threat model row (name, status, application association, timestamps)
|
|
8
|
+
- **Linked Diagrams** (\`linked_diagrams\`): first-class \`Diagram\` entities linked to this threat model. Use \`zivis_get_diagram\` for full content.
|
|
9
|
+
- Threat-model documents are listed via \`zivis_list_documents\` with \`threat_model_id\`.
|
|
21
10
|
|
|
22
|
-
IMPORTANT: The threat_model_id must be a threat model UUID from zivis_list_threat_models, NOT a scan ID or agent instance ID
|
|
23
|
-
|
|
24
|
-
Use this to understand the full security posture before making changes, adding entities, or running pen tests.
|
|
25
|
-
After viewing, use zivis_manage_actor, zivis_manage_component, zivis_manage_data_flow, etc. to add or update entities.
|
|
26
|
-
Use zivis_get_diagram with a diagram_id from the linked_diagrams to view full diagram details (nodes, connections, boundaries).`;
|
|
11
|
+
IMPORTANT: The threat_model_id must be a threat model UUID from zivis_list_threat_models, NOT a scan ID or agent instance ID.`;
|
|
27
12
|
export const GET_THREAT_MODEL_SCHEMA = {
|
|
28
13
|
threat_model_id: z
|
|
29
14
|
.string()
|
|
30
15
|
.describe("Threat model UUID (from zivis_list_threat_models, NOT a scan ID or agent ID)"),
|
|
31
|
-
include_test_cases: z
|
|
32
|
-
.boolean()
|
|
33
|
-
.default(true)
|
|
34
|
-
.describe("Whether to include test cases in the response"),
|
|
35
16
|
};
|
|
36
17
|
export function createGetThreatModelHandler(apiClient) {
|
|
37
18
|
return async (params) => {
|
|
38
19
|
try {
|
|
39
|
-
// Fetch threat model and linked diagrams in parallel
|
|
40
20
|
const [threatModelData, diagramsData] = await Promise.all([
|
|
41
|
-
apiClient.get(`/api/threat-models/${params.threat_model_id}
|
|
21
|
+
apiClient.get(`/api/threat-models/${params.threat_model_id}`),
|
|
42
22
|
apiClient
|
|
43
23
|
.get(`/api/diagrams?linkedThreatModelId=${params.threat_model_id}&take=50`)
|
|
44
24
|
.catch(() => ({ diagrams: [], total: 0 })),
|
|
45
25
|
]);
|
|
46
26
|
const sanitized = sanitizeResponse(threatModelData);
|
|
47
|
-
|
|
48
|
-
const diagrams = Array.isArray(diagramsData.diagrams)
|
|
27
|
+
const linkedDiagrams = Array.isArray(diagramsData.diagrams)
|
|
49
28
|
? diagramsData.diagrams.map((d) => ({
|
|
50
29
|
diagram_id: d.id,
|
|
51
30
|
name: d.name,
|
|
@@ -59,7 +38,7 @@ export function createGetThreatModelHandler(apiClient) {
|
|
|
59
38
|
: [];
|
|
60
39
|
const result = {
|
|
61
40
|
...sanitized,
|
|
62
|
-
linked_diagrams:
|
|
41
|
+
linked_diagrams: linkedDiagrams,
|
|
63
42
|
linked_diagrams_count: diagramsData.total,
|
|
64
43
|
};
|
|
65
44
|
return {
|
|
@@ -80,4 +59,3 @@ export function createGetThreatModelHandler(apiClient) {
|
|
|
80
59
|
}
|
|
81
60
|
};
|
|
82
61
|
}
|
|
83
|
-
//# sourceMappingURL=get-threat-model.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ApiClient } from "../../api-client.js";
|
|
3
|
+
export declare const LIST_ATTACK_SCENARIOS_NAME = "zivis_list_attack_scenarios";
|
|
4
|
+
export declare const LIST_ATTACK_SCENARIOS_DESCRIPTION = "List attack scenarios for a threat model, including their path steps.\n\nUse this when you need scenario IDs or attack path step IDs for follow-up tools (for example, step-level library test mappings).\n\nIMPORTANT: threat_model_id must be a threat model UUID (from zivis_list_threat_models), not a scan ID.";
|
|
5
|
+
export declare const LIST_ATTACK_SCENARIOS_SCHEMA: {
|
|
6
|
+
threat_model_id: z.ZodString;
|
|
7
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
8
|
+
};
|
|
9
|
+
export declare function createListAttackScenariosHandler(apiClient: ApiClient): (params: {
|
|
10
|
+
threat_model_id: string;
|
|
11
|
+
limit?: number;
|
|
12
|
+
}) => Promise<{
|
|
13
|
+
content: {
|
|
14
|
+
type: "text";
|
|
15
|
+
text: string;
|
|
16
|
+
}[];
|
|
17
|
+
isError?: undefined;
|
|
18
|
+
} | {
|
|
19
|
+
content: {
|
|
20
|
+
type: "text";
|
|
21
|
+
text: string;
|
|
22
|
+
}[];
|
|
23
|
+
isError: boolean;
|
|
24
|
+
}>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { sanitizeResponse } from "../../sanitize.js";
|
|
3
|
+
export const LIST_ATTACK_SCENARIOS_NAME = "zivis_list_attack_scenarios";
|
|
4
|
+
export const LIST_ATTACK_SCENARIOS_DESCRIPTION = `List attack scenarios for a threat model, including their path steps.
|
|
5
|
+
|
|
6
|
+
Use this when you need scenario IDs or attack path step IDs for follow-up tools (for example, step-level library test mappings).
|
|
7
|
+
|
|
8
|
+
IMPORTANT: threat_model_id must be a threat model UUID (from zivis_list_threat_models), not a scan ID.`;
|
|
9
|
+
export const LIST_ATTACK_SCENARIOS_SCHEMA = {
|
|
10
|
+
threat_model_id: z
|
|
11
|
+
.string()
|
|
12
|
+
.describe("Threat model UUID (from zivis_list_threat_models, NOT a scan ID)"),
|
|
13
|
+
limit: z
|
|
14
|
+
.number()
|
|
15
|
+
.min(1)
|
|
16
|
+
.max(200)
|
|
17
|
+
.default(50)
|
|
18
|
+
.describe("Maximum scenarios to return (1-200, default 50)"),
|
|
19
|
+
};
|
|
20
|
+
export function createListAttackScenariosHandler(apiClient) {
|
|
21
|
+
return async (params) => {
|
|
22
|
+
try {
|
|
23
|
+
const data = await apiClient.get(`/api/threat-models/${params.threat_model_id}/attack-scenarios`);
|
|
24
|
+
const limit = params.limit ?? 50;
|
|
25
|
+
const scenarios = (data.attackScenarios || []).slice(0, limit).map((scenario) => ({
|
|
26
|
+
scenario_id: scenario.id,
|
|
27
|
+
display_id: scenario.displayId,
|
|
28
|
+
title: scenario.title,
|
|
29
|
+
severity: scenario.severity,
|
|
30
|
+
likelihood: scenario.likelihood,
|
|
31
|
+
status: scenario.status,
|
|
32
|
+
review_status: scenario.reviewStatus,
|
|
33
|
+
risk_score: scenario.riskScore,
|
|
34
|
+
test_case_count: scenario._count?.testCases ?? 0,
|
|
35
|
+
step_count: scenario.pathSteps?.length ?? 0,
|
|
36
|
+
path_steps: (scenario.pathSteps || []).map((step) => ({
|
|
37
|
+
step_id: step.id,
|
|
38
|
+
step_order: step.stepOrder,
|
|
39
|
+
action: step.action,
|
|
40
|
+
library_test_count: step._count?.libraryTests ?? 0,
|
|
41
|
+
})),
|
|
42
|
+
created_at: scenario.createdAt,
|
|
43
|
+
updated_at: scenario.updatedAt,
|
|
44
|
+
}));
|
|
45
|
+
const sanitized = sanitizeResponse({
|
|
46
|
+
is_analyzing: data.isAnalyzing ?? false,
|
|
47
|
+
is_fallback_version: data.isFallback ?? false,
|
|
48
|
+
total_returned: scenarios.length,
|
|
49
|
+
scenarios,
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
content: [{ type: "text", text: JSON.stringify(sanitized, null, 2) }],
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
const message = err instanceof Error ? err.message : "Failed to list attack scenarios";
|
|
57
|
+
return {
|
|
58
|
+
content: [{ type: "text", text: `Error: ${message}` }],
|
|
59
|
+
isError: true,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* zivis_list_threat_models — List threat models for the org
|
|
3
|
-
*
|
|
4
|
-
* Maps to: GET /api/threat-models
|
|
5
|
-
*/
|
|
6
1
|
import { z } from "zod";
|
|
7
2
|
import type { ApiClient } from "../../api-client.js";
|
|
8
3
|
export declare const LIST_THREAT_MODELS_NAME = "zivis_list_threat_models";
|
|
9
|
-
export declare const LIST_THREAT_MODELS_DESCRIPTION = "List all threat models for your organization. Returns name, status, summary info, and linked diagram counts for each threat model.\n\nAlso fetches any diagrams linked to each threat model, so you can see which threat models have associated architecture, data flow, or trust boundary diagrams. Use zivis_get_threat_model to see full diagram details.\n\nIMPORTANT: Threat models are NOT scans and NOT agents. They are separate entities:\n- A **threat model** (returned here) has its own UUID and contains components, data flows, actors, findings, etc.\n- A **scan** is an agent execution run (from zivis_list_scans) \u2014 scans may CREATE or UPDATE threat models, but scan IDs \u2260 threat model IDs.\n- An **agent instance** is a configured agent (from the UI) \u2014 agents RUN scans which produce threat models.\n\nUse the threat model ID (from this tool's response) when calling zivis_get_threat_model,
|
|
4
|
+
export declare const LIST_THREAT_MODELS_DESCRIPTION = "List all threat models for your organization. Returns name, status, summary info, and linked diagram counts for each threat model.\n\nAlso fetches any diagrams linked to each threat model, so you can see which threat models have associated architecture, data flow, or trust boundary diagrams. Use zivis_get_threat_model to see full diagram details.\n\nIMPORTANT: Threat models are NOT scans and NOT agents. They are separate entities:\n- A **threat model** (returned here) has its own UUID and contains components, data flows, actors, findings, etc.\n- A **scan** is an agent execution run (from zivis_list_scans) \u2014 scans may CREATE or UPDATE threat models, but scan IDs \u2260 threat model IDs.\n- An **agent instance** is a configured agent (from the UI) \u2014 agents RUN scans which produce threat models.\n\nUse the threat model ID (from this tool's response) when calling zivis_get_threat_model, zivis_manage_actor, zivis_manage_attack_scenario, etc. Do NOT pass scan IDs or agent instance IDs to those tools.";
|
|
10
5
|
export declare const LIST_THREAT_MODELS_SCHEMA: {
|
|
11
6
|
status: z.ZodOptional<z.ZodEnum<{
|
|
12
7
|
draft: "draft";
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* zivis_list_threat_models — List threat models for the org
|
|
3
|
-
*
|
|
4
|
-
* Maps to: GET /api/threat-models
|
|
5
|
-
*/
|
|
6
1
|
import { z } from "zod";
|
|
7
2
|
import { sanitizeResponse } from "../../sanitize.js";
|
|
8
3
|
export const LIST_THREAT_MODELS_NAME = "zivis_list_threat_models";
|
|
@@ -15,7 +10,7 @@ IMPORTANT: Threat models are NOT scans and NOT agents. They are separate entitie
|
|
|
15
10
|
- A **scan** is an agent execution run (from zivis_list_scans) — scans may CREATE or UPDATE threat models, but scan IDs ≠ threat model IDs.
|
|
16
11
|
- An **agent instance** is a configured agent (from the UI) — agents RUN scans which produce threat models.
|
|
17
12
|
|
|
18
|
-
Use the threat model ID (from this tool's response) when calling zivis_get_threat_model,
|
|
13
|
+
Use the threat model ID (from this tool's response) when calling zivis_get_threat_model, zivis_manage_actor, zivis_manage_attack_scenario, etc. Do NOT pass scan IDs or agent instance IDs to those tools.`;
|
|
19
14
|
export const LIST_THREAT_MODELS_SCHEMA = {
|
|
20
15
|
status: z
|
|
21
16
|
.enum(["draft", "analyzing", "analyzed", "reviewed", "approved", "archived"])
|
|
@@ -40,13 +35,11 @@ export function createListThreatModelsHandler(apiClient) {
|
|
|
40
35
|
const path = `/api/threat-models${queryStr ? `?${queryStr}` : ""}`;
|
|
41
36
|
const data = await apiClient.get(path);
|
|
42
37
|
const sanitized = sanitizeResponse(data);
|
|
43
|
-
// Fetch diagram counts for each threat model in parallel
|
|
44
38
|
const threatModels = Array.isArray(sanitized) ? sanitized : [];
|
|
45
39
|
const diagramCounts = await Promise.all(threatModels.map((tm) => apiClient
|
|
46
40
|
.get(`/api/diagrams?linkedThreatModelId=${tm.id}&take=1`)
|
|
47
41
|
.then((res) => res.total ?? 0)
|
|
48
42
|
.catch(() => 0)));
|
|
49
|
-
// Format with clear ID labeling to prevent confusion with scan/agent IDs
|
|
50
43
|
const summary = Array.isArray(sanitized)
|
|
51
44
|
? sanitized.map((tm, i) => ({
|
|
52
45
|
threat_model_id: tm.id,
|
|
@@ -79,4 +72,3 @@ export function createListThreatModelsHandler(apiClient) {
|
|
|
79
72
|
}
|
|
80
73
|
};
|
|
81
74
|
}
|
|
82
|
-
//# sourceMappingURL=list-threat-models.js.map
|