A local diagnostic that shows what a coding agent running as you can reach.
Just want to run it? See RUNNING.md — build, scan, dashboard, and the AI setup, copy-pasteable. TL;DR:
cargo build --release && ./target/release/blastradius dashboard --ai
Worktrees are not security boundaries. Coding agents inherit ambient authority —
your shell environment, SSH keys, git credentials, cloud profiles, registry
tokens, sibling repos, shell history, network egress, and filesystem visibility.
blastradius makes that reachable surface visible.
It proves reachability, not intent. It does not claim an agent is malicious, that a token is valid, that a push would be accepted, or that every secret was found. It claims: these files, stores, remotes, and egress routes are reachable by code running as this user — and a worktree alone does not constrain that.
# npm wrapper (fetches the binary on first explicit invocation — never on install)
npx @amlalabs/blastradius compareRelease binaries and SHA256SUMS are also published on GitHub Releases for manual install.
Grouped by finding class:
Credentials
- Cloud & cluster — AWS profiles + SSO/CLI token caches, GCP, Azure, Kubernetes config + in-pod service-account token, Docker & podman registry auth, HashiCorp Vault
- Package / registry / build — npm, PyPI, Cargo, Terraform, Maven, Gradle, Composer, RubyGems, pip, NuGet
- Data & secrets tooling — dbt, Databricks, Snowflake,
.pgpass, GPG keys, SOPS/age, Teleport, password managers, rclone - OS keyring / Secret Service — GNOME Keyring, KWallet, macOS Keychain
- SaaS & agent tokens — SaaS CLI tokens (Vercel, Netlify, Fly, doctl, Sentry, …) and the agent's own AI-assistant credentials
- SSH — private keys and a reachable ssh-agent (loaded keys usable without the key files)
- Browser — cookie jars & saved passwords (session hijack past password+MFA)
- Other — GitHub/git credential sources (incl. XDG path), secret-named env vars, and shell- / DB-REPL-client history token patterns
Cross-repo — sibling repos and lateral .env / key / secret files.
Git write — remotes + push likelihood, and dangerous git-config directives
(alias, sshCommand, fsmonitor, content filters, insteadOf).
Process & host — privilege escalation (docker group / NOPASSWD sudo → root),
the post-escalation "if root" blast radius, process-memory introspection
(ptrace_scope → dump ssh-agent / browser / password-manager RAM), secrets in
other processes' command lines, and reachable localhost datastores.
Persistence — writable Claude Code control & instruction surface
(settings.json, .mcp.json, CLAUDE.md), shell rc / editor / login dotfiles,
$PATH shadowing, git hooks, build/CI/dev-env exec sinks, and cron / systemd
timers.
Egress — outbound reachability (DNS + TLS), proxy mediation, and cloud-metadata reachability (always on; the scan's network checks aren't configurable).
The credential-store checks are spec-driven (~35 stores): each is a data
entry, so adding one is a few lines — see src/probes/registry.rs. The full
coverage map is in docs/claude-code-security-model.md §6a.
- no telemetry · no secret values · no exploit behavior · no repo secret scanning
- secret values never leave the machine — not in any report, and not in the
opt-in
dashboard --airequest, which carries only the value-free inventory --aiis the only feature that sends the value-free findings inventory off-machine; everything else (the egress + cloud-metadata reachability probes the scan always runs, and the dashboard's CDN-loaded UI assets) carries no scan data- never writes to repo files, shell/git config, credential stores, or
$HOMEby default
blastradius dashboard # local web dashboard of the reachable surface
blastradius dashboard --ai # + AI-generated attack-scenario narrativesdashboard runs a scan and serves a local web page (value-free, swept): a
narrative walkthrough of the reachable surface. Its reachable-surface rings and
tallies are live from the scan (severities and the full inventory). It
always also runs the §24 retro-hazard scan over every agent transcript on disk
(Claude Code, Codex, Cursor, …, across all time) and renders, value-free, which
historical sessions "already happened and still matter" today. The benign-vs-risky
per-session blast-radius score remains an illustrative teaching fixture
(labeled on-page) — there is no live per-session scoring of your own sessions in
the dashboard view. The page loads React/Babel and webfonts from a CDN to render
(those carry no scan data). It binds 0.0.0.0:5321 by default; override with
--bind/--port.
⚠ The dashboard has no authentication and renders your full reachable-credential inventory, escalation paths, post-root blast radius, and which still-reachable credentials your agents already read — a precise targeting map. Binding to
0.0.0.0exposes that to your whole network — only do so on a trusted network. Use--bind 127.0.0.1to restrict it to loopback.
--ai additionally asks the OpenAI API to describe, for your own defensive
awareness, how the reachable credentials/identities could be chained — attack
paths, impact, and containment — grounded only in what the scan found.
--ai is the only feature that sends the findings inventory off-machine, and
it is opt-in. It transmits ONLY the value-free inventory (finding ids, classes,
severities, titles, summaries — the same metadata the local report prints) and
re-runs the redaction sweep over the exact bytes before sending; no secret
value, file content, or env value is ever transmitted. (The scan's egress +
cloud-metadata reachability probes always run but send no findings, and the
dashboard's CDN-loaded UI assets carry no scan data.) The key is read from
OPENAI_API_KEY (environment or ./.env) and used only as the bearer token.
Scenarios are conceptual blast-radius narratives with containment, not exploit
code. Omit --ai to skip it.
Every scan always performs one outbound reachability check: it resolves a
fixed, well-known anycast endpoint (1.1.1.1:443) and opens a single TLS
connection to it. There is no flag to configure or disable this — measuring
outbound reach is part of the audit. No HTTP body and no findings, credentials,
paths, env vars, repo names, hostnames, usernames, or machine identifiers are
sent; it reports only whether DNS resolution and the TLS handshake succeeded, the
resolved IP, and latency. (Any outbound connection necessarily exposes your
source IP and a timestamp to the destination.) The scan also probes
cloud-metadata (169.254.169.254) reachability the same way.
blastradius scan # run the battery once (default command)
blastradius scan --report # also write ./blastradius-report.{md,json}
blastradius scan --output audit # write audit/blastradius-report.{md,json}
blastradius compare # repo-root vs temporary worktree, side by side
blastradius dashboard # serve a local web dashboard of the reach
blastradius dashboard --ai # + AI attack-scenario narratives (opt-in; sends value-free inventory)
blastradius sessions # value-free preview of every discovered transcript
blastradius audit-history # retro-hazard scan over all transcripts
blastradius self-test-redaction # assert no synthetic secret leaks any rendererEvery scan runs at full reach automatically — home-wide sibling search, broad env-name heuristics, key NAMES listed (value-free), and the network egress + cloud-metadata probes. There are no flags to narrow, scope, or disable any of it.
Exit codes: 0 success · 1 runtime error · 2 invalid usage · 3 compare
outside a git repo · 4 --fail-on <severity> threshold met (CI: --fail-on exposed).
══ worktree comparison ════════════════════════════════════════
AMBIENT BLAST RADIUS repo root worktree
───────────────────────────────────────────────────────────
AWS profiles 2 2
SSH private keys 3 3
secret-like env vars 4 4
sibling repos readable 23 23
outbound connectivity open open
► working directory changed. ambient blast radius UNCHANGED.
A git worktree is a directory-level convenience, not a
security boundary.
Reachability is not malice and not validity. A reachable credential may be
expired, scoped, or rejected server-side. Severity (Info/Notable/Exposed)
describes exposure; confidence (Confirmed/Likely/Possible/Unknown) is
reported separately for inferred capability such as push likelihood.
- Credential substitution — scoped, short-lived creds per agent.
- Filesystem isolation — mount only the task repo + explicit deps.
- Egress control — default-deny outbound, then allowlist.
- Process isolation — prevent same-user process inspection.
- Server-side enforcement — branch protection, review, token scopes.
For a concrete worked example of one such containment layer — what the Claude Code
bubblewrap sandbox does and does not contain, audited against the open-source
sandbox-runtime — see docs/claude-code-security-model.md.
cargo test # unit + fixture + worktree tests
cargo run -- compareMIT © Amla Labs