Home

/

Prompt Injection: Blast Radius

/

Quarantine: The Planner Never Reads the Mail

Quarantine: The Planner Never Reads the Mail

Chapter 7
Part II
6
min read

Chapter 6 ended on an uncomfortable result. Once a model reads tainted content, everything it emits for the rest of the session is tainted, because its context now contains the attacker's text and every subsequent token is conditioned on it.

Tracking that spread is honest and not much help. The structural answer is to stop the spread instead: keep the tainted text out of the model that decides things.

Two models, two jobs

Split the work between a planner and a quarantine.

The planner holds the conversation, decides what to do, and calls tools. It sees your system prompt, the authenticated user's turn, and typed results. It never sees a retrieved document, a fetched page, or an uploaded file.

The quarantine reads untrusted content. It has no tools. It cannot call anything, reach anything, or take any action. Its only output is a value conforming to a schema the planner asked for.

The technique comes from Google DeepMind's CaMeL, published as Defeating Prompt Injections by Design. Their terms are the privileged LLM and the quarantined LLM, and their central property is worth quoting because it is stricter than what most implementations attempt: at no point is content handled by the quarantined model exposed to the privileged one. The quarantined model populates references, and the planner passes those references around without ever seeing what they contain.

Willison's earlier dual-LLM pattern is the ancestor. His own assessment of CaMeL, when it appeared, was that it offered a promising direction. Promising is the right word and it is not the same as solved.

The typed contract

The boundary between the two is a schema, and the schema is the whole security mechanism.

public interface IQuarantinedReader
{
    Task<T> ExtractAsync<T>(Tagged<string> untrusted, CancellationToken ct)
        where T : notnull;
}

public sealed record RefundRequest(decimal Amount, string Currency, string OrderId);

The planner asks for a RefundRequest. What comes back is three fields with three types. The document that produced them is never in the planner's context.

Consider what an attacker can do through that interface. They control a PDF. The quarantine reads it. The most they can influence is the value of a decimal, a three-letter currency code, and an order identifier. There is no field in RefundRequest capable of carrying "ignore previous instructions", because a decimal does not have a field for prose.

This is the property to internalise. Quarantine does not make the content safe, it removes the content's ability to be instruction-shaped by the time it reaches the component that acts. The attacker's text cannot become a directive because there is no longer any text.

What quarantine does not do

A dangerous misreading is available here and it is worth closing off directly.

The attacker still controls the values. They wrote the PDF, so they chose the amount. The quarantine faithfully extracted 2,400 because 2,400 is what the document said. Nothing was prevented.

What changed is the class of the attack. Before quarantine, an attacker could make the planner do anything the planner was capable of, including calling tools the task never needed. After quarantine, an attacker can only supply wrong values to the specific operation the planner had already decided to perform.

That is a large reduction and it is not elimination, which is why the extracted values stay tainted and why chapter 9's gate still refuses tainted arguments on irreversible actions. The two primitives are doing different jobs. Quarantine constrains the shape of attacker influence. Provenance and the gate constrain what may be done with it.

References, not content

Often the planner does not need the value at all, only the ability to move it around.

public sealed record Ref(string Id);

var summary = await _quarantine.SummariseToRefAsync(document, ct); // Ref("doc-1")
await _mail.SendAsync(to: recipient, bodyRef: summary, ct);

The planner decides that the summary should be sent to the recipient. It never learns what the summary says. The mail tool resolves the reference at the point of sending, outside the planner's context.

This is CaMeL's mechanism and it generalises well. Any time the planner is routing rather than reasoning about content, pass a reference. The context window stays clean and the attacker's text never enters the component holding the tools.

Where the boundary leaks

Three ways this fails in practice, all of them worth designing against explicitly.

Free-text fields in the schema. A RefundRequest with a string Reason re-opens everything. The attacker writes their instruction into Reason, the planner reads the field while composing its next step, and the quarantine has been defeated by a single convenient field. Where a schema genuinely needs prose, that field is a reference, never a value.

Error messages. The quarantine fails to parse, and the exception helpfully includes the offending input. That exception reaches the planner's context. An attacker who can force a parse failure has a channel straight through the boundary, and this one is easy to ship by accident.

Enum abuse. A constrained field still carries a few bits. An attacker choosing between five valid categories is signalling, and across enough calls that is a covert channel. Low bandwidth, real, and mostly acceptable. Know it exists before someone finds it for you.

The CV attack, twice

Chapter 2 left an attack running. A recruitment assistant reads applications; an applicant hides one sentence in white four-point text instructing it to mail the shortlist and internal scoring notes to an address in the contact block.

Without quarantine. The screening model reads the whole PDF, because reading the whole PDF is the task. The hidden sentence enters its context alongside the system prompt. It holds a mail tool, because filing and forwarding notes is what it was built for. It composes a message and sends it. Every component behaved as designed.

With quarantine. The planner asks for a CandidateSummary, declared as a name, a years-of-experience integer, a list of skills drawn from a fixed vocabulary, and a reference to a prose summary it will never read. The quarantine reads the PDF, including the hidden sentence, and returns those four things. There is no field in which the instruction can survive. The planner files the note and the attack is simply absent from the system, not detected and not blocked.

The attacker still influenced the outcome. They chose the skills list, and could have inflated the experience figure. That is the residual risk and it is a recruitment problem rather than a security incident.

the-three-year-bug
why-the-industry-shipped-anyway
injection-is-not-jailbreaking
why-the-confusion-persists
the-lethal-trifecta
running-the-audit
why-filtering-fails
measured-here-on-a-named-model
why-this-is-structural
what-solved-would-look-like
the-harness
provenance-every-value-knows-where-it-came-from
on-the-reference-agent
quarantine-the-planner-never-reads-the-mail
what-two-models-cost-in-practice
capability-authority-the-agent-cannot-widen
expiry-is-a-feature
the-gate-the-model-proposes-code-disposes
the-policy
failing-closed
egress-closing-the-exfiltration-leg
how-much-can-actually-leak
sandboxing-containing-the-code-the-agent-writes
the-sandbox-held-and-it-did-not-help
poisoned-memory-poisoned-retrieval
cleaning-up-afterwards
the-tool-supply-chain
mcp-and-the-rest
human-in-the-loop-that-isnt-theatre
when-there-is-nobody-there
testing-for-injection
measuring-coverage-not-pass-rate
red-teaming-agents
a-finding-worked-through
when-it-happens-anyway
what-the-logs-cost-you-in-an-incident-you-did-not-have
governance-procurement-and-the-regulator
writing-the-policy
end-to-end
what-it-actually-took
what-stays-broken
why-this-is-probably-structural
the-trifecta-audit-worksheet
action-schema-and-policy-reference
control-mapping
prompt-injection-sources
incidents
appendix-e-what-we-re-ran-ourselves
e4-the-control-that-keeps-e2-and-e3-honest

Download the full PDF for free?

Free download — no account required

Get the PDF
Get the PDF
Related Chapters
Free Download
Get the full PDF
All pages, including all code examples, diagrams, and the appendix reference card.
No spam. Unsubscribe at any time.
Your email won't be shared.
Oops! There's a problem with your request. We're working on fixing it. Please try again later.