BlastRadius

Fault sequence · elapsed time

Nine seconds,
start to finish

An agent is doing something routine. This is one documented incident, but the sequence is not specific to the company it happened to.

  1. 00:00

    The agent hits a credential mismatch mid-task.

  2. 00:01

    Rather than stopping, it goes looking for something that will authenticate.

  3. 00:03

    It finds a token in a file with nothing to do with its task. Not an exhaustive search — one carelessly placed file was enough.

  4. 00:04

    The token was issued months ago for one narrow job. Nobody noticed it also carried authority over the entire account, because the platform never offered a way to scope it down.

    This is the only second that matters. Everything before it is ordinary; everything after it is arithmetic.

  5. 00:09

    One API call. The production volume is gone, and so are the backups — they were stored inside the volume they were meant to protect.

Nothing in that loop knew what the credential it picked up could do.

Around thirty hours to recover most of it. The newest backup held anywhere else was three months old. This has happened.

Install

One command, nothing to install

$ npx @mediaforge/blastradius --resolve

Node 20+. Zero dependencies — there is nothing to audit but the tool itself. Scoped because npm already has a blast-radius; installed globally, the command is just blastradius. Free, no account, no telemetry, and nothing is uploaded: discovery runs entirely on your machine, and resolution talks only to the provider that issued each credential.

As a CI gate

$ blastradius --resolve --fail-on severe

Exit 0 clean, 1 at or above threshold, 2 error. Credentials whose privileges could not be determined fail by default; --allow-unknown opts out if you consciously accept that trade.

Why

Scanners find credentials.
They do not say what they reach.

TruffleHog, GitGuardian, gitleaks and GitHub's native scanner all answer the same question well: is there a credential here, and is it live?

Nobody answers the two questions that actually predicted the sequence above.

What is the worst thing this credential can do?
To a conventional scanner, a live token and a live token that can drop your database are the same finding.
Can the agent on this machine reach it?
Reachability is not the git index. It is dotfiles, the shell environment, and MCP server definitions — where credentials sit in plaintext, outside the repository, invisible to anything that only reads what you committed.

BlastRadius resolves each credential's privileges against the issuing provider's own introspection endpoint, then ranks findings by what they would destroy. Not by token shape. Not by what the token was for.

Output

What a report looks like

Every line below is printed by the tool itself, not redrawn for the page. Only the closing block is cut for length: a real run ends by listing what it did not cover. Reports describe what a credential can do, not which scopes it holds.

$ blastradius --resolve
CATASTROPHIC Railway aaaa************a4f1
             Railway account ops@example.com
             can delete databases, volumes, or bucket contents
             can delete backups or snapshots
             can delete projects, services, or environments
             can manage members or issue further credentials (privilege escalation)
             can read environment variables or stored secrets
             can trigger deployments or run code
             ↳ can destroy data AND its backups — unrecoverable
             found in scripts/add-domain.sh:14
             fix: Replace this account token with a project token scoped to
             the single environment that needs it — account tokens reach
             every workspace you belong to.

SEVERE       Supabase eyJb************mnop
             Supabase service_role key (project ffqkmtxs)
             can delete databases, volumes, or bucket contents
             can read customer or application data
             can modify application data
             found in agent config ~/.cursor/mcp.json

UNKNOWN      Cloudflare cccc************cccc
             Cloudflare API token 9c1f0b
             privileges COULD NOT be determined — do not read this as safe
             Cloudflare's verify endpoint returns status only — it does not
             expose the token's permission groups, so its reach cannot be
             determined here.
             found in env CF_API_TOKEN

3 credentials reachable, worst case: CATASTROPHIC

The Railway finding is catastrophic rather than merely severe because one credential reaches the data and the way back. Destroying data is recoverable. Destroying backups is survivable. Ranking both together as just another severe finding is the mistake that turns an incident into an extinction event.

The Cloudflare finding is the important one. It says the tool could not work out what that token reaches, and refuses to let you read that as safe. Cloudflare's verify endpoint returns status without policies — a token cannot read its own permissions. Inventing a scope mapping to produce a tidier report is exactly the confident-and-wrong output this tool exists to prevent.

Constraints

What it will not do

A tool that reads every credential on a developer's machine is itself a target. These are enforced in code, not promised in a README.

  1. It never prints a raw secret

    Everything user-facing goes through a fingerprint. Error messages are scrubbed too — there is a test for it.

  2. It never sends a credential anywhere but its issuer

    Each provider declares the hosts it may contact. A guard blocks everything else and all plaintext HTTP, and re-checks every redirect hop rather than only the first request. Wildcards are rejected. It narrows what reviewing a contributed module demands — it does not remove the need to read it, because a module runs when it is imported and a declared hostname is only ever checked for shape, never for whether it is really that provider.

  3. It never reports unknown as safe

    Every failure path degrades to unknown, never to fine. Unknown renders louder than low and fails CI by default. A gate that passes on "we couldn't tell" teaches people to trust a green tick that means nothing.

  4. It never claims a clean bill of health

    An empty result says "nothing matched the providers we ship" — because that is all it means. Unfamiliar credentials sitting under a secret-shaped name are reported as visible ignorance rather than left silently absent. A token with no distinctive shape, stored under a name that gives nothing away, is missed entirely — and every report says so in as many words.

Resolution is opt-in for the same reason. Discovery is inert and offline; touching third-party accounts with every secret on your laptop is a materially different act, so it takes an explicit --resolve.

Coverage

Six providers, and what each can determine

Coverage is deliberately narrow. A wrong "this token is harmless" is worse than no answer, so a provider ships only when its scope mapping can be proven against the live API. A narrow list that stays correct is more useful than a broad one that does not.

Supported providers and what each can determine
ProviderWhat it can tell you
Railway Full Railway has no token scopes at all, so an account token maps confidently to the whole destructive set — including the backups stored inside the volume.
Supabase Full Key class resolves offlineservice_role and sb_secret_ bypass row-level security. Nothing leaves the machine to determine it.
GitHub Partial Classic PAT scopes in full. Fine-grained PATs report unresolved — the API does not expose their permissions.
Stripe Partial Live versus test mode. Restricted keys report unresolved rather than being guessed at.
Vercel Full Account-level reach. Vercel has no project-level scoping, so a token reads decrypted environment variables and can delete projects.
Cloudflare Liveness only Cloudflare will not tell a token its own permissions. Every live token reports unresolved, loudly.

No AWS. Mapping IAM policy to real capability is the single most likely place to be confidently wrong, and the credential under test usually cannot call the simulation API anyway. An AWS secret key still surfaces as an unrecognised credential rather than passing silently — a missing provider is better than a wrong one.

Provenance

Real-world incidents

The sequence at the top of this page is not hypothetical, and it is not a composite. It happened in April 2026, in nine seconds, with a thirty-hour recovery.

It is told here in the abstract on purpose. The mechanism is what generalises — anyone running an agent against a platform with coarse token scopes is one credential mismatch away from the same afternoon. The founder involved published the details openly so that others could learn from them, which deserves better than being used as a cautionary brand.

The verified account, every source, and a log of what checking it actually corrected are kept separately.

Read the verified account