Put a credential proxy in front of your coding agentLeak a placeholder, not your API key
Your agent needs to call the Stripe API, not hold your Stripe key. A credential proxy keeps those apart: the agent sends a placeholder, the proxy swaps in the real secret at egress. Setup takes an afternoon.
-
01
Agent
Placeholder
Sends __api_key__
Holds no real secret -
02
Proxy
Swap at egress
Injects the real key
TLS terminated locally -
03
Upstream
Real request
Stripe, GitHub, LLM
Key never in agent env
TL;DR· the answer, in twenty seconds
What happened: The standard setup puts a long-lived API key in the agent's environment, where every subprocess, MCP server, and dependency can read it and a single prompt injection can exfiltrate it.
The minimum fix: Put a credential proxy between the agent and the API. The agent holds a placeholder, the proxy holds the real key and injects it at egress, and a dump of the agent's environment yields nothing worth stealing.
The lesson: The agent needs to make the call, not keep the key. Move the secret to the boundary and a leaked environment stops being an incident.
Your coding agent needs to call the Stripe API. It does not need to hold your Stripe key, and a credential proxy is how you keep those two facts apart.
The key lives in the agent's environment
When your agent calls a paid API, the standard setup puts the key in its environment. STRIPE_SECRET_KEY in .env, ANTHROPIC_API_KEY exported in your shell, a GitHub token in the agent's config. The agent reads the variable, builds the request, sends it. So does every child process the agent spawns and every MCP server it talks to, because environment variables flow down the process tree.
Knostic spent the back half of 2025 documenting what that costs. Their research found Claude Code reads .env, .env.local, and similar files without asking and without documenting that it does. One researcher watched it pick up an HTTP_PROXY value from a project .env and run up proxy charges before he moved the file out of the directory. Another team's Cursor instance swept an API key into an unrelated file and uploaded it to the cloud. The agent did not need to be compromised. It read its environment, which is what programs do.
Prompt injection turns the same plumbing into an exfiltration path. A string in a web page the agent fetches, an instruction buried in an issue it was asked to triage. Either one can tell the agent to read its own environment and post it somewhere. The credential was sitting in process.env the whole time, readable by anything in the tree, waiting for one instruction to walk it out. You do not need a sophisticated attacker for this. You need one tool in the chain that reads its own environment, which is all of them, and one message that reaches the model and asks.
Deny rules help and do not finish the job. You can add Read(./.env*) to a deny list, you can chmod 600 the file, you can keep secrets out of the repo. None of that touches the case where the agent has to have the key to do its work. If it authenticates to Stripe, the key has to be reachable when the request goes out. The question is whether "reachable at request time" has to mean "sitting in the agent's environment for the whole session." It does not.
What a credential proxy does
A credential proxy moves the secret out of the agent and onto the edge of the wire. The agent holds a placeholder. The proxy holds the real key. When the agent makes an outbound HTTPS request, it routes through the proxy, the proxy strips the placeholder and injects the real credential, then opens the upstream connection and forwards the response back. The agent gets its answer from Stripe. It never read the key, because the key was never in its environment to read.
The mechanism is the ordinary HTTPS_PROXY variable plus TLS interception. The agent points HTTPS_PROXY at a local listener. The proxy terminates TLS using a certificate authority you install in the local trust store, inspects the request, swaps the credential, re-encrypts to the upstream, and streams the response. From the agent's side it looks like a plain HTTPS call. From the network's side the real key appears only on the connection the proxy opens, never on anything the agent controls.
This is an old idea with new packaging. CyberArk's Secretless Broker has done sidecar credential injection for years, and HashiCorp added native agent support to Vault in 2026 with an agent registry and per-request authorization. In 2026 two projects packaged the egress-proxy version for coding agents and built it around how agents behave in practice.
Set it up with Agent Vault
Infisical released Agent Vault on April 22, 2026. It is an open-source binary that runs as both the proxy server and a CLI, on macOS and Linux or in Docker. The setup is short.
Install it and start the server with a master password that encrypts the credential store:
curl --proto '=https' --tlsv1.2 -fsSL https://get.agent-vault.dev | sh
export AGENT_VAULT_MASTER_PASSWORD=... # encrypts the local store
agent-vault server -d
The server listens on two ports: 14321 for the management API and UI, and 14322 for the TLS-terminating proxy. Add your real credentials through the management UI on port 14321, then define a service rule that maps a placeholder to a real value for a given host. The rule reads: on requests to api.anthropic.com, replace the dummy string __anthropic_api_key__ with the stored secret.
Mint a token for the agent:
agent-vault create-agent my-coding-agent
# => prints a token for the agent's environment
Now the agent's environment holds a placeholder where the key used to be:
AGENT_VAULT_ADDR=http://localhost:14321
AGENT_VAULT_TOKEN=<token-from-create-agent>
AGENT_VAULT_VAULT=my-vault
ANTHROPIC_API_KEY=__anthropic_api_key__ # placeholder, not the real key
Launch the agent through the proxy:
agent-vault run -- claude
Dump that environment now and the worst an attacker gets is the string __anthropic_api_key__, which authenticates to nothing. The same run wrapper works for codex, opencode, or a custom harness. The real key sits in the vault process, on a port the agent has no reason to talk to, behind a master password the agent never saw.
Confirm the swap before you trust it. Make one real request through the agent and check the proxy's request log, which records that a call to api.anthropic.com went out with an injected credential and which agent token asked for it. If the upstream accepts the call while the agent's environment still shows only the placeholder, the boundary holds. That log is the other half of the value. You get a record of every credential use keyed to an agent, which is the audit trail a static key in .env never gave you, and the thing you reach for when something looks wrong at 2 a.m. and you need to know which task touched which API.
For sandboxes that spin up per task, Agent Vault also ships a TypeScript SDK that builds the proxy environment for a fresh session. A container gets a scoped, expiring session and a placeholder rather than a key baked into the image, so a leaked image layer leaks nothing.
The lighter version: scoped tunnels
Running a full proxy is more than some workflows need. If the agent only shells out to a deploy script or a CLI that reads an env var, Bitwarden's Agent Access takes a smaller bite. It shipped May 15, 2026 as an open protocol plus a CLI called aac, still in early preview, built on an end-to-end encrypted tunnel between your vault and a remote process.
Your laptop runs the provider, holding the vault:
aac listen
The agent, or a script it runs, connects as a consumer and asks for one domain's credential:
aac connect --token <pairing-token> --domain github.com --output json
aac run --domain api.stripe.com --env-all -- ./deploy.sh
The consumer never sees the full vault. It gets the one item it asked for, scoped to the domain it named. With aac run, the agent sees the command aac run --domain api.stripe.com --env-all -- ./deploy.sh, not the Stripe key the script behind it uses. The secret enters the child process for the length of one command and leaves with it.
The difference between the two tools is where the secret lives at request time. Agent Vault keeps it on the wire and the agent talks plain HTTPS to a local proxy. Bitwarden Agent Access keeps it in a sibling process and injects it per command. Reach for the proxy when the agent makes the API calls itself. Reach for the tunnel when the agent drives tools that read credentials from their own environment.
Where the proxy stops protecting you
A credential proxy is real protection and it is not a wall. Three failure modes deserve your attention before you trust one.
TLS pinning breaks it. Any client that pins its server certificate refuses the proxy's CA and the connection dies. Most public API SDKs do not pin, so Stripe, GitHub, and the LLM providers work, but the first time a pinned client fails behind the proxy you lose an afternoon to a confusing handshake error. Keep a NO_PROXY list for the hosts that pin.
The proxy authorizes by token, not by who is asking. The agent's AGENT_VAULT_TOKEN is itself a credential, and every process in the agent's tree inherits it. A prompt injection that can no longer read ANTHROPIC_API_KEY can still make the agent send requests through the proxy, and the proxy injects the real key into each one. You moved the secret out of reach. You did not stop the agent from spending it. A proxy narrows exfiltration of the raw key without narrowing misuse of the access that key grants.
The CA is a new trust anchor. You installed a certificate authority that can decrypt the agent's HTTPS traffic. That is the point, and it is also a key worth guarding. If the proxy's CA private key leaks, an attacker who has it can impersonate any site to anything that trusts the CA. Scope that trust to the agent's environment rather than the whole machine wherever the runtime lets you.
This is where the boundary you picked matters. A proxy scopes by token across many hosts. It does not scope by which process in the tree is allowed to spend the credential. If you want the agent to use a key but the MCP server it spawned to get nothing, you need a broker that authorizes per process rather than per token. hasp does this at the process-tree level: it brokers the credential to the requesting process and its children and logs each access, so a sibling the agent spawned cannot ride the same grant. The proxy and the process broker cover adjacent halves of the problem, and a careful setup runs both.
What this means for your stack
The minimum move this week: get the long-lived API keys out of your agent's environment and replace them with placeholders that a proxy or a tunnel resolves at request time. An afternoon with Agent Vault turns a key that any subprocess can read into a string that authenticates to nothing, and a leaked environment dump stops being an incident.
The pattern is credential injection at the boundary. The consumer holds a token or a placeholder, something else holds the real secret and resolves it at the moment of use, and the secret never lands in the consumer's environment where injection and dependencies reach it. The same shape runs under workload identity: SPIFFE hands a service a short-lived identity document instead of a long-lived shared secret. Egress proxies, scoped tunnels, and process brokers are that idea in different packaging, and they compose.
hasp is the process-tree shape of it. hasp run -- claude brokers credentials to that process and its children, logs every access, and keeps the secret out of the ambient environment, so the proxy handles the wire and the broker handles the tree. Source-available (FCL-1.0), local-first, macOS and Linux, no account.
Whatever you put in front of the agent, the test is the same one. Dump the agent's environment and read what falls out. If a real, working API key is sitting there, you have not protected it. You have only hoped nobody asks the agent to read it.
Sources· cited above, in one place
- Knostic Research on AI code editor secret leakage (Claude Code, Cursor)
- Infisical Open-source secrets management
- Bitwarden Securing AI coding agent access with Secrets Manager
- CyberArk Secretless Broker Open-source sidecar credential broker
- HashiCorp Vault Documentation
- SPIFFE / SPIRE Workload identity
Stop handing the agent your real keys.
hasp keeps secrets in one local encrypted vault, brokers them into the child process at exec, and never lets the agent read the value.
- Local, encrypted vault — no account, no cloud, no telemetry by default.
- Brokered run — agent gets a reference, the child process gets the value.
- Pre-commit + pre-push hooks catch managed values before they ship.
- Append-only HMAC audit log answers "did the agent touch the prod token?" in seconds.
macOS & Linux. Source-available (FCL-1.0, converts to Apache 2.0). No account.