Prompt injection isn't XSS, but it rhymes
Both come from mixing instructions with data. The difference is that there is no escaping function for English.
XSS happens because HTML mixes markup and content, and a parser cannot tell which is which unless you escape. We solved it with escaping and contextual output encoding.
Prompt injection has the same shape — instructions and data in one channel — and no equivalent solution, because the "parser" is a model interpreting natural language and there is no character sequence that reliably means "the instructions stop here".
What it looks like
An agent summarises a web page. The page contains text instructing the model to ignore its previous instructions and do something else. If the model complies, the page's author just issued commands to your system.
The indirect version is the dangerous one: the injected text does not come from your user at all. It comes from a document, an email, a search result, an API response — anything the model reads. Your user is the victim, not the attacker.
Why the usual defences underperform
Instructing the model to ignore embedded instructions helps and does not hold. It is a probabilistic barrier against an adversary who can iterate.
Delimiters and structured formats help and can be imitated. If the model treats a particular marker as authoritative, injected content can contain that marker.
Input filtering catches known phrasings. Natural language has unlimited paraphrases.
All are worth doing. None should be load-bearing.
Treat model output as user input, because in the presence of injection that is exactly what it is.
What actually contains the damage
Constrain capability rather than input. An agent that can only call three specific, narrow tools cannot be talked into arbitrary action, however convincingly it is asked. The blast radius is the tool surface, so make the tool surface small.
Authorise every tool call against the *user*, not the model. If the model requests a record the user may not see, the authorization layer refuses — exactly as it would for a forged HTTP request. This is the single most effective control, and it is ordinary application security rather than anything AI-specific.
Require confirmation for consequential actions. Anything that spends money, sends a message externally, or deletes something should surface to a human with what it is about to do.
Isolate contexts. Content fetched from outside should not share a context window with privileged instructions and credentials where that can be avoided.
Structured output helps for the right reason
Forcing responses into a strict schema does not stop injection, but it narrows what the model can express, and it makes validation possible: you can check that a returned identifier is one the user may access before acting on it.
That validation is the actual control. The schema just gives you something to validate.
The honest position
There is no complete fix today. Design as though the model will occasionally be persuaded, and make sure that when it is, the worst outcome is a bad answer rather than a bad action.