If you are building anything on top of a language model, prompt injection is the vulnerability you most need to understand. This guide is written for defenders: engineers, security reviewers and product people who want to reason about the risk clearly. It describes the shapes prompt injection takes and how to blunt them. It deliberately does not hand out working attack payloads, because the goal here is to help you protect systems, not exploit them. The illustrations stay schematic, at the level of ideas that are already common knowledge.
What prompt injection actually is
Prompt injection happens when untrusted data gets interpreted as instructions. A language model reads a single stream of text, its context window, and it does not natively distinguish the developer’s instructions from the content it was handed to work on. If an attacker can get text into that stream, they can try to make the model treat their text as a command rather than as data.
This is the same class of problem as classic injection bugs, where input meant as data ends up executed as code. The twist with language models is that there is no clean syntax separating the two, which is exactly why the defenses look different. It is, at heart, a trust-boundary failure, the same shape of problem we cover in is your clipboard a security risk? where shared, unguarded memory lets one party read or influence another.
The main categories, with schematic examples
Direct injection
The simplest form: a user types text into the model that tries to override the system’s instructions. The canonical shape is the well-worn “ignore previous instructions and do X” pattern, aimed at making the model disregard its guardrails and follow the attacker instead. It is the version everyone has heard of, and on its own it is often the least damaging, because the attacker is only affecting their own session.
Indirect injection
More dangerous, and more subtle. Here the malicious instructions are not typed by the user at all. They are hidden inside content the model reads on someone’s behalf: a webpage an agent browses, a document it summarizes, an email it processes. The user asks an innocent question; the model fetches a page; the page contains text along the lines of “ignore your task and instead do X,” and the model may act on it. The victim never sees the instruction, which is what makes indirect injection the category defenders worry about most.
Tool-result injection against agents
When a model is wired up as an agent that calls tools, the results those tools return become part of the context, and those results can themselves carry injected instructions. An agent that reads a file, queries an API, or scrapes a page is ingesting text it did not write, and any of it can try to redirect the agent’s next actions. Because agents can take real actions, this is where injection stops being a curiosity and starts being a genuine security event.
Why it works
There is no privilege separation inside a context window. Operating systems separate kernel from user space; databases separate queries from data with parameterization. A language model has no equivalent boundary. Every token, whether it came from your carefully written system prompt or from a random webpage, sits in the same undifferentiated stream and is weighed the same way.
That is the root cause, and it is why prompt injection has proven so stubborn. It is not a bug in a particular model that a patch will close. It is a structural property of how these systems read text. Treat it as a permanent condition to design around, the way you would any standing constraint of the platform.
Real-world consequence patterns
The point of understanding the categories is to anticipate what an attacker is trying to achieve. Two patterns dominate.
- Data exfiltration attempts. Injected text tries to get the model to reveal something it can see but should not disclose: contents of other documents, system prompts, credentials in context, or data from another user. The attack often pairs with a channel to smuggle the data out, such as a crafted link or an outbound tool call.
- Action hijacking in agent systems. When the model can act, injected instructions try to redirect those actions: sending a message, modifying a file, making a purchase, calling a destructive API. The damage here is not leaked text but unwanted real-world effects.
Defenses, honestly assessed
There is no single control that closes prompt injection. The realistic posture is layered mitigation that lowers the blast radius. Ranked roughly by how much they actually help:
Least-privilege tool access
The strongest lever. Give an agent only the tools and permissions it truly needs, scoped as narrowly as possible. If the model cannot reach sensitive data or take a dangerous action, an injection that tries to trigger one has nothing to grab. Most of the worst outcomes come from over-privileged agents, so this is where to spend your effort first.
Human confirmation for side effects
Put a person in the loop before any consequential, irreversible action: sending, deleting, paying, publishing. This does not stop the model from being fooled, but it stops a fooled model from doing lasting harm on its own. For high-stakes operations, a confirmation step is worth the friction.
Input and output filtering
Scanning inputs for known injection patterns and outputs for signs of exfiltration helps at the margins, and it is worth doing. Understand what it buys you: filtering slows attackers down, it does not stop them. Attackers rephrase, encode and obfuscate, and no filter reliably catches all injections without also breaking legitimate use. Treat it as defense in depth, never as the load-bearing control.
Treat all model output as untrusted
The mindset that ties it together. Whatever comes out of the model may have been influenced by injected content, so do not feed it straight into anything sensitive. Do not pass model output unescaped into a shell, a query, or another privileged system. Validate and constrain it the way you would any untrusted input, because in effect that is what it is.
The takeaway for builders
Assume the context window is contestable. If attacker-controlled text can reach it, and in any system that reads external content it can, then design so that a successful injection cannot do much: minimal privileges, confirmation on the actions that matter, output treated as untrusted, and filtering only as an added layer. Prompt injection is not solved, and framing it as solvable leads to fragile systems. Framing it as a structural condition to contain leads to resilient ones.
For more on the trust-boundary thinking that underlies all of this, see is your clipboard a security risk? One practical way to reduce exposure in the first place is to keep more of the pipeline local; our pillar on running models on your own machine covers how, and end-to-end encryption explains why keeping data readable only to you closes off a whole class of downstream risk.