Why prompt injection is not solved
What the problem is, why filtering does not fix it, and what does help. Written for someone about to give a model access to something real.
Tested on Claude Sonnet · 4.5 ·
Every guide to AI security ends up saying sanitise your inputs. For prompt injection that advice is nearly useless, and you should know why before you build on it.
The problem in one paragraph
A model gets one stream of text. Your instructions and the data it is working on arrive in the same channel and the same format, with nothing reliable to tell them apart. When a document says ignore the above and do X, nothing guarantees that the model reads it as content and not as a command. No single model is to blame. It is what happens when instructions and data share a channel, and it belongs to the same family as SQL injection. SQL has parameterised queries. Here there is no equivalent.
Why filtering does not work
In SQL injection the dangerous strings form a small set you can describe, and the parser is deterministic. With a language model, the dangerous input is any text that carries an instruction, in any language and any phrasing, including phrasings nobody has thought of yet. A filter for ignore previous instructions misses a paragraph that persuades instead of commanding. There is no complete list to match against.
What reduces the damage
Cut what the model can reach. Limiting consequences is the one defence that holds. A model with a read-only database role cannot drop a table, however convincing the injected text is. Put most of your effort here. It is also why the mcp entries on this site talk about scope and say little about prompts.
Separate the channels as far as the API lets you. Instructions go in the system message, untrusted content in a user message, marked as content. The boundary is weaker than a parser. It is real, and it costs nothing.
Ask a human to confirm anything irreversible. If a tool call sends an email, spends money, deletes something or writes to a shared system, put a person in front of it. You do not need that for every call, only for the ones you cannot take back.
Make attempts visible. Ask the model to report instruction-like content and not to refuse in silence. You then learn that a page in your pipeline is hostile, which beats a clean refusal you never see.
Assume the system prompt is public. People have extracted enough system prompts that keeping yours secret is a plan built on hope. Keep credentials, internal URLs and anything about other users out of it.
What to do with that
None of this makes injection impossible. A model that reads untrusted content and holds a powerful tool is a risk you accept, not one you remove. Stop asking whether your prompt is secure. Ask what happens when it fails, and whether you would notice.
For information only, not professional advice. You use it at your own risk and we are not liable for any loss or damage. See the disclaimer.
Tagged