{"_id":"@amlalabs/blastradius","_rev":"2-e808fc21905a8edf4013efbe9b32c3ca","name":"@amlalabs/blastradius","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@amlalabs/blastradius","version":"0.1.0","author":{"name":"Amla Labs"},"license":"MIT","_id":"@amlalabs/blastradius@0.1.0","maintainers":[{"name":"amlalabs_npm","email":"souvik@amlalabs.com"}],"homepage":"https://github.com/amlalabs/blastradius#readme","bugs":{"url":"https://github.com/amlalabs/blastradius/issues"},"bin":{"blastradius":"bin/blastradius.js"},"dist":{"shasum":"7a95479fe6152e9ab0a58fbbf862fa4e729a805b","tarball":"https://registry.npmjs.org/@amlalabs/blastradius/-/blastradius-0.1.0.tgz","fileCount":4,"integrity":"sha512-lRmUgoagQn4v/xP7s6any1Pr2yLq6vCJ3MjnJXu3KSDOEeOIVg2FKyC6F9G8mhlFRZCBiWmUYyQIkSGP/T+oWQ==","signatures":[{"sig":"MEUCIFyuA9pKD9p7YH07UHA4SYhnZ4mcsPOqPn2/qrZsmGo0AiEA46FC8RMC5ZA6yYZiA/0aVr1ikZdWS/+dRAwkBZFaunk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":21932},"engines":{"node":">=16"},"gitHead":"d28a92c4f12eaeda97dd3585b9c22371fa93ca73","scripts":{"test":"node test/shim.test.js"},"_npmUser":{"name":"amlalabs_npm","email":"souvik@amlalabs.com"},"repository":{"url":"git+https://github.com/amlalabs/blastradius.git","type":"git"},"_npmVersion":"11.16.0","description":"Local reachability audit for coding-agent environments (run-time binary fetch; no install hooks)","directories":{},"_nodeVersion":"26.2.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/blastradius_0.1.0_1781390946813_0.9450411895458326","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@amlalabs/blastradius","version":"0.2.0","description":"Local reachability audit for coding-agent environments (run-time binary fetch; no install hooks)","author":{"name":"Amla Labs"},"homepage":"https://github.com/amlalabs/blastradius#readme","bin":{"blastradius":"bin/blastradius.js"},"scripts":{"test":"node test/shim.test.js"},"engines":{"node":">=16"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/amlalabs/blastradius.git"},"gitHead":"77ba6cc20f0b801020d083d83533c7d99165664f","_id":"@amlalabs/blastradius@0.2.0","bugs":{"url":"https://github.com/amlalabs/blastradius/issues"},"_nodeVersion":"24.16.0","_npmVersion":"11.13.0","dist":{"integrity":"sha512-WK0wXDxz+WXPwC2EZqgXDCRSLWmpeC5hHB0D+DzatqU3Po6uaC/RB8NVUyWMw1xY7TTgvJPaAZhxMDi0Z6Ly3g==","shasum":"74d5e84ac1069a75ad504ca0a80b4f780647486f","tarball":"https://registry.npmjs.org/@amlalabs/blastradius/-/blastradius-0.2.0.tgz","fileCount":4,"unpackedSize":21940,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@amlalabs%2fblastradius@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDk2iG3cSRgsm1yZ4U0+EPjA8Y7YhiNeiwt2GBRI+SY9gIgRyCZkEdI8oNk56s8QODYQ4vb4TwSe1AlJLScitKyoOc="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:2fcdfe58-d78d-4155-a3dc-3104e5ae08a4"}},"directories":{},"maintainers":[{"name":"amlalabs_npm","email":"souvik@amlalabs.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/blastradius_0.2.0_1781391282793_0.8318424934793762"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-13T22:49:06.628Z","modified":"2026-06-13T22:54:43.192Z","0.1.0":"2026-06-13T22:49:06.970Z","0.2.0":"2026-06-13T22:54:42.924Z"},"bugs":{"url":"https://github.com/amlalabs/blastradius/issues"},"author":{"name":"Amla Labs"},"license":"MIT","homepage":"https://github.com/amlalabs/blastradius#readme","repository":{"type":"git","url":"git+https://github.com/amlalabs/blastradius.git"},"description":"Local reachability audit for coding-agent environments (run-time binary fetch; no install hooks)","maintainers":[{"name":"amlalabs_npm","email":"souvik@amlalabs.com"}],"readme":"# blastradius\n\nA local diagnostic that shows what a coding agent running as you can reach.\n\n> **Just want to run it?** See **[RUNNING.md](RUNNING.md)** — build, scan,\n> dashboard, and the AI setup, copy-pasteable. TL;DR:\n> `cargo build --release && ./target/release/blastradius dashboard --ai`\n\n## Why this exists\n\nWorktrees are not security boundaries. Coding agents inherit ambient authority —\nyour shell environment, SSH keys, git credentials, cloud profiles, registry\ntokens, sibling repos, shell history, network egress, and filesystem visibility.\n`blastradius` makes that reachable surface visible.\n\nIt proves **reachability, not intent.** It does not claim an agent is malicious,\nthat a token is valid, that a push would be accepted, or that every secret was\nfound. It claims: these files, stores, remotes, and egress routes are reachable\nby code running as this user — and a worktree alone does not constrain that.\n\n## Install\n\n```sh\n# npm wrapper (fetches the binary on first explicit invocation — never on install)\nnpx @amlalabs/blastradius compare\n```\n\nRelease binaries and `SHA256SUMS` are also published on GitHub Releases for manual install.\n\n## What it checks\n\nGrouped by finding class:\n\n**Credentials**\n\n- **Cloud & cluster** — AWS profiles + SSO/CLI token caches, GCP, Azure,\n  Kubernetes config + in-pod service-account token, Docker & podman registry\n  auth, HashiCorp Vault\n- **Package / registry / build** — npm, PyPI, Cargo, Terraform, Maven, Gradle,\n  Composer, RubyGems, pip, NuGet\n- **Data & secrets tooling** — dbt, Databricks, Snowflake, `.pgpass`, GPG keys,\n  SOPS/age, Teleport, password managers, rclone\n- **OS keyring / Secret Service** — GNOME Keyring, KWallet, macOS Keychain\n- **SaaS & agent tokens** — SaaS CLI tokens (Vercel, Netlify, Fly, doctl,\n  Sentry, …) and the agent's own AI-assistant credentials\n- **SSH** — private keys and a reachable ssh-agent (loaded keys usable without\n  the key files)\n- **Browser** — cookie jars & saved passwords (session hijack past password+MFA)\n- **Other** — GitHub/git credential sources (incl. XDG path), secret-named env\n  vars, and shell- / DB-REPL-client history token patterns\n\n**Cross-repo** — sibling repos and lateral `.env` / key / secret files.\n\n**Git write** — remotes + push likelihood, and dangerous git-config directives\n(`alias`, `sshCommand`, `fsmonitor`, content filters, `insteadOf`).\n\n**Process & host** — privilege escalation (docker group / NOPASSWD sudo → root),\nthe post-escalation \"if root\" blast radius, process-memory introspection\n(`ptrace_scope` → dump ssh-agent / browser / password-manager RAM), secrets in\nother processes' command lines, and reachable localhost datastores.\n\n**Persistence** — writable Claude Code control & instruction surface\n(`settings.json`, `.mcp.json`, `CLAUDE.md`), shell rc / editor / login dotfiles,\n`$PATH` shadowing, git hooks, build/CI/dev-env exec sinks, and cron / systemd\ntimers.\n\n**Egress** — outbound reachability (DNS + TLS), proxy mediation, and\ncloud-metadata reachability (always on; the scan's network checks aren't\nconfigurable).\n\nThe credential-store checks are **spec-driven** (~35 stores): each is a data\nentry, so adding one is a few lines — see `src/probes/registry.rs`. The full\ncoverage map is in [docs/claude-code-security-model.md](docs/claude-code-security-model.md) §6a.\n\n## What it never does\n\n- no telemetry · no secret values · no exploit behavior · no repo secret scanning\n- secret values never leave the machine — not in any report, and not in the\n  opt-in `dashboard --ai` request, which carries only the value-free inventory\n- `--ai` is the only feature that sends the value-free findings inventory\n  off-machine; everything else (the egress + cloud-metadata reachability probes\n  the scan always runs, and the dashboard's CDN-loaded UI assets) carries no\n  scan data\n- never writes to repo files, shell/git config, credential stores, or `$HOME`\n  by default\n\n## Dashboard & AI blast-radius analysis\n\n```sh\nblastradius dashboard            # local web dashboard of the reachable surface\nblastradius dashboard --ai       # + AI-generated attack-scenario narratives\n```\n\n`dashboard` runs a scan and serves a local web page (value-free, swept): a\nnarrative walkthrough of the reachable surface. Its reachable-surface rings and\ntallies are **live from the scan** (severities and the full inventory). **It\nalways also runs the §24 retro-hazard scan over every agent transcript on disk**\n(Claude Code, Codex, Cursor, …, across all time) and renders, value-free, which\nhistorical sessions \"already happened and still matter\" today. The benign-vs-risky\nper-session blast-radius score remains an **illustrative teaching fixture**\n(labeled on-page) — there is no live per-session scoring of your own sessions in\nthe dashboard view. The page loads React/Babel and webfonts from a CDN to render\n(those carry no scan data). It binds `0.0.0.0:5321` by default; override with\n`--bind`/`--port`.\n\n> ⚠ The dashboard has **no authentication** and renders your full reachable-credential\n> inventory, escalation paths, post-root blast radius, and which still-reachable\n> credentials your agents already read — a precise targeting map. Binding to\n> `0.0.0.0` exposes that to your whole network — only do so on a trusted network.\n> Use `--bind 127.0.0.1` to restrict it to loopback.\n\n`--ai` additionally asks the OpenAI API to describe, **for your own defensive\nawareness**, how the *reachable* credentials/identities could be chained — attack\npaths, impact, and containment — grounded only in what the scan found.\n\n`--ai` is the **only** feature that sends the findings inventory off-machine, and\nit is opt-in. It transmits ONLY the value-free inventory (finding ids, classes,\nseverities, titles, summaries — the same metadata the local report prints) and\nre-runs the redaction sweep over the exact bytes before sending; **no secret\nvalue, file content, or env value is ever transmitted**. (The scan's egress +\ncloud-metadata reachability probes always run but send no findings, and the\ndashboard's CDN-loaded UI assets carry no scan data.) The key is read from\n`OPENAI_API_KEY` (environment or `./.env`) and used only as the bearer token.\nScenarios are conceptual blast-radius narratives with containment, not exploit\ncode. Omit `--ai` to skip it.\n\n## Network egress probe\n\nEvery scan **always** performs one outbound reachability check: it resolves a\nfixed, well-known anycast endpoint (`1.1.1.1:443`) and opens a single TLS\nconnection to it. There is no flag to configure or disable this — measuring\noutbound reach is part of the audit. No HTTP body and no findings, credentials,\npaths, env vars, repo names, hostnames, usernames, or machine identifiers are\nsent; it reports only whether DNS resolution and the TLS handshake succeeded, the\nresolved IP, and latency. (Any outbound connection necessarily exposes your\nsource IP and a timestamp to the destination.) The scan also probes\ncloud-metadata (169.254.169.254) reachability the same way.\n\n## Usage\n\n```sh\nblastradius scan                 # run the battery once (default command)\nblastradius scan --report        # also write ./blastradius-report.{md,json}\nblastradius scan --output audit  # write audit/blastradius-report.{md,json}\nblastradius compare              # repo-root vs temporary worktree, side by side\nblastradius dashboard            # serve a local web dashboard of the reach\nblastradius dashboard --ai       # + AI attack-scenario narratives (opt-in; sends value-free inventory)\nblastradius sessions             # value-free preview of every discovered transcript\nblastradius audit-history        # retro-hazard scan over all transcripts\nblastradius self-test-redaction  # assert no synthetic secret leaks any renderer\n```\n\nEvery scan runs at full reach automatically — home-wide sibling search, broad\nenv-name heuristics, key NAMES listed (value-free), and the network egress +\ncloud-metadata probes. There are no flags to narrow, scope, or disable any of it.\n\nExit codes: `0` success · `1` runtime error · `2` invalid usage · `3` compare\noutside a git repo · `4` `--fail-on <severity>` threshold met (CI: `--fail-on exposed`).\n\n## Demo\n\n```\n══ worktree comparison ════════════════════════════════════════\n\n  AMBIENT BLAST RADIUS                  repo root      worktree\n  ───────────────────────────────────────────────────────────\n  AWS profiles                          2              2\n  SSH private keys                      3              3\n  secret-like env vars                  4              4\n  sibling repos readable                23             23\n  outbound connectivity                 open           open\n\n  ►  working directory changed.  ambient blast radius UNCHANGED.\n     A git worktree is a directory-level convenience, not a\n     security boundary.\n```\n\n## Interpreting results\n\nReachability is not malice and not validity. A reachable credential may be\nexpired, scoped, or rejected server-side. Severity (`Info`/`Notable`/`Exposed`)\ndescribes exposure; confidence (`Confirmed`/`Likely`/`Possible`/`Unknown`) is\nreported separately for inferred capability such as push likelihood.\n\n## What would contain this\n\n- **Credential substitution** — scoped, short-lived creds per agent.\n- **Filesystem isolation** — mount only the task repo + explicit deps.\n- **Egress control** — default-deny outbound, then allowlist.\n- **Process isolation** — prevent same-user process inspection.\n- **Server-side enforcement** — branch protection, review, token scopes.\n\nFor a concrete worked example of one such containment layer — what the Claude Code\nbubblewrap sandbox does and does not contain, audited against the open-source\n`sandbox-runtime` — see [docs/claude-code-security-model.md](docs/claude-code-security-model.md).\n\n## Development\n\n```sh\ncargo test                          # unit + fixture + worktree tests\ncargo run -- compare\n```\n\n## License\n\nMIT © Amla Labs\n","readmeFilename":"README.md"}