Blog
The confused deputy problem, explained
A program that holds more authority than whoever is asking it to act, tricked into spending that authority on their behalf. Norm Hardy named the pattern in 1988, and a coding agent holding your credentials fits it exactly.
A confused deputy is a program that holds more authority than the party asking it to act, and gets tricked into spending that authority on the requester's behalf. Norm Hardy named it in 1988 after a real bug: a compiler at Tymshare could write files in its own directory, and a user told it to write debugging output to the billing file sitting there, destroying it. The compiler had done nothing wrong; it had no way to tell whose authority it was spending. A coding agent holding your login, your keys and your shell, taking instructions from text it did not write, is the same shape.
What the confused deputy problem is
A confused deputy is a program that has more authority than the party asking it to do something, and acts on that request using its own greater authority rather than the requester's lesser one. It is not buggy code and it is not a malicious program. It does exactly what it was written to do, every time, which is what makes the pattern hard to see coming.
Norm Hardy named it in a short 1988 paper, The Confused Deputy (or why capabilities might have been invented), published in Operating Systems Review. He was describing a bug from roughly a decade earlier at Tymshare, a commercial timesharing company, and the paper is still the clearest statement of the problem almost forty years later.
The core failure is a mix-up between two things that look alike but are not: having the authority to do something, and knowing on whose behalf you are doing it. A deputy can have plenty of the first and none of the second.
The compiler that overwrote a billing file
The incident is concrete enough to walk through in full. Tymshare ran an operating system with Unix-like protection. A compiler lived in a directory called SYSX, and a user ran it by typing RUN (SYSX)FORT, optionally naming a file to receive debugging output.
The compiler also collected language-usage statistics, written to a file called (SYSX)STAT inside its own directory. To let it do that, Tymshare granted the compiler's program file a home files license: permission to write anywhere inside SYSX, its home directory. That looked like a reasonable, narrow grant for a narrow job.
The billing file, (SYSX)BILL, also lived in SYSX. A user who had learned that filename passed it to the compiler as the destination for debugging output. The compiler, carrying its home files license, opened (SYSX)BILL for writing and overwrote the billing data. Nothing in the compiler's own code was wrong. It wrote wherever it was told to write, inside a directory it was licensed to write to.
Hardy's own diagnosis: the compiler was running with authority from two different sources at once, its home files license and whatever its invoker was allowed to do, and it had no way to keep them apart. That is the whole mechanism. Everything downstream, the fixes that work and the ones that do not, follows from that one sentence.
Ambient authority: permission by identity, not by request
The compiler's mistake has a name capability-security writing later gave it: ambient authority. Authority is ambient when a program gets to use it just by virtue of being that program, running as that identity, rather than by presenting a specific permission for the specific thing it is about to do. The compiler's home files license was ambient in exactly this sense: it covered every file in SYSX, for every write the compiler ever made, whether or not the write had anything to do with the license's actual purpose.
Ambient authority is not a 1988 artifact. A Unix process inherits its user's full filesystem permissions the moment it starts, not a permission scoped to the one file the current task needs. An API key sitting in a shell's environment variables is available to every line of code that process runs for as long as it runs, not just the one call that needed it. Both are the same shape as the home files license: broad, standing, and attached to identity rather than to the task at hand.
None of that is automatically a security hole. Most programs never get asked to do something their owner would not have wanted. The hole opens the moment something inside that ambient scope takes an instruction from a party who does not share the owner's interest, which is exactly what happened to the compiler, and is exactly what a coding agent reading untrusted text is exposed to.
Why a coding agent holding your credentials is a textbook case
A coding agent in a terminal runs as you. It has your shell, your filesystem permissions, your environment variables, and any API key you have exported or left in a .env file nearby. All of that is ambient: available to the agent for the whole session, not issued per action.
It also reads text it did not write and was never asked to trust. A README it opens while getting oriented in a new repository. An issue or a pull request description. A web page it fetches to look something up. The description text an MCP server publishes for its own tools, which the agent reads as instructions for how to use them. None of that text arrives labeled as untrusted, and once it sits in the same context as your actual instructions, the agent has no structural way to tell which parts came from you and which came from someone else's text.
If any of that text tells the agent to do something, read a key out of the environment and send it somewhere, write to a file it was not asked to touch, run a command that benefits whoever wrote the text, the agent executes it with the authority it already holds. That is Hardy's compiler, with the SYSX directory replaced by your machine: real authority, a request from a party that holds none of it, and nothing in between to notice the difference. MCP tool descriptions are a concrete version of this: a server can publish a tool description carrying instructions the agent treats as legitimate simply because it arrived in the right shape.
CSRF and SSRF: the same shape on the web
The pattern predates AI agents by decades, and web developers already have names for two common cases. Cross-site request forgery makes the browser the deputy. A browser holds a session cookie ambiently: it attaches that cookie to every request to a given site, regardless of which page or script triggered the request. A malicious site can get the browser to fire a request the user never intended, and the target site sees a perfectly authenticated request, because the browser cannot tell a request the real site asked it to make from one a different page tricked it into making.
Server-side request forgery makes the server the deputy. A web application often has network reach a remote attacker does not: an internal admin panel, a cloud metadata endpoint, an HR system on the office network. OWASP's own example is direct: a user cannot reach the HR system directly, but if the application handling that user's input is vulnerable to SSRF, the user can use the application to reach it anyway. The server has the access. The attacker just supplies the request.
Both are the confused deputy problem wearing a web-shaped costume: a program with standing access, fed a request by a party who has none of that access itself, with no mechanism in between to check whose interest the request serves.
The fix: capabilities, and keeping the credential out of the deputy
Hardy's own fix is in the same paper. Instead of giving the compiler a broad license to its whole home directory and letting a filename supplied by someone else decide what gets written, give it a capability: a single, unforgeable reference to the one statistics file it is actually meant to write. The capability both names the resource and carries the authority to use it, in one object, so there is no separate name for an attacker to redirect and nothing broader left sitting around to be misused.
The general version of the fix is to designate authority explicitly, per use, instead of granting it ambiently, per identity. A permission handed to a program for the one call that needs it, naming the one resource it is for, cannot be redirected onto a different resource the way a standing license to a whole directory can.
The fix underneath that fix is to not give the deputy the credential at all. If the program that might be fooled never holds the value, being fooled about what to do with it stops mattering, because it has nothing left to misuse. How much authority a deputy should hold in the first place, even on a day nobody tries to trick it, is the question Saltzer and Schroeder answered seven years before Hardy named this bug: see least privilege and capability-based security for AI agents.
How this works in Forkbench
Forkbench is a desktop app for running coding agents, and the Vault is built around the second fix rather than the first: a key you add to it is used by the command that needs it without the value ever reaching the agent's prompt, command line or transcript. Access is deny by default, an agent resolves zero secrets until a person grants one, so even a fully fooled agent, one that read a malicious README and tried to act on it, has nothing to hand over, because it never held the credential Hardy's compiler would have needed to misuse. See what actually stops a key reaching an agent.
Where a secret is bound to a destination, the stand-in value a command receives only resolves into the real credential on its way to that one destination; the same stand-in pointed anywhere else is refused and recorded. That is Hardy's capability fix applied to a credential instead of a file: authority designated to one place, rather than ambient to whatever the process decides to do with it. See where a key can go.
The limit, stated the way the rest of that page states its limits: a secret with no established destination cannot be substituted this way, so it falls back to being injected into the command's environment, and a program running inside that process can still read what it was handed. That fallback is ambient authority again, narrowed to one process instead of a whole account, but a value sitting in a process environment is still a value a confused process can act on.
Related: What actually stops a key reaching an agent, MCP tool poisoning and secrets in config files, Least privilege and capability-based security for AI agents
Frequently asked
What is the confused deputy problem?
A confused deputy is a program that holds more authority than whoever is asking it to act, and gets tricked into spending that authority on the requester's behalf. Norm Hardy named it in a 1988 paper describing a real bug: a compiler licensed to write files in its own directory was told by a user to write debugging output to the billing file sitting in that same directory, destroying it. The compiler did nothing wrong; it simply had no way to tell whose interest it was serving.
What is ambient authority?
Ambient authority is permission a program gets to use just by virtue of being that program or running as that user, rather than by presenting a specific grant for the specific thing it is about to do. A Unix process inheriting its user's full filesystem access, or an API key sitting in an environment variable available to every line of code that process runs, are both ambient: standing, broad, and attached to identity rather than to the one task that actually needs them.
Is CSRF a confused deputy attack?
Yes. Cross-site request forgery makes the browser the deputy: it holds a user's session cookie ambiently and attaches it to any request sent to that site, regardless of which page triggered the request. A malicious site gets the browser to fire a request the user never intended, and the target site sees a fully authenticated request, because the browser has no way to tell a request its owner meant to make from one it was tricked into making.
How do capabilities fix the confused deputy problem?
A capability is a single, unforgeable reference that names a resource and carries the authority to use it in one object, handed to a program for the one use it is meant for. Norm Hardy's own fix for his compiler bug replaced a broad standing license to write anywhere in a directory with a direct capability to the one file the compiler actually needed, so there was no separate filename left for a user to redirect and nothing broader left to misuse.
Can an AI coding agent become a confused deputy?
Yes, and it is close to the default case rather than an edge case. An agent running in your terminal holds your shell, your filesystem access and any credential you have exported, ambiently, for the whole session. It also reads text it did not write: READMEs, issues, web pages, the descriptions an MCP server publishes for its own tools. If that text carries an instruction, the agent can execute it with the authority it already holds, which is yours.