Chapter · secrets

Secrets: filtering, swapping and brokering

Give an agent an API key and you have given it the ability to leak that key, because a model that can read a value can also be persuaded to write it somewhere. Give it a placeholder and a proxy instead, and the same agent does the same work with nothing worth stealing.

The four levels of credential handling

Every setup in the ecosystem sits at one of these levels. The jump from level 3 to level 4 is the single most valuable change available to almost everyone.

1 · Ambient

The real secret is in the environment or on disk, readable by the agent. cat $AWS_SECRET_ACCESS_KEY works. So does leaking it through a log, a crash dump, a test fixture or a screenshot.

2 · Mounted

A file or environment variable is placed inside the sandbox. Better than ambient because it is deliberate and scoped to one workload — but the agent still holds the plaintext, so the exfiltration question is unchanged.

3 · Forwarded

The secret never enters the guest: an SSH agent socket, a hardware token, a proxy handle. Genuinely better, and it introduces a new problem — the agent can use the capability, so your control is over which operations are possible rather than whether the credential exists.

4 · Brokered

The agent holds a placeholder. A trusted intermediary outside the sandbox swaps it for the real credential at the network boundary. The agent cannot print what it does not have, and logs and transcripts contain only the placeholder.

SANDBOX code + toolchain the coding agent itself OPENAI_API_KEY=__placeholder__ OPENAI_BASE_URL=http://127.0.0.1:PORT Bearer __placeholder__ TRUSTED INTERMEDIARY proxy, outside the sandbox, different process, own memory verifies session token (constant time) strips placeholder, injects real key key source: OS keyring, 1Password, Bitwarden, file, env, cmd, OAuth held as Zeroizing<String> Authorization: Bearer sk-…real… EXTERNAL API the real service, with the real credential, as normal DNS resolved by the proxy, link-local + cloud metadata (169.254.169.254) blocked What the agent can leak: a placeholder and a localhost port. What it cannot leak: your key.
The phantom-token pattern, as implemented by nono, Docker Sandboxes, Infisical Agent Vault and several Vercel and Anthropic designs. The load-bearing detail is placement: the proxy must run outside the sandbox, in a process the agent cannot read or ptrace.

Why this matters more than your choice of runtime

Consider two setups with identical isolation:

  • Setup A: a container with your .env mounted read-only, network open.
  • Setup B: the same container, but the environment contains placeholders and every outbound request goes through a broker with an allowlist.

If a poisoned dependency, README or tool result convinces the agent to POST its environment somewhere, Setup A has just leaked your production keys and Setup B has leaked a string that is useless outside your own proxy. The container topology was the same. The difference is that in Setup B, there was nothing in the sandbox worth stealing.

This is also why the industry converged on it. The IETF has a draft standard for a Credential Broker for Agents. The same pattern appears in Anthropic's managed-agent architecture ("the harness is never made aware of the credentials"), in Vercel's platform brokering, and in Cloudflare's Outbound Workers. The stakes are concrete: a supply-chain campaign against an LLM gateway in 2026 harvested SSH keys, cloud credentials and .env files and exfiltrated hundreds of gigabytes from hundreds of thousands of identities — a gateway whose entire job is holding provider API keys.

Credentials leak in boring ways first

Before you worry about a determined attacker: an agent will happily printenv into a transcript, paste a key into a commit message, write it into a test fixture, include it in a stack trace you then paste into a chat, or screenshot it. Brokering fixes all of those at once, because the value was never there.

A related idea: scoped and short-lived

If you cannot broker, the next best thing is to make what the agent holds worthless quickly. Use scoped tokens with minimal permissions, expiring in minutes or hours, issued per task. Vault and OpenBao are good at exactly this; they are stores, not brokers, so the agent still receives the plaintext — but a token that dies in ten minutes is a very different risk from a personal access token with no expiry.

The implementations

Approaches, not endorsements. Maturity assessments are in the linked repo profiles.
ApproachMechanismAgent holds the secret?Notes
nono (nolabs) TLS-terminating reverse proxy with session-scoped phantom tokens; header, url_path, query_param and basic_auth injection modes; proxy-side AWS SigV4 signing and OAuth client-credentials exchange; OAuth login capture with a phantom store outside the sandbox. No The most complete open implementation, and the one the whole field now cites. Pre-1.0, with a 2026 history that includes a full sandbox escape and a fail-open in pack verification — both fixed and disclosed. Assessment →
Infisical Agent Vault Forward proxy that terminates TLS, matches a placeholder in outbound requests, and substitutes the real secret from the vault. Host allowlists via access bundles. Designed to run on a separate host from the agent. No Maintained by a mainstream secrets company, which is the main advantage over rolling your own. Licensing is split between open components and a commercial product. Assessment →
mitmproxy, DIY Transparent or wireguard-mode intercepting proxy with a small addon that rewrites headers. Projects like keys-on-the-wire, sandcat and OpenSandbox's credential-vault spec build exactly this, sometimes publishing testable guarantees (for example: "the agent's address space never contains the real secret bytes", verified by core-dumping it). No The most control and the most responsibility. You own CA distribution, iptables redirection for clients that ignore proxy variables, SigV4 re-signing, and the fail-closed test. mitmproxy assessment →
Docker Sandboxes Host-side proxy injects credentials into outbound requests from a microVM. The sandbox sees a managed placeholder. No Good architecture, shipped as a product rather than a library, and closed source. Its Copilot integration bug was a textbook example of an agent validating a placeholder locally before the proxy could ever substitute it.
MCP-native brokers (keyward, Pincer-MCP, keymask, DemiPass, and similar) The broker is exposed as MCP tools: the agent requests a credential or a brokered call and gets a scoped token, a one-time nonce or a redacted response. Approvals fire out-of-band, in an OS dialog rather than in the agent's stream. No, or a scoped token Fits the tool-calling UX well and keeps approvals away from the model's influence. Requires MCP support, and because the broker is reachable through the agent's own tool interface, its authorisation logic becomes part of your boundary.
1Password Agent Hooks Pre-tool-use hooks that validate .env files were mounted from 1Password Environments before a shell command runs, blocking execution with stale or improperly mounted secrets. Yes, once mounted Point-of-use validation rather than brokering. It prevents the common "wrong secrets mounted" mistake; it does not stop the agent reading a value that is correctly mounted.
Vault / OpenBao Central secrets store with dynamic, short-lived credentials and audit logs. Yes A vault answers "where is the secret and who may fetch it". Excellent at issuing five-minute database credentials. It still hands the plaintext to the requester, so it belongs behind a broker rather than in front of an agent.
SOPS Encrypt values in YAML/JSON/.env with KMS, age or PGP, and commit them to Git. Yes, after decryption Solves secrets at rest and secrets in repositories. It is an encryption format, not a runtime control: once decrypted, everyone including the agent sees plaintext.

The failure modes to design against

Brokering is simple in concept and has a short list of ways to go wrong. Every one of these is a real incident or advisory from 2026.

Fail-open defaults

A credential proxy that treated an empty host allowlist as allow all, so a configuration that looked restrictive functioned as an open CONNECT tunnel. The fix is to make the empty case deny, and to make every configuration explicit. Audit your broker's default, not its documentation.

Proxy inside the sandbox

If the proxy runs in the same namespace as the agent, the agent can read the proxy's memory, its configuration, or its keyring access. The pattern only works when the intermediary is a separate process the agent cannot reach — ideally on a separate host.

Clients that ignore the proxy

Environment variables are a convention. Node ignored HTTP_PROXY before v24. Raw sockets ignore it always. If a tool can reach the network without passing the broker, the broker is decoration. Redirect at the kernel where possible, and verify by killing the proxy.

Local validation of the placeholder

A tool that checks whether its token looks like a real credential will reject your placeholder before any request is made. This broke a shipping product's Copilot integration for months. Choose placeholder formats that match the expected prefix, or use a real-but-scoped token as the placeholder.

Request signing schemes

Simple header substitution fails for anything that signs the request body, such as AWS SigV4: the signature covers the credential, so the proxy has to re-sign with the real key. Some brokers implement this; many do not. Check before you assume.

Host-side helpers on PATH

If the broker shells out to a host-side helper (op, bw, security, git) resolved by name, and the sandbox can write to a directory on PATH, the sandbox can plant a binary that runs with real privileges. Sanitise PATH to read-only entries, or pin absolute paths.

Metadata services and DNS rebinding

An allowed hostname that resolves to 169.254.169.254 is a cloud credential theft. A good broker resolves DNS itself and blocks link-local addresses and known metadata hostnames. A broker that forwards the hostname to the system resolver does not.

Redaction that corrupts your data

The inverse risk: a broker configured to mask anything that looks like a secret will eventually mask something that is not, and the agent will act on the wrong value. Placeholder substitution on the way out of the model is not deterministic, and there are documented cases of it substituting incorrectly.

What to do, in order

The ninety-minute version

no new dependency
1 · Move secrets out of the agent's environment Take every key out of .env, shell profile and container environment for the agent's process. Mount nothing.
↓
2 · Give the agent a placeholder and a base URL Most SDKs honour *_BASE_URL and *_API_KEY. Point them at 127.0.0.1 and a dummy value.
↓
3 · Run a rewriting proxy on the host, not in the sandbox mitmproxy with a small addon is enough: match the header, load the real key from the OS keyring, forward. Deny everything not on your allowlist.
↓
4 · Make it fail closed, and prove it Stop the proxy and confirm the agent cannot reach the network. If it can, your enforcement is in the wrong place.
↓
5 · Add secret scanning as a backstop gitleaks or detect-secrets in a pre-commit hook, so an agent that writes a key into a file cannot commit it. It catches the mistakes brokering has not been configured to cover.
The design principle to remember Authority should live outside the thing you do not trust. The agent does not need the key, it needs the API call to happen. The agent does not need the network, it needs to reach four hosts. The agent does not need your SSH key, it needs to push one branch. Every time you can reframe a requirement as "the effect should happen" rather than "the agent should hold the capability", you have removed a class of failure rather than mitigated it.
And the honest limit Brokering does not stop an agent from doing something legitimate-but-destructive through the broker: it can still spend your tokens, push to an allowed host, or delete data through an allowed API. It changes what can be stolen, not what can be done. That is why the guide keeps insisting on the last box in the computer-use diagram: a human gate on consequential actions, and a diff you actually read.