Prompt injection stopped being a chatbot party trick the moment we gave models tools. Here's why it can't be patched the way SQL injection was, what the GitHub MCP heist and CVE-2025-6514 actually looked like, and the three-ingredient rule for telling whether your agent is exploitable.

For about two years, prompt injection was treated as a party trick. You typed “ignore your previous instructions” at a chatbot, it said something it was not supposed to, everyone screenshotted it, and nothing was actually at risk because the model could not do anything.
That changed when we started handing models tools. An assistant that can only produce text has a fairly boring failure mode. An agent that can read your repositories, query your database, send email and execute shell commands has the same failure mode attached to real capability — and the industry connected those wires far faster than it worked out how to secure them.
If you have done any SQL injection work, you already understand the shape of this problem — and, more importantly, why the fix that worked there does not port over.
SQL injection was solved by parameterised queries. Not by filtering apostrophes, not by escaping better, but by giving the query and the data two separate channels so that data physically cannot be parsed as instructions. The database engine holds that boundary; no amount of cleverness in the input crosses it.
A language model has exactly one channel. System instructions, retrieved documents, tool output and user input are concatenated into a single token stream. The model infers which part is authoritative from context and training, which is a probabilistic judgement, not a structural guarantee:
This is why every mitigation to date is probabilistic. Delimiters, instruction hierarchies, and classifier guardrails all raise the cost of an attack. None of them makes it impossible, because they are all still expressed in the same channel the attacker is writing into.
Direct injectionis a user typing an attack into the box. It is real, but the blast radius is limited to that user's own session and their own permissions. Someone jailbreaking a chatbot into swearing has mostly harmed themselves.
Indirect injectionis the dangerous one. The attacker never talks to the model at all. They plant instructions in content the agent will later read — a web page, a support ticket, a code comment, a calendar invite, a filename, the alt text of an image — and wait for someone else's agent to consume it. The victim is not the attacker's account. The victim is whoever's agent happens to fetch that content, carrying whoever's permissions that agent runs with.
Three disclosures from the last year make the pattern concrete, and none of them required a novel model exploit.
In May 2025, researchers at Invariant Labs showed that a booby-trapped issue filed on a publicrepository could hijack a developer's agent. The developer asks something entirely ordinary — “have a look at the open issues” — the agent reads the malicious issue, follows the instructions inside it, pulls data out of the developer's private repositories, and publishes it in a pull request on the public repo.
The crucial detail: this was not a coding flaw in the MCP server. Invariant were explicit that it is an architecturalproblem — the server holds one token with broad access, so any successful injection inherits all of it. There is no patch for “the agent did exactly what it was permitted to do”.
Disclosed by JFrog in July 2025 and rated 9.6, this one is a more conventional bug in mcp-remote, the npm bridge used to connect clients to remote MCP servers. A malicious server returns a crafted authorization_endpointduring the OAuth flow, and the value is passed to the operating system unsanitised. On Windows that is full arbitrary command execution on the developer's machine.
# The class of bug is decades old.
# The context is new: it fires when a developer's
# tooling connects to an untrusted MCP server.
authorization_endpoint -> passed unsanitised to the OS
-> command injection
-> RCE on the developer's laptop
affected: mcp-remote 0.0.5 - 0.1.15
fixed in: 0.1.16Note what this is: command injection. Not an AI vulnerability at all. The AI ecosystem simply built new plumbing quickly, and the new plumbing had the same bugs the old plumbing had in 2005.
An agent picks which tool to call by reading each tool's description— text supplied by the tool's author. That makes tool descriptions an injection surface: a malicious server can describe its tool in ways that steer the agent, or quietly change that description after the user has already approved the server.
And because MCP servers ship as ordinary packages, they inherit ordinary supply chain risk. The postmark-mcp package is the clean example — fifteen legitimate releases, then a version that added silent exfiltration. Users had already vetted and trusted it fourteen versions earlier.
The most useful way to reason about whether a given agent is actually dangerous is to check for three properties at once. An agent needs all three before injection turns into theft:
This is genuinely useful in design review, because it converts an unsolvable research problem into a concrete architectural question. You are not trying to make the model injection-proof — you cannot. You are trying to make sure no single agent session holds all three properties simultaneously.
| Ingredient | How to remove it |
|---|---|
| Access to private data | Scope the token to the one resource this session needs. The GitHub case was fatal precisely because one token reached every repository. |
| Untrusted input | Usually impossible to remove — reading external content is the point of the agent. Assume this one is always present. |
| An outbound channel | Require human approval for actions that leave the boundary: opening PRs, sending mail, outbound HTTP, writing to shared storage. |
There is a temptation to file this under “AI stuff” and leave it to someone else. That is a mistake, because almost every real incident above resolves into a bug class that has been on the syllabus for twenty years.
| The AI framing | What it actually is |
|---|---|
| Prompt injection | Untrusted input crossing into a control channel — the same root cause as injection generally. |
| Excessive agency | Broken access control. The agent acted with permissions far wider than the task needed. |
| Tool poisoning | Supply chain compromise, with a package that reached a trusted position first. |
| CVE-2025-6514 | OS command injection, unchanged since the 1990s, in new plumbing. |
| Agent data leakage | An exfiltration channel nobody enumerated during design. |
The skill that transfers is the underlying one: knowing where a trust boundary is supposed to be, and testing what happens when input crosses it. Agents just moved the boundaries somewhere unfamiliar and handed them far more privilege than the old ones ever had.
Everything in this post has a hands-on lab on hackr.gg. Exploit it yourself right inside the lesson — no setup, no install, runs in your browser.
Open Prompt Injection course →