Back to Insights
21 Jun 20264 min readAI & LLMs

Your Agent Can Read Everything Your Shell Can. Have You Looked?

Last time we frisked the inputs — the invisible Unicode that smuggles instructions into a coding agent. But injection only matters because of what the agent can do once hijacked, and the quietest, highest-impact thing it can do is read a secret and send it somewhere. A coding agent with shell access has exactly your file permissions. So the question to ask before you point one at a repo — especially with --dangerously-skip-permissions — isn't "will it misbehave?" It's "if it's compromised, what's in reach?"

That's a concrete, answerable question, and almost nobody asks it. So we wrote a 100-line tool, agent-reach, that answers it — by listing the secret-bearing files reachable from where the agent runs. It reports paths and existence only; it never opens or prints a secret. The audit shouldn't itself be the leak.

Two zones of blast radius

An agent's reach has two parts, and you want to see both.

The repo tree. Everything under the working directory is one cat away. agent-reach walks it for the usual secret-bearing names — .env and .env.*, *.pem / *.key / id_rsa / id_ed25519, .npmrc (npm _authTokens live here), .pypirc, .netrc, .git-credentials, GCP service-account JSONs, *.p12 / *.pfx, and more — skipping the noise (node_modules, .git, build dirs).

$HOME. This is the part people forget. The agent doesn't stop at the repo — it can read your user's credential stores too. So agent-reach checks for the presence of the well-known ones: ~/.aws/credentials, ~/.ssh/id_*, ~/.config/gh/hosts.yml (a GitHub token), ~/.docker/config.json, ~/.kube/config, ~/.netrc, ~/.npmrc. Existence only — but existence is the point: if those files are there, a hijacked agent in any repo can exfiltrate them.

$ agent-reach
agent-reach — blast radius from /work/my-app

  IN THE REPO TREE      (an agent here can read every one of these)
    ● .env                — env file (secrets/config)
    ● .npmrc              — npm config (may hold an _authToken)   ⚠ COMMITTED (not gitignored)
    ● config/server.pem   — private key / cert                   ⚠ COMMITTED (not gitignored)

  REACHABLE IN $HOME    (same shell access — exfiltratable if hijacked)
    ● ~/.aws/credentials  — AWS access keys
    ● ~/.ssh/id_ed25519   — SSH private key

  blast radius: 5 secret store(s) in reach, 2 committed to the repo.

The COMMITTED flag is the one to act on first

A secret sitting in your working tree is bad; a secret you committed is worse — it's in history, on the remote, and in every clone and CI runner forever. So agent-reach cross-checks each repo hit against git check-ignore: anything that's both present and not gitignored gets a red ⚠ COMMITTED. That's your priority list. (A .env that's properly gitignored still shows up — an agent can read it — but it's a contain-the-radius problem, not a rotate-everything-now problem.)

It exits non-zero when the radius is non-empty, so it slots into a pre-flight check:

agent-reach --repo-only && echo "ok to run an agent here"   # gate on a clean repo tree

What to do with the number

The output is a worklist, in order:

  1. Rotate + un-commit anything flagged COMMITTED. It's already exposed independent of any agent.
  2. Move repo secrets out of the tree — into your shell env or a secrets manager — so the working directory an agent sees has nothing to read.
  3. Shrink the $HOME set for risky runs. If you're going to run an agent with broad permissions on untrusted code, do it somewhere its $HOME doesn't hold your production AWS keys — a container, a throwaway user, a sandbox.
  4. Frisk the inputs (agent-frisk) so the agent is less likely to be hijacked into reaching for any of it in the first place.

Prevention (don't get injected) and least-privilege (have nothing to steal) are the same defense from two ends — agent-frisk shrinks the first, agent-reach measures the second.

The honest limits

It's a names-and-locations audit, not a secret scanner. It finds files that conventionally hold secrets; it does not crack open a random config.json to see if you stuffed an API key in it (that's gitleaks/trufflehog's job, on content). It checks a curated list of $HOME stores, not every possible one. And "in reach" is about file permissions, not a guarantee the agent will read them — it's the denominator of the risk, the thing you want as small as possible before you hand over the keys to the shell. Pair it with real sandboxing for anything genuinely untrusted.

The real lesson

"I'll just let the agent run, it's probably fine" is a bet whose size you've never measured. agent-reach measures it: one command turns "probably fine" into a list of exactly what a single injected instruction could walk out the door with. The goal isn't zero tools — it's to know your blast radius and shrink it on purpose, so that when something does go wrong, the worst case is small.

We build and run autonomous agent fleets on Claude Code in production. If you're securing an agent that touches untrusted content, talk to us.


Get the tool → agent-reach in agent-ops — open source (MIT), a single dependency-free script, part of our toolkit for running coding agents in production.

AI agentssecuritysecretsblast radius

Found this useful?