Documentation Index
Fetch the complete documentation index at: https://quintsecurity.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Security Graph: Attack Path Visualization for AI Agents
The Precedent
Wiz built a $32B company partly because their Security Graph made invisible risk visible. The UX thesis: show a CISO “this misconfigured S3 bucket is reachable from this compromised EC2 via this role” as a traversable graph, and they immediately understand blast radius. Every major cloud security vendor copied the pattern:
| Vendor | Graph Brand | Key UX Move |
|---|
| Wiz | Security Graph | Left-to-right attack path flow. Colored icons per resource type (green=network, orange=compute, blue=identity, teal=storage). Badge counts on nodes. “Click to expand” clusters. “View on Security Graph” link from every alert. Crown jewel terminus nodes highlighted. |
| Orca Security | Unified Data Model | Dark-themed horizontal flow with diamond-shaped risk nodes between resources. Split pane: “Attack Flow” graph on top, “Attack Story” narrative below explaining each hop in plain English. Business Impact Score per path. MITRE ATT&CK tags on each vector. |
| Microsoft Defender | Cloud Security Graph | Simple Attacker -> Internet -> Vulnerability -> Sensitive Data linear path as conceptual intro. Full product has “Cloud Security Explorer” with graph-based query builder (KQL-style). Blast radius view from any choke point. Now covers AI agents explicitly (2026 update). |
| Palo Alto Prisma Cloud | Evidence Graph | ”Intelligent Network Graph” combining network + config data. DSPM findings injected into attack path nodes so you see data classification at the terminus. Natural language queries via Prisma Copilot. |
| Cisco (ex-Lightspin) | Attack Path Engine | Graph-theory core from Lightspin acquisition (2023). Prioritized paths by severity. Agentless scanning. Integrated into Panoptica/ET&I. |
What They All Share
Every implementation follows the same pattern:
- Left-to-right directed graph from entry point (Internet/Attacker) to crown jewel (database/model/PII)
- Typed nodes with distinct icons and colors per category
- Typed edges showing relationship semantics (permissions, network, data flow)
- Click-to-expand on clustered nodes (e.g., “8 Application Endpoints”)
- Narrative companion alongside the graph explaining the path in English
- Severity scoring on the path as a whole, not just individual nodes
Screenshot Reference (Wiz AI-SPM Attack Path)
Wiz’s AI-specific attack path visualization (2025) shows:
Internet -> Application Endpoints (8, expandable) -> EC2 Instance (redhat-customer-related-v1, with CVE-2022-21724 finding) -> EC2IAMFullAccessRole -> s3-for-ai-training-test (S3 Bucket) -> test-bedrock-model (Bedrock Custom Model)
This is the exact pattern we need, but for AI agent sessions instead of cloud infrastructure.
Quint’s Version: The Agent Security Graph
Nobody is doing this for AI agents yet. Wiz shows “Internet -> VM -> IAM Role -> S3 -> Bedrock Model.” We show “Claude Code session on Amer’s laptop -> Bash tool -> MCP postgres server -> production RDS -> PII table.”
The insight: Wiz maps infrastructure attack paths. Quint maps agent capability paths — what an autonomous agent can reach given its tools, credentials, and MCP connections, cross-referenced against what it actually did.
Node Taxonomy
type NodeKind =
// Physical layer
| 'machine' // Amer's MacBook Pro (hostname, OS, IP)
| 'user' // amer@quintai.dev (identity, role)
// Agent layer
| 'agent_session' // Claude Code session abc-123 (pid, start_time, model)
| 'agent_platform' // Claude Code | Cursor | Copilot | Aider
| 'model' // claude-opus-4-7 | gpt-4o | claude-sonnet-4
// Capability layer
| 'mcp_server' // github | postgres | slack | filesystem
| 'tool' // Bash | Read | Write | list_repos | query
| 'permission' // "allow Bash(*)" | "allow Read(/Users/**)"
// Resource layer
| 'cloud_resource' // RDS instance | S3 bucket | ECS service | Lambda
| 'local_resource' // ~/.ssh/id_rsa | .env | ~/.aws/credentials
| 'api_endpoint' // api.quintai.dev/v1/events | github.com/api/v3
// Data layer
| 'data_class' // PII | credentials | source_code | financial
| 'secret' // AWS_SECRET_ACCESS_KEY | GITHUB_TOKEN | DB password
Edge Taxonomy
type EdgeKind =
// Structural
| 'runs_on' // agent_session -> machine
| 'authored_by' // agent_session -> user
| 'powered_by' // agent_session -> model
| 'platform_is' // agent_session -> agent_platform
| 'spawned_from' // child_session -> parent_session (subagents)
// Capability
| 'has_tool' // agent_session -> tool
| 'connects_to' // mcp_server -> cloud_resource | api_endpoint
| 'serves_tool' // mcp_server -> tool
| 'grants' // permission -> tool (with scope)
// Data flow (observed)
| 'read' // tool -> local_resource | cloud_resource
| 'wrote' // tool -> local_resource | cloud_resource
| 'invoked' // agent_session -> tool (with timestamp, args hash)
| 'exfiltrated_to' // tool -> api_endpoint (outbound data)
// Credential chain
| 'inherits_creds' // mcp_server -> machine (ambient creds)
| 'has_access_to' // secret -> cloud_resource
| 'exposed_in' // secret -> local_resource (.env file)
// Classification
| 'contains' // cloud_resource -> data_class
| 'classified_as' // local_resource -> data_class
The Headline Query
“Show me the blast radius of compromising this agent session.”
Traverse outward from an agent_session node:
- What
tools does it have access to?
- For each tool, what
mcp_servers provide it?
- For each MCP server, what
cloud_resources and api_endpoints does it connect to?
- For each cloud resource, what
data_class does it contain?
- For each tool, what
local_resources has it actually read/written (observed edges)?
- What
secrets are reachable via ambient credential inheritance?
The result is a subgraph. Highlight it. That is the blast radius.
The inverse query is equally powerful: “What agent sessions can reach this production database?” Traverse inward from the cloud_resource node.
UX Flow
Entry Point: Session Dashboard
User clicks a session row in the existing sessions list. Currently opens session detail view. New: add a “Graph” tab alongside “Timeline” and “Events.”
Graph View
+------------------------------------------------------------------+
| Session: abc-123 [Timeline] [Events] [Graph] |
+------------------------------------------------------------------+
| |
| [Amer]--authored_by-->[Claude Code]--runs_on-->[MacBook Pro] |
| \ | |
| \ |--has_tool-->[Bash] |
| \ |--has_tool-->[Read] |
| \ |--has_tool-->[Write] |
| powered_by |--has_tool-->[mcp_postgres.query] |
| \ | | |
| v | connects_to |
| [claude-opus-4-7] | | |
| | v |
| spawned_from [prod RDS] |
| | | |
| v contains |
| [subagent-1] | |
| v |
| [PII: emails] |
| |
+------------------------------------------------------------------+
| Blast Radius: 3 cloud resources, 2 data classes, 14 local files |
| [Expand All] [Show Only Observed] [Export] |
+------------------------------------------------------------------+
Interactions
- Click any node -> side panel shows detail (for agent_session: pid, duration, event count; for cloud_resource: ARN, region, data classes)
- Click “Blast Radius” on any node -> highlights all reachable nodes with pulsing animation
- Click “Can Reach” on any resource -> highlights all sessions/tools that can reach it (inverse traversal)
- Toggle “Show Only Observed” -> dims capability edges, highlights only edges with actual observed events (tool invocations, file reads, network calls)
- Drag to rearrange -> force-directed layout snaps back; manual positions persist per session
Divergence Overlay
This is the Quint-specific innovation no cloud security vendor has. Our three-tier architecture (Proxy intent / ES truth / Cloud storage) gives us two parallel views of reality:
- Intent edges (green): what the agent said it would do (from proxy/MCP interception)
- Truth edges (red): what actually happened (from Endpoint Security framework)
- Divergence: where intent and truth differ. Visually: red glow on edges where ES observed activity the proxy didn’t predict, or vice versa.
Example: Agent says “I’ll read config.yaml” (intent edge to config.yaml). ES observes reads to config.yaml AND ~/.ssh/id_rsa (truth edge to both). The ~/.ssh/id_rsa edge glows red — divergence detected. That is the signal.
Graph Backend
Option Analysis
| Approach | Latency | Complexity | Already in Stack | Verdict |
|---|
| Postgres recursive CTE | ~50ms for 3-hop on 10K nodes | Low | Yes (RDS) | Start here |
| Postgres + Apache AGE | ~20ms, native graph queries | Medium | Yes (extension) | Upgrade path |
| Memgraph | <10ms, Cypher native | Medium | Yes (already eval’d) | If graph queries dominate |
| Neo4j | <10ms | High (new infra) | No | Overkill for now |
Recommendation: Postgres recursive CTE, migrate to AGE when query complexity demands it.
The graph is small per-org. A design partner with 50 machines, 200 agent sessions/day, 20 MCP servers = ~5K nodes, ~15K edges. Postgres handles this trivially. Recursive CTEs with WITH RECURSIVE give us variable-depth traversal. We already have RDS. Zero new infrastructure.
Schema Sketch
CREATE TABLE graph_nodes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
org_id UUID NOT NULL REFERENCES organizations(id),
kind TEXT NOT NULL, -- 'agent_session', 'tool', 'cloud_resource', etc.
external_id TEXT, -- session UUID, ARN, hostname, etc.
label TEXT NOT NULL, -- display name
metadata JSONB, -- kind-specific properties
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE graph_edges (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
org_id UUID NOT NULL REFERENCES organizations(id),
kind TEXT NOT NULL, -- 'has_tool', 'connects_to', 'read', etc.
source_id UUID NOT NULL REFERENCES graph_nodes(id),
target_id UUID NOT NULL REFERENCES graph_nodes(id),
observed BOOLEAN DEFAULT false, -- capability vs actual
metadata JSONB, -- timestamps, event count, args hash
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX idx_edges_source ON graph_edges(org_id, source_id);
CREATE INDEX idx_edges_target ON graph_edges(org_id, target_id);
CREATE INDEX idx_nodes_kind ON graph_nodes(org_id, kind);
Blast Radius Query (Recursive CTE)
WITH RECURSIVE reachable AS (
-- Seed: the selected node
SELECT target_id AS node_id, 1 AS depth, ARRAY[source_id, target_id] AS path
FROM graph_edges
WHERE source_id = $1 AND org_id = $2
UNION ALL
-- Traverse outward
SELECT e.target_id, r.depth + 1, r.path || e.target_id
FROM graph_edges e
JOIN reachable r ON e.source_id = r.node_id
WHERE e.org_id = $2
AND e.target_id != ALL(r.path) -- prevent cycles
AND r.depth < 6 -- max depth
)
SELECT DISTINCT n.*, r.depth, r.path
FROM reachable r
JOIN graph_nodes n ON n.id = r.node_id
ORDER BY r.depth;
Graph Frontend
XYFlow (@xyflow/react v12) — already in quint-cloud-dashboard/package.json. No new dependency.
Layout strategy:
- Dagre (via
@dagrejs/dagre) for the default left-to-right hierarchical layout matching Wiz’s visual language
- D3-Force as an alternative toggle for exploring dense graphs
- Custom node components per
NodeKind with distinct icons and color families
- Animated edges for “observed” (data flowing) vs static edges for “capability” (could flow)
- Edge labels showing relationship type on hover
Engineering Effort
| Phase | Work | Estimate |
|---|
| 1. Schema + API | graph_nodes/graph_edges tables, migration, CRUD endpoints, recursive CTE blast-radius query | 3 days |
| 2. Graph Population | Pipeline worker that builds graph from existing session/event data. On session create: add agent_session + tool nodes. On MCP registration: add mcp_server + connects_to edges. On observed event: mark edge as observed. | 4 days |
| 3. Frontend: Graph Tab | New tab in session detail. XYFlow canvas with Dagre layout. Custom node components (8 kinds). Click-to-select, side panel. | 5 days |
| 4. Blast Radius | ”Blast Radius” button triggers CTE query, highlights subgraph with animation. Inverse “Can Reach” query. | 2 days |
| 5. Divergence Overlay | Compare intent vs truth edges. Red glow on divergent edges. Toggle switch. | 3 days |
| 6. Polish | Export (SVG/PNG), keyboard nav, minimap, responsive, loading states | 2 days |
Total: ~19 days for one engineer. Call it 4 weeks with testing and iteration.
Phase 1-3 are the MVP. Ship that to design partners. Phases 4-6 are the differentiation.
Why This Wins
Wiz showed CISOs that isolated CVEs are noise but connected attack paths are signal. We do the same thing for AI agents: isolated tool calls are noise, but “this Claude session can reach prod Postgres via MCP, and it read your SSH keys, and the intent didn’t match” — that is the signal no one else surfaces.
The divergence overlay is the moat. Cloud security vendors compare config-vs-runtime. We compare intent-vs-truth at the agent behavioral layer. Nobody else has both the proxy (intent) and ES (truth) data to build this view.