What a Migration Does to Your Prompt Injection Defences
10 min read · updated August 11, 2026
“Do our injection defences still work on the new model?” is two questions wearing one coat. Some of what you built is enforced by code that does not care which model is behind it. The rest is a behaviour you observed in one model and wrote down as a defence, and that part has no reason to survive a swap.
The question a swap raises
Prompt injection is the failure where text that arrives as data — a retrieved document, a web page, a tool result, a user’s file — is treated by the model as instruction. The general treatment of the attack and its countermeasures is in prompt injection and prompt injection defences. The narrower question here is what a provider migration does to a set of defences that was working.
The common answers are both wrong. “Injection is a model problem, so everything must be re-tested” treats deterministic controls as if they were probabilistic, and produces a re-test plan so large it does not get done. “Our defences are in the application, so nothing changes” is the more dangerous one, because most real defences are a mixture and the mixture is not labelled.
Two classes of defence
The line that actually predicts transfer is this: does the defence still hold if the model complies fully with the injected instruction?
If yes, the defence is architectural. The model can be entirely fooled and the attack still fails, because something outside the model refuses to carry it out. If no — if the defence works by the model deciding not to follow the injected text — it is behavioural, and it is a property of that model’s training, not of your system.
- Architectural: tool allowlists per context; requiring human confirmation before an irreversible action; scoping credentials so the agent cannot reach data the current user cannot; validating tool arguments against a schema and a business rule before execution; never interpolating untrusted text into a place with elevated authority; rendering model output as text rather than as markup or executable code; rate-limiting and budget caps on tool loops; logging and post-hoc review.
- Behavioural: delimiter conventions that mark untrusted regions; a system instruction saying to ignore instructions found inside data; spotlighting or datamarking techniques; asking the model to classify whether the input contains an injection attempt; relying on the model to refuse an obviously harmful instruction; and — the one people forget is behavioural — relying on the model to keep an output format that your parser depends on.
Why the architectural class transfers
Because it does not involve the model in the enforcement. If the tool registry available in the document-summarisation context contains three read-only tools, an injected “now send an email to [email protected]” cannot succeed regardless of how convincing the injection is or how compliant the model is, because there is no email tool in scope to call. The model may emit a call to a name that does not exist — a case worth testing, see testing what happens when a model calls a nonexistent tool — and your dispatcher rejects it.
This is why the architectural class is worth building even though it is more work than a paragraph in the system prompt: it is the only part of your defence with a guarantee attached, and it is the only part that survives a model swap, a model upgrade, a silent provider-side update, or an attack technique nobody has published yet. Everything else degrades quietly as the world moves. That is an argument for architecture over instruction generally, and a migration is simply the moment the difference becomes visible.
The one caveat: architectural defences transfer only if they are truly outside the model. A tool allowlist implemented by telling the model which tools it may use in this context, while all the tools stay in the tools array, is behavioural wearing an architectural costume. So is a schema that is described in a tool description rather than enforced by a validator. Audit for that costume before you assume transfer.
Why the behavioural class does not
A behavioural defence works because the model was trained in a way that makes it respond to that pattern. Three specific dependencies make them model-specific.
Delimiter conventions are trained conventions. Models differ in which structural markers they were trained to treat as significant. XML-style tags, fenced blocks, headed sections and JSON envelopes are not equally salient to every model, and a prompt built around one convention because it demonstrably held a boundary on the old model has not established anything about the new one. Rewriting prompts around a target model’s preferred delimiters is a real migration task — see rewriting XML-delimited prompts.
Instruction hierarchy is a trained property. How strongly a model privileges the system instruction over content later in the context varies, and it is precisely the property injection attacks the. A defence that rests on “the system prompt wins” rests on a gradient, not a rule, and the gradient is different on different models.
Refusal posture is a trained property. Where the last line of defence was the model declining to do something plainly harmful, you inherited a safety posture you did not build and cannot port. It may be stricter on the new model, which shows up as false refusals on legitimate traffic; it may be looser, which shows up as nothing at all until someone finds it. Both directions are covered in refusal behaviour after a model migration.
None of this means the behavioural class is worthless. Layered defence is the right posture and a defence that stops eight attacks in ten is worth having behind one that stops the tenth. It means only that the evidence for a behavioural defence is empirical and the evidence expires when the model changes.
What to re-establish, and in what order
The practical consequence is that a migration re-test is not a full security review. It is a short list, in this order:
- Inventory the defences and label each one with the comply-fully test above. This takes an hour and is the highest-value hour in the exercise, because it usually reveals two or three controls everyone believed were architectural and are not.
- Confirm the architectural set is still enforced after the client rewrite — not re-derived, just confirmed. Tool dispatch, argument validation, credential scope and confirmation gates are code paths a provider migration can accidentally bypass when the response parsing changes.
- Re-run your injection corpus against the new model for the behavioural set. If you do not have a corpus, this is the moment to build one from the attempts your logs already contain; a few dozen real cases beat a published list.
- Re-run it with the tool layer disarmed so that a successful injection is visible rather than absorbed. Measuring defence-in-depth end-to-end tells you only that the stack held; you want to know which layer held, because the answer determines what to fix.
- Re-tune the behavioural prompts against the new model and re-run. Expect this to be iterative, and expect at least one phrasing that worked well to stop working.
The uncomfortable conclusion is that a migration is a good audit precisely because it forces the inventory. A system whose injection resistance mostly came from one model’s training was never as defended as its documentation said; the swap does not create that weakness, it discloses it.