Skip to content

Repository files navigation

blastradius

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

Why this exists

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.

Install

# npm wrapper (fetches the binary on first explicit invocation — never on install)
npx @amlalabs/blastradius compare

Release binaries and SHA256SUMS are also published on GitHub Releases for manual install.

What it checks

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.

What it never does

  • 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 --ai request, which carries only the value-free inventory
  • --ai is 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 $HOME by default

Dashboard & AI blast-radius analysis

blastradius dashboard            # local web dashboard of the reachable surface
blastradius dashboard --ai       # + AI-generated attack-scenario narratives

dashboard 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.0 exposes that to your whole network — only do so on a trusted network. Use --bind 127.0.0.1 to 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.

Network egress probe

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.

Usage

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 renderer

Every 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).

Demo

══ 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.

Interpreting results

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.

What would contain this

  • 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.

Development

cargo test                          # unit + fixture + worktree tests
cargo run -- compare

License

MIT © Amla Labs

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages