· Updated

Your Background Subagents Can Leak Secrets — Build the Isolation Model

Claude Code#security#subagents#claude-code#isolation#guide#mental-model

Developers flagged a reproducible issue that should make anyone running background agents pause: Claude Code’s background Opus subagents intermittently stall on their first turn and, instead of producing useful work, emit system-prompt fragments — including text shaped like authorization data — as their only output. It’s labeled a security issue, it has a reproduction, and it’s open. That’s enough to treat it as a real, if intermittent, class of failure, and it generalizes to every agent that spawns autonomous child loops.

Here’s the mental model that matters: a subagent is not a trusted subprocess. It’s an autonomous loop with access to a context window, a toolset, and — too often — the same credentials as its parent. When that loop stalls and dumps its prompt instead of its result, anything that was in context is now in output. Authorization-shaped text leaking is the canary: if the prompt carried a token, a session string, or an internal endpoint, that’s what surfaces.

The fix is structural, not reactive. Three rules:

1. Scope credentials per subagent, not per session. A background agent that only needs to read a repo shouldn’t hold deploy keys. Hand it the narrowest token that completes its task and revoke it when the task ends. If the tooling can’t scope credentials, that’s a gap to close before you scale subagents.

2. Treat subagent output as untrusted. Anything a subagent returns — including error text, logs, and especially “stalled” dumps — should be parsed and sanitized before it touches shared state. Don’t pipe raw subagent output into a context that feeds other agents or into any log that leaves your machine.

3. Separate the system prompt from the working context. The leak happened because authorization-shaped content sat in the same window the subagent could echo. Keep credentials and internal routing data out of the prompt that a stalled loop might surface. Put them in a side channel the model can call, not text it can print.

Detecting a leak before it becomes an incident

The hard part is that a stall echoes silently — there’s no raised error, just output that looks like output. So detection has to be mechanical, not eyeballed. Three cheap signals worth wiring into any subagent runner:

  • Hash-and-compare prompt fragments. Your system prompt is finite and known. Tokenize it, take a rolling hash of long spans, and scan subagent output for collisions. A subagent that repeats any locked span of its own prompt is stalling and needs to be killed, not trusted.
  • Credential-pattern grep on every output. Before output touches shared state, run it through the same secret-scanning patterns you use in CI — sk- keys, BEGIN RSA/OPENSSH/PRIVATE KEY blocks, AWS_-prefixed assignments, known UUID session id formats. A failed pattern match is a finding, not a warning.
  • Disposition log. Track, per subagent run, whether the output ended in a well-formed result or a truncation/stall, so you can spot the failure rate climbing before a specific run matters.

None of these need new tooling. They’re shellable in a few lines, and they convert the “silent” failure into an observable one.

The isolation model, concretely

The principles above map to four boundaries you can actually implement:

  1. Prompt boundary. Keep the system prompt minimal and credential-free. Anything machine-readable that the agent may need — a token file, a registry address — lives at a path the agent must call to retrieve, not as literal text in the prompt it can echo.
  2. Tool boundary. Give each subagent a read-only toolset by default. Deploy keys, write handles, and network capabilities are granted per-task and revoked on completion. If the runner can’t revoke, use throwaway tokens that expire by design.
  3. Output boundary. Treat output as an untrusted artifact. Sanitize, pattern-scan, and verify shape before it reaches git, a log aggregator, or another agent’s context.
  4. Runtime boundary. Run background agents where a stall cannot touch host state — a disposable sandbox, a container with no inbound credentials, or at minimum a dedicated user with a minimal keyring.

Solo developer vs. team

For solo developers this is a config discipline: separate keys, minimal scopes, sanitized logs. The whole model collapses to one script that creates a scoped credential, runs the subagent against a read-only clone, scans the output for secret patterns, and tears the credential down.

For teams it’s an architecture requirement — the runner becomes infrastructure, with audited credential lifecycles and a redaction layer that gates every subagent result.

Either way, the model is the same: untrusted loop, scoped credentials, isolated prompt. Do that and a leaked fragment is annoying. Skip it and a leaked fragment is an incident. Assume every background agent will, at some point, speak its prompt aloud — and design the boundary so that what it says can’t hurt you.


Ever wonder if Claude gives a better answer than GPT for a specific coding problem? aiFiesta lets you compare 9+ premium models side-by-side in one chat. No more juggling tabs.

FREE RESOURCE

Get the AI Agent Cheat Sheet

All 19 coding agents in one comparison table — pricing, features, benchmarks. Updated weekly. Delivered to your inbox.

k
kira_bug_hunter
Security & Bug Hunter
Former pen tester. Finds the bugs nobody wants to exist. Skeptical of everything, especially status indicators.

Related articles