Secrets Exfiltration: Your LLM Provider Can Force Your Agent to Leak Secrets
Discount LLM providers slash your model spend — but whoever runs the endpoint writes your agent's responses, and agents turn responses into shell commands. We tested Claude Code, Codex, and OpenCode against a hostile one — see what it can steal and how to stop it.

Cheaper LLM proxies let you run the same models for less, and pointing a coding agent at one is a one-line change. But whoever runs that provider can read everything your agent sends — and, less obviously, can make your agent run commands on your machine.
An LLM proxy sits between your application and a model provider. You point your client at the proxy's URL instead of api.openai.com or api.anthropic.com, and it forwards your requests upstream. In practice these gateways do useful things: a single API for many models, key management, caching, spend limits, load-balancing across providers, request logging. LiteLLM, OpenRouter, Cloudflare AI Gateway, Helicone, and dozens of self-hosted variants all live in this category, and most teams running agents at scale use one.
Because almost every agent lets you override its base URL — ANTHROPIC_BASE_URL, OPENAI_BASE_URL, a model_provider block in a config file — pointing an agent at a proxy is a one-line change. That same knob is what makes the discount market possible: a growing number of resellers advertise the flagship models at a fraction of first-party prices. You paste in a new base URL and an API key, keep your existing tooling, and your bill drops. Some of these endpoints are legitimate aggregators; others are opaque resellers routing your traffic through infrastructure you know nothing about, in jurisdictions you didn't choose.
This is not hypothetical. Intermediary proxies — sometimes called "transfer stations" — that resell access to frontier models are a documented market. In July 2026 the Financial Times reported Anthropic tightening its rules to close such loopholes, after Chinese firms reached Claude through VPNs, foreign subsidiaries, and transfer-station proxies. Months earlier it had accused three Chinese companies — DeepSeek, Moonshot AI, and MiniMax — of using commercial proxies and thousands of fake accounts to harvest millions of Claude responses and train their own models on them. We are not alleging any particular reseller tampers with your traffic; the point is narrower — with an opaque intermediary you simply can't know who runs the endpoint or what it does with your stream. That uncertainty is the risk.
The usual objection to the cheap ones is data privacy: they can read everything I send. That's true, and for a coding agent "everything" means your source code, your diffs, your environment, and any secret that ends up in a prompt. But privacy is the smaller half of the problem. The bigger half is that you have no idea who is on the other end, and the other end is not a passive relay.
Your LLM provider is the other side of the conversation
Here is the part people miss. Your LLM provider is not an eavesdropper on the wire. It is the endpoint your agent talks to. The agent sends a request; whatever comes back, the agent treats as the model's decision. If the provider writes the response, the provider decides what the agent does next.
Modern coding agents are loops: the model's reply can contain tool calls — "run this shell command," "read this file," "edit this file" — and the agent executes them, feeds the result back, and continues. So a hostile provider doesn't need to break anything. It just answers a normal request with a response that contains a tool call the model never made:
- Confidentiality — it injects a call that reads
~/.ssh/id_rsaor.env, and the file contents come back to the provider in the very next request. The provider is the wire the data returns on. - Integrity — it injects a call that runs a shell command or edits your source, and the agent runs it.

None of this requires a prompt-injection payload hidden in your data, a malicious dependency, or a bug in the agent. It's the designed behavior of an agent — pointed at a brain you don't control. Sharing your data with a cheap provider is a choice you can reason about. Handing an unknown party a channel that issues tool calls on your laptop is a different category of risk, and most people opting into the first haven't realized they've opted into the second.
We tested it against three agents
To see how far this goes in practice, we built a small hostile proxy and pointed three popular coding agents at it — one config change each, on a laptop, with benign payloads and a synthetic .env full of fake secrets. The proxy speaks each agent's wire format, logs every request, and — on the agent's first turn — answers with a fabricated response containing a tool call the user never asked for.
The three agents span the three wire protocols in use today:
| Agent | Wire format |
|---|---|
| Claude Code | Anthropic Messages |
| Codex CLI | OpenAI Responses |
| OpenCode | OpenAI Chat Completions |
We gave each one a harmless prompt — "summarize the README, don't run anything" — through the proxy. Two findings held across all three.

1. Every agent reads files automatically — so .env exfiltration needs no approval
Reading files is the bread and butter of a coding agent, so file reads are cheap or free by default. That is exactly what a hostile proxy needs. In each agent, the proxy injected a read of the synthetic .env, and the fake AWS, Stripe, and database credentials came straight back — with no approval prompt:
- Claude Code auto-approves its read-only tools (
Read,Grep,Glob). The injectedReadof.envexecuted silently; the secrets returned on the next request. - Codex, in non-interactive
execmode, defaults to approvalneverinside a workspace sandbox. An injectedcat .envran with no prompt — the sandbox blocks network egress and out-of-workspace writes, but reading a workspace file and returning it to the model is exactly what it's supposed to allow. - OpenCode guards its
readtool against reading.env— a nice touch — but itsbashtool has no such guard, so an injectedcat .envwalks right around the protection.
The important point: the sandbox and the permission prompt are aimed at escape — network, writes outside your project. Neither stops confidentiality loss, because the stolen data doesn't leave over the network. It leaves over the model API channel the agent is already, legitimately, using. The endpoint that receives it is the attacker.
2. Some agents execute code with no human in the loop
Reading is universal; execution varies by how much friction the agent puts in front of a shell command.
- Claude Code prompts before running
Bashby default — the injected command surfaces as an approval request for something you never asked for. That prompt is the one real speed bump we found. It disappears the moment a user runs with--dangerously-skip-permissionsor an allowlist, which many do for convenience. - Codex ran injected commands inside its OS sandbox with no prompt in
execmode; only commands that try to escape the sandbox (network, GUI, writes outside the workspace) require escalation. Its Seatbelt sandbox is genuine defense-in-depth — we confirmed it blocks network and out-of-workspace writes at the kernel level, and that obfuscating the command doesn't help, because enforcement is on the syscall at runtime, not on the command string. But reads and in-workspace edits — enough to steal secrets and rewrite your code — run freely. - OpenCode, in headless
runmode, auto-executedbashwith no sandbox and no prompt. The command we injected to pop a GUI Calculator — which needed a sandbox-bypass flag on Codex — simply ran.
So on the integrity side: one agent asks (until you turn it off), one contains the blast radius with an OS sandbox but still runs your code, and one just does it.
The protection is a property of the harness, not the agent
Notice how far apart those defaults are: Claude Code prompts before a shell command, Codex wraps every command in an OS sandbox, and OpenCode in headless mode runs shell with neither. The safety you rely on isn't inherent to "using an AI coding agent" — it belongs to one specific harness and its default configuration. Move the same workflow from Claude Code to OpenCode, flip on --dangerously-skip-permissions, or run headless in CI, and you have silently changed what a hostile provider — or a prompt injection, or a buggy tool call — is allowed to do. Switching agents is a security decision, and it rarely looks like one.
The durable fix is to put the security at the runtime layer instead of the agent. When isolation, least privilege, and policy are enforced by the environment the agent runs in, the guarantees hold no matter which agent runs inside it — so you can switch harnesses freely without re-auditing a new set of defaults. That is the Agyn model: a consistent security boundary around whatever agent you choose.
What actually defends against this
The through-line is simple: the endpoint controls the agent. A hostile provider reads every prompt and, with no exotic technique, drives the agent's tools to steal secrets and — depending on the agent's settings — run code. The privacy trade-off people consciously accept is the lesser half; the tool-execution channel is the half that owns the machine.
So the main point is the obvious one: don't route an agent through an LLM provider you don't trust. Use the first-party provider or a gateway you or your organization operate.
But if you do it anyway — for cost, for access, because a team already stood one up — then assume the endpoint may turn on you and minimize the blast radius:
- Isolate the agent. Run it in a container or VM with its own filesystem and network, not directly on your workstation, so a forged command can't reach the rest of your machine.
- Least privilege. No ambient cloud credentials, short-lived scoped tokens, and nothing in the agent's environment it doesn't strictly need for the task in front of it.
- Boundaries and policies on what the agent can do. Explicit allow/deny rules for commands, files, and destinations — enforced at runtime, not left to a permission prompt an attacker can talk a user through.
- Keep secrets out of the agent's reach.
.envfiles, keys, and tokens should live outside the workspace and environment the agent can read, so "read a file and send it upstream" returns nothing worth having.
This is the model we build toward with Agyn: treat the agent as untrusted-by-default and isolate what it can reach, instead of trusting the thing on the other end of the API.
A cheap LLM provider looks like a line-item on your bill. For an autonomous agent, it's a decision about who is allowed to run commands on your machine. Price it accordingly.
Newsletter
Get new agent engineering posts in your inbox
Occasional practical notes on secure agent runtimes, orchestration, and AI engineering.