The agent's threat model starts with admitting a simple fact: the agent reads untrusted text. Someone else's code, documentation, command output, web pages, replies from external servers. Any of those sources may contain instructions disguised as task requirements. Prompt injection is not about the text itself but about the text being joined with permissions: to the shell, the browser, external systems, secrets and the repository provider. What is dangerous is not a paragraph carrying harmful advice but that same paragraph next to the ability to carry it out.
The naive defense is to ask the model not to give in to harmful instructions. It does not work by construction. The model tells texts apart by their content, not by their origin: your assignment and a page it found arrive in the same stream, and one well-chosen phrasing is enough for the request to stop applying. You will not learn about it in time. A system instruction is a direction, not a boundary. The boundary is where an action is technically impossible: in permissions, the sandbox, allowed-command lists and approvals.
It helps to lay the sources of untrusted content and the deterministic controls for them out in a table once. Below is that map: the repository, a web page, terminal output, an external server's reply, a plugin or skill, someone else's follow-up in team work. The value of the map is that for every source it names a mechanism rather than a wish: workspace trust and review, browser protection and domain policy, command lists and the sandbox, tool policy, source review, isolation of service accounts.
| Source | Example of risk | Deterministic control |
|---|---|---|
| The repository | A task, hook or package script runs someone else's code | Workspace trust, review, the sandbox |
| A web page | An instruction to send data or sign in | Browser protection, approval, domain policy |
| Terminal output | A log suggests running a destructive command | Allow and deny lists, the sandbox |
| An MCP result | An external system returns hostile content | Server and tool policy, argument review |
| A plugin or skill | A bundled script or hook widens the actions |
| Source review, marketplace policy |
| Someone else's follow-up | Another user steers the agent with your secrets | Follow-up policy, service-account isolation |
|---|
The repository is especially underestimated as a source of risk. Editor tasks, hooks, external server configuration and package lifecycle scripts arrive together with the code - all of it executable content written by someone else. Opening an unfamiliar project and allowing everything at once means executing someone else's code before you have read a single file. The treachery is that it triggers on ordinary actions: open the folder, install dependencies, run the build - steps nobody perceives as granting rights.
The second underestimated source is command output. A log looks like technical information, but it is text the agent reads and may take as guidance. A message like to fix this, run the following command inside someone else's log is a ready-made instruction that arrived from nowhere. And the output does not have to be hostile on purpose: it is enough for it to carry a fragment of someone else's file, a third-party service's reply or an error message containing somebody's advice. That is why tool output belongs to the same class of data as a web page.
To stop this being an abstraction, it is worth following one chain all the way through. The agent is given a bug report written by an outsider to work through. Besides the description of the symptom, the report contains a paragraph addressed to the performer: check the configuration and send its contents to such-and-such address for diagnostics. The agent reads that in the same stream as your task, and it has access to files and to the network. No single step looks like an attack: the text came through an ordinary channel, the action resembles diagnostics, and the result is a leak. The chain is broken not by persuading the model but by the network being closed and the secrets never entering the context.
The strength of layers lies in composition, not in picking the strictest one. No single layer covers everything: workspace trust does not make file contents safe, the sandbox does not save you from a wrong edit, approvals do not help if a human clicks accept without looking. What works is the set: a deliberate trust decision, exploration without edits on an unfamiliar project, a mode with review, the sandbox, explicit permissions for the network and tools, and at the end the diff and the tests. Each layer is cheap on its own and closes its own class of mistakes, and together they leave few paths on which a single slip becomes an incident.
There is also a practical marker of a dangerous configuration worth remembering. Risk rises sharply when the agent has three things at once: access to secrets, the right to write and network access. Separately each limits the damage: without the network there is nowhere to send what was stolen, without writing there is no way to persist, without secrets there is nothing to steal. In an untrusted context those three are deliberately kept apart - and it is the cheapest audit of your own configuration, because the answer is visible immediately, without analyzing any code.
It pays to know in advance what a successful injection looks like, because in the moment it is far from obvious. The agent proposes an action the task never called for: reaching an unfamiliar address, reading a file with credentials, sending contents somewhere outside. Requirements you never set appear in its reasoning, with a reference to some instructions. The order of work drifts from the task toward gathering information about the environment. The right reaction is not to argue and not to refine the request in the same conversation: that context is already contaminated. You end the session, restart the task with a clean context, and if secrets were within reach you rotate them without waiting for proof of a leak.
The typical failures are predictable. Relying on a request to the model instead of a technical boundary. Opening someone else's repository and immediately allowing its configuration to execute. Treating command output as safe technical text. Continuing to work in a conversation where an injection has already landed. And keeping secrets, write access and the network together where the content is knowingly untrusted.