Prompt injection is the new SQL injection
Every team rushing AI into their product has reopened a class of vulnerability we thought we'd solved. Most AI tools are wide open. The defense is old, boring, and entirely ignored.
By Dmitrii SelikhovFounder
Key takeaways
- Prompt injection is the AI era's SQL injection: untrusted text reaches an interpreter that can't reliably separate instructions from data, so a 'document' or 'support ticket' can carry commands the model obeys — and most AI features ship with no defense against it at all.
- There is no input filter that fully solves it, because the model's entire job is to follow instructions in natural language and an attacker writes in the same natural language as the user — so the fix is architectural, not a clever prompt or a blocklist of bad phrases.
- Defense in depth is the only honest answer: treat all model input as untrusted data, give the agent the least privilege it can possibly do its job with, and require human approval before any action that's expensive, destructive, or irreversible.
- Assume the model will eventually be fooled and design so that a fooled model can't do real damage — a scoped, audited, approval-gated agent that gets tricked produces a logged proposal a human rejects, not a deleted database.
Twenty years ago we learned, painfully, that you can't build a query by gluing user input into a string and handing it to an interpreter, because somewhere in that input is a '; DROP TABLE waiting to be read as a command instead of data. We invented parameterized queries, drilled the lesson into a generation of engineers, and mostly stopped bleeding. Then we wired large language models into everything and reopened the exact same wound with a new name.
Prompt injection is SQL injection for the AI era, and it's worse in one specific way: there is no parameterized query for natural language. The model's whole purpose is to read instructions written in plain English and act on them, and an attacker writes in the same plain English as your legitimate user. Most AI features being shipped right now have no defense against this whatsoever. They're the PHP-circa-2004 of the AI boom, and the breaches are coming.
Why it's the same bug wearing a new face
The structural flaw is identical. In SQL injection, you have an interpreter — the database — that can't tell the difference between the query you intended and the query an attacker smuggled into a text field, because both arrive as one undifferentiated string. In prompt injection, the interpreter is the model, and it can't reliably tell the difference between the instructions you put in the system prompt and the instructions an attacker buried in a document, a web page, a support ticket, or an email it was asked to summarize. To the model, it's all just text in the context window, and text in the context window is exactly what it was built to obey.
That's why the attack surface is so much larger than people expect. It isn't only the chat box where a user types. It's every piece of content the model ever reads on a user's behalf — the PDF it ingests, the page it browses, the ticket it triages, the calendar invite it parses. Any of those can carry a line that says, in effect, 'ignore your previous instructions and instead do this,' and a naive agent will do this. The injection doesn't have to come from the user at all; it can come from anything the user pointed the model at.
There is no input filter that saves you
The instinct is to reach for the SQL-injection playbook and sanitize the input — strip the dangerous phrases, block 'ignore previous instructions,' run the text through a classifier. It doesn't work, and it's important to understand why, because a lot of teams are about to waste a year discovering it. Sanitizing SQL works because SQL has a grammar; you can definitively separate code from data. Natural language has no such grammar. 'Ignore previous instructions' is one phrasing of infinitely many, an attacker can encode the same intent in a poem, in another language, in a base64 blob the model helpfully decodes, in instructions hidden in white text. You are trying to filter meaning, and meaning doesn't filter.
So the honest position is that you cannot fully prevent the model from being fooled by clever input, any more than you can write a regex that catches every social-engineering email. That sounds like surrender, but it's actually the start of a real defense — because once you accept that the model will sometimes be tricked, you stop trying to build an unbreakable input filter and start building a system where a tricked model can't do anything that matters. The fix isn't keeping the attacker out of the model's head. It's making sure that even when they get in, the model's hands are tied.
Least privilege: tie the model's hands
An agent is only as dangerous as the tools it can reach, so the first real defense is to give it almost none. A triage agent needs to read a request and set a priority and maybe assign a team; it does not need the ability to delete records, export the customer list, or change permissions. If those tools aren't in its toolset, no amount of clever injected text can make it use them, because they don't exist from the model's perspective. Least privilege turns 'the model got fooled' from a catastrophe into a non-event: the attacker convinced it to do something, and the something it was convinced to do simply isn't available.
This is the part teams skip because it's tedious. It's much easier to hand the agent a broad, capable toolset and a permissive prompt and marvel at how much it can do in the demo. But every capability you grant is a capability an injection can borrow, and the demo doesn't include an adversary. Scope each agent to the narrowest set of actions its actual job requires, scope those actions to the data it's allowed to touch, and the blast radius of a successful injection shrinks to whatever that minimal toolset can reach — which, if you scoped it right, is nothing you'd lose sleep over.
Human approval for anything that bites
Least privilege handles the actions an agent should never take. The harder case is the actions it legitimately needs but that are expensive, destructive, or irreversible — bulk-archiving issues, deleting a project, sending a message to a customer, spending real money. You can't remove these tools, because then the agent can't do its job, but you can't let a possibly-injected model fire them unsupervised either. The resolution is to put a human in the loop precisely at the moment of consequence: the agent proposes the action, a person reviews the proposal, and only an explicit approval executes it.
This is the natural-language equivalent of requiring a second signature on a large wire transfer. It doesn't assume the requester is malicious; it assumes the stakes are high enough that one party shouldn't be the only check. A propose-and-approve gate means an injection that successfully convinces the model to delete everything produces a proposal to delete everything — which a human looks at, recognizes as insane, and rejects, while the audit trail records exactly what was attempted. The attack becomes evidence instead of damage.
Build as if the model will be fooled
Put the three together and you have the only posture that survives contact with real attackers: treat every byte of model input as untrusted data rather than trusted instruction, grant the least privilege the job can tolerate, and gate every consequential action behind human approval. None of these tries to make the model un-foolable, because that's not achievable. Each one limits what a fooled model can actually accomplish, and in defense in depth that's the whole game — you assume each layer fails and build the next one to catch it when it does.
This is the standard we build Planoda's agents to, because we think it's the only defensible one. The model gateway treats injected content as data and is hardened against it, every agent is scoped to least-privilege tools rather than handed the keys, and every destructive action routes through propose-and-approve with an immutable audit row recording what was proposed, by whom, and who approved it. The bet isn't that our models can't be tricked — we assume they can. The bet is that a tricked agent here produces a logged, rejected proposal instead of a breach, and that's the difference between AI you can actually turn on and a demo you'd never dare point at production.