{"slug": "show-hn-an-audit-for-ai-agents-headed-into-air-gapped-networks", "title": "Show HN: An audit for AI agents headed into air-gapped networks", "summary": "PrashnaLabs released agent-blast-radius, an agent skill that audits an AI agent's codebase for external dependencies and in-enclave blast radius before air-gapped deployment, writing a BLAST_RADIUS.md report with file:line evidence, OWASP agentic (ASI) IDs and a minimal fix per path. A run on the deliberately vulnerable examples/vulnerable-agent returned a CRITICAL verdict with 4 critical, 7 high and 6 medium findings and a LEAKY boundary showing 8 paths out, including a hosted support-agent model at agent.py:51 that sends whole context on every call and an unpinned issue-tracker MCP server at .mcp.json:3-5. The skill installs via /plugin install agent-blast-radius --marketplace PrashnaLabs/agent-blast-radius in Claude Code 2.1.275 or later, and the repository is private for now, requiring read access through existing git credentials or a GITHUB_TOKEN.", "body_md": "**Check your agent for vulnerabilities before it goes into an air-gapped environment.**\n\n`agent-blast-radius` is an agent skill that reads an AI agent's codebase and answers two questions:\n\n1. **Boundary:** does anything in this agent need, or reach, the outside world? That covers hosted\nmodel APIs, telemetry that phones home, packages and models fetched at start, SaaS connectors\nand hard-coded external hosts.\n2. **Blast radius:** inside the enclave, if the agent is steered by a poisoned document, an\ninsider or a compromised host, what can it do?\n\nIt writes a `BLAST_RADIUS.md` report with `file:line` evidence, the failure pattern each finding\nmatches, OWASP agentic (ASI) ids, and the smallest fix for each path.\n\nAn air gap removes the network path out. It does not make an agent safe.\n\n- **Agents leak by default.** Hosted model clients send the whole context out on every call.\nSeveral frameworks export traces or telemetry to a vendor unless you opt out. In a sealed\nenclave these calls fail, and in a leaky one the data leaves.\n- **Agents fetch code at start.**`npx -y some-mcp-server` ,`pip install` in a start script, and\nmodel downloads on first use all break the first time the agent boots inside the gap. Or, with a\nmirror, they run whatever the registry served that day.\n- **The damage happens inside.** Documented failures show agents deleting production databases and\ntheir backups with one call, leaking private data after reading a poisoned ticket, and serving as\na path from one compromised laptop to other engineers' machines. None of these needed the\ninternet. They needed an agent with more reach than its task.\n\nFrom [`examples/sample-report.md`](https://github.com/PrashnaLabs/agent-blast-radius/blob/main/examples/sample-report.md), a run on the deliberately vulnerable\n[`examples/vulnerable-agent`](https://github.com/PrashnaLabs/agent-blast-radius/blob/main/examples/vulnerable-agent):\n\n```\n**Verdict:** CRITICAL · 4 critical, 7 high, 6 medium, 0 low\n**Boundary:** LEAKY · 8 paths out\n\n| What | Where | Crosses | When | Switch | Severity |\n| Hosted model (support agent) | agent.py:51 | whole context: tickets, SQL results, emails | every call | none | HIGH |\n| Issue-tracker MCP, unpinned | .mcp.json:3-5 (npx -y ...) | code in, newest release | every start | none | HIGH |\n\n1. **CRITICAL**: ticket or web page → support agent → run_sql (DATABASE_URL, model-written SQL)\n   → any write, delete or drop, no gate\n   - Pattern: P02 · OWASP: ASI01, ASI02, ASI03\n   - Fix: remove run_sql from the agent that reads tickets; typed read tools on a read-only role.\n```\n\nThe report also includes a reach map (agent × tool × credential × gate), findings for each dimension, a detect-and-recover section, and a list of what static reading cannot prove.\n\nInside Claude Code 2.1.275 or later:\n\n```\n/plugin install agent-blast-radius --marketplace PrashnaLabs/agent-blast-radius\n```\n\nOn older versions, add the marketplace first, then install:\n\n```\n/plugin marketplace add PrashnaLabs/agent-blast-radius\n/plugin install agent-blast-radius@prashnalabs\n```\n\nThe repository is private for now. Installing needs read access to it, and Claude Code clones it with your\nexisting git credentials, so make sure `git clone git@github.com:PrashnaLabs/agent-blast-radius.git`\nworks for you first (SSH key, or `gh auth login`). If background updates cannot reach it, export a\n`GITHUB_TOKEN` with read access.\n\nCopy the skill folder into your agent's skills directory.\n\n```\ngit clone git@github.com:PrashnaLabs/agent-blast-radius.git\ncp -r agent-blast-radius/skills/agent-blast-radius ~/.claude/skills/          # all projects\n# or: cp -r agent-blast-radius/skills/agent-blast-radius <your-repo>/.claude/skills/\n```\n\nThe folder follows the Agent Skills layout (`SKILL.md` + `references/` + `scripts/`), so other\nhosts that read Agent Skills can load it from their own skills directory. The skill itself needs no\nnetwork access.\n\nIn the repo you want audited, ask your agent:\n\n```\nis this agent ready for an air-gapped deployment?\n```\n\nor \"audit my agent's blast radius\", or \"is this agent safe to ship?\".\n\nThe scanner also runs on its own and prints JSON evidence:\n\n```\npython3 skills/agent-blast-radius/scripts/inventory.py path/to/repo\n```\n\n|  | Dimension | Question | \n|---|---|---|\n| D8 | Boundary | What needs or reaches outside the enclave, and is there a switch to seal it? | \n| D1 | Untrusted input | What attacker-controllable text reaches the context? | \n| D2 | Reach | What systems, data and credentials can the agent touch? | \n| D3 | Privilege fit | Is each credential scoped to the task? | \n| D4 | Irreversibility | Which reachable actions cannot be undone? | \n| D5 | Egress | Where can data go? | \n| D6 | Gates | What stands between the model's decision and the action, enforced in code? | \n| D7 | Identity & audit | Can you prove who did what, and stop it? | \n\nThe report has two verdict lines:\n\n- **Boundary:** SEALED (nothing crosses), BRITTLE (nothing leaks, but something is fetched at\nstart), or LEAKY (context leaves by default).\n- **Blast radius:** CRITICAL (a toxic path or lethal trifecta), EXPOSED (high-severity reach), or\nCONTAINED (every irreversible action is gated and audited).\n\nThe full rules are in [`references/rubric.md`](https://github.com/PrashnaLabs/agent-blast-radius/blob/main/skills/agent-blast-radius/references/rubric.md).\n\nFrameworks: LangChain, LangGraph, deepagents, CrewAI, OpenAI Agents SDK, Claude Agent SDK, Vercel AI SDK, raw tool-calling loops, and MCP client configs, in Python and TypeScript, plus Dockerfiles and start scripts.\n\nTwo halves keep the judgment honest:\n\n1. **`scripts/inventory.py`** : a deterministic, read-only scanner that uses only the Python\nstandard library and needs no network. It never imports or runs your code and never prints\nsecret values; credentials appear by name and location only. It lists every external host\nfound in code, and the same repo always gives the same JSON.\n2. **`SKILL.md`** : the agent reads each tool and boundary crossing the scanner points at, decides\nwhat really crosses or is reachable, traces the toxic paths, and scores them against a fixed\nrubric. Whether a send tool's \"only call this after the user confirms\" is enforced by the server\nor only written in a docstring needs reading the code. A linter cannot decide it.\n\nFindings cite patterns from\n[`references/patterns.md`](https://github.com/PrashnaLabs/agent-blast-radius/blob/main/skills/agent-blast-radius/references/patterns.md): documented agent\nfailures and risky library defaults, described without naming the organisations involved.\n\n- Read-only. The only file it writes is `BLAST_RADIUS.md` , and it asks before overwriting one.\n- It never runs, installs or connects to anything in the target repo.\n- Secret values are never printed.\n- The scanner runs fully offline.\n\n- Static only. It cannot see network policy, IAM policies, token scopes, or the tools a remote MCP server serves at runtime. These go under \"Unverifiable statically\", with where to check.\n- The scanner matches line by line, so it can miss calls split across lines. The reading step covers most of these.\n- The scanner takes about 1 s of CPU per MB of source. In a large monorepo, point it at the agent's directory.\n\n```\nuvx pytest -q tests\n```\n\n`tests/test_inventory.py` checks the scanner against the fixture: every expected hit and no extra\nhits, the build-time versus runtime install rule, the external host summary, secret redaction,\nvendor-directory skipping and the per-rule cap.\n[`examples/vulnerable-agent/expected.md`](https://github.com/PrashnaLabs/agent-blast-radius/blob/main/examples/vulnerable-agent/expected.md) is the golden\nset for the skill itself.\n\nApache-2.0", "url": "https://wpnews.pro/news/show-hn-an-audit-for-ai-agents-headed-into-air-gapped-networks", "canonical_source": "https://github.com/PrashnaLabs/agent-blast-radius", "published_at": "2026-11-11 16:59:55+00:00", "updated_at": "2026-11-11 17:21:51.311444+00:00", "lang": "en", "topics": ["ai-agents", "ai-safety", "ai-tools", "ai-policy"], "entities": ["PrashnaLabs", "agent-blast-radius", "Claude Code", "OWASP", "agent.py", "GitHub"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/show-hn-an-audit-for-ai-agents-headed-into-air-gapped-networks", "markdown": "https://wpnews.pro/news/show-hn-an-audit-for-ai-agents-headed-into-air-gapped-networks.md", "text": "https://wpnews.pro/news/show-hn-an-audit-for-ai-agents-headed-into-air-gapped-networks.txt", "jsonld": "https://wpnews.pro/news/show-hn-an-audit-for-ai-agents-headed-into-air-gapped-networks.jsonld"}}