The confused deputy problem, and why AI agents are prone to it

A program with legitimate authority is tricked into using it for someone who has none. The classic compiler case, the browser version everyone has already met, and why an AI assistant is the sharpest instance.

5 min read

A confused deputy is not a compromised program. It is a program doing exactly what it was built to do, correctly, on behalf of someone who had no right to ask.

The name comes from Norm Hardy's account of a compiler that overwrote a billing file. The failure keeps recurring because it is not a defect you patch out — it is a consequence of how authority is normally arranged.

The original case

The compiler ran on a shared, pay-per-use system. It recorded usage, so it held write access to a billing file no ordinary user could touch. It also accepted a caller-supplied filename for its optional output.

A user invoked the compiler and named the billing file as the output path. The compiler opened it and wrote. The billing records were gone.

Nothing malfunctioned, and no permission check returned the wrong answer. The compiler was allowed to write there; the caller was not, and never obtained that permission. What failed is that the compiler held two authorities at once — its own and its caller's — and the request carried nothing to say which applied.

The pattern in one sentence: a deputy with more authority than its requester performs the requester's request using the deputy's authority.

Ambient authority is the enabling condition

The compiler was confusable because its authority was ambient — in force for every operation it performed, by virtue of what it was rather than what it had been handed. That is the normal case, not an exotic one. A process identity, a session cookie, a key in an environment variable, a grant issued once when an app was connected: each converts this actor made the request into the request is permitted.

A confused deputy exploits that conversion. Nobody steals the credential; they get the holder to spend it.

Cross-site request forgery is the version you already know

Same shape, in a browser. Your browser holds a session cookie for your bank and attaches it automatically to any request bound for that origin. A page served by someone else causes such a request; the cookie rides along, because that is what browsers do. The bank receives a well-formed, authenticated instruction and cannot see that you never intended it.

The browser is the deputy. The other page is the requester with no authority. Your session is the authority being borrowed.

The defenses generalize past the web. An anti-forgery token requires a secret that could only have come from a page the site itself served — evidence the action traces back to something the principal did. Cookie policies that stop credentials attaching to cross-site requests attack the ambient attachment directly. Neither treats the caller's identity as sufficient.

Why an AI assistant is the sharp version

An assistant is a deputy by construction. It holds your authority — connected accounts, keys, file access — and it decides what to do next by reading text. Both halves are the point of the product; neither is removable.

The compiler had one narrow opening: a filename argument. An assistant's opening is every token in its context. A fetched web page, an attached document, a tool result, a message from a stranger — all of it arrives through the same channel as your instructions, and none of it carries authority. The confused-deputy precondition holds for essentially everything the model reads.

There is also no schema to validate against. A filename can be canonicalized and checked against a policy; natural language has no reliable delimiter between data and instruction. The mechanism by which text steers a model is prompt injection, a subject of its own. The point here is narrower — the confusing party need not be a caller. Their text only has to arrive.

Separate this from its neighbour. The principal-agent problem is an agent pursuing a goal it inferred instead of the one you meant. A confused deputy is an agent faithfully pursuing a goal belonging to somebody else.

Bind authority to an intent, not to a speaker

Hand over a capability rather than a permission. If the deputy can only write to the handle it was given, naming a different file achieves nothing. Authority travels with the reference to the specific thing, so there is no ambient pool to misdirect — which is what the original case was written to argue for.

Keep instruction and data separable where the format allows — parameterized queries are this move. For a language model it holds weakly at best, worth conceding rather than designing around.

Require a fresh expression of intent immediately before the consequential step — not a standing grant issued when the tool was connected, but the specific action, in final form, authorized at the moment it would happen.

Bound what the deputy can do at all, so a confused one is cheap.

None of this makes a deputy un-confusable. What changes is whether confusion produces an action or only a proposal.

One implementation

RelayLink leans on the last two. Sending is two calls: one writes a draft, a separate confirm releases a draft the same account already created, and that check runs on the server rather than in a prompt. Holding the API key does not get a message out — delivery attaches to one rendered draft a person looked at. The authority to send is not ambient, and the delivering tool is titled Send package (irreversible).

The same principle governs the labels. No tool parameter accepts a provenance value; the server derives it by comparing the final wording against the draft. The deputy does not get to vouch for the requester.

Inbound packages are also wrapped in a frame telling the reading assistant to treat them as third-party information, not instructions — the weakest layer here, since it asks a model to behave rather than removing its ability to misbehave.

If you are auditing something else, the question is not what the deputy may do. It is on whose behalf it can be made to do it, and what an outsider could get out that way — which is data exfiltration. To see a send bound to a named intent, connect your assistant.

Frequently asked questions

What is the confused deputy problem?
It is a security failure in which a program holding legitimate authority is induced by a less-privileged party to exercise that authority on their behalf. Nothing is impersonated and no permission check returns the wrong answer. The deputy simply has no way to tell which of its two masters a given request should be charged to, so it applies its own authority to a request from someone who had none.
Is cross-site request forgery a confused deputy attack?
Yes, and it is the clearest everyday example. The browser is the deputy. It holds a session credential for a site and attaches that credential automatically to requests bound for it, so a page from another origin can cause an authenticated request the user never intended. Defenses work by requiring evidence that the action traces back to something the user actually did, rather than accepting the caller's identity as sufficient.
How is the confused deputy problem different from the principal-agent problem?
The principal-agent problem is an agent pursuing a goal that diverges from what you meant, usually one it inferred from an underspecified instruction. The confused deputy problem is an agent faithfully pursuing a goal that belongs to a third party with no authority of their own. The first is answered by making inferences visible before they are acted on. The second is answered by making authority attach to a specific expressed intent instead of applying automatically.