Skip to content

Use case

Injection through a retrieved document

The dangerous input is rarely the one the user typed. It is the one a tool went and fetched, and it arrives already inside the trusted area.

trusted areaplannerexecutorno re-inspectionretrieved docanswer

The situation

A planning agent searches an internal index, gets three documents back, and passes the most relevant one to an executor agent that can call tools. One of those documents is a PDF a supplier uploaded to a shared folder eighteen months ago.

It contains a line addressed to whatever model reads it. Nobody typed that line into your product, so nothing on the user-facing path ever saw it.

What breaks without a check

Everything inside the trusted area is trusted by construction, which is correct and is the whole point of the design. It only holds if the boundary is where you think it is. A retrieval tool that returns text from outside is a second entrance, and if it is unguarded then the trusted area extends to your supplier’s shared folder.

Which detectors apply

The policy is data, not code. A reviewer who does not write Python should be able to read this and say whether it is right.

border-code.yaml
detectors:  injection:    on_fail: block    threshold: 0.43         # calibrated, lower than the 0.5 default on purpose  secrets:    on_fail: block  gibberish:    on_fail: flag    threshold: 0.37         # unreadable input short circuits the tiers above it

The same case in code

The scan sits where the text enters the trusted area, which is the retrieval tool, not the chat endpoint. Everything downstream of this loop trusts what it is handed, and that is the design working rather than the design failing.

retrieval_gate.py
# The user turn is not the only entrance. Every retrieved# document crosses the boundary too, and it crosses here.documents = search_index.query(task) checked = []for doc in documents:    crossing = scan_input(doc.text, policy)    if crossing.verdict == "block":       # injection, secrets        quarantine(doc.uri, crossing.evidence.record_id)        continue    checked.append(crossing.text) # Inside the area, planner and executor exchange text freely.# The stamp on each document is why no second inspection runs.plan = planner.run(task, context=checked)

What the stamp holds

A stamp on the retrieved document, not just on the user turn. That is what lets the executor agent accept it: the check ran at the point it entered the area, so the exchange between planner and executor needs no second inspection. Services that accept each other’s stamps are what the area is.

Read by the engineer debugging why an agent did something nobody asked it to.

What this does not catch

  • The published threshold matters more than usual here: the model separates injections from prose well below the 0.5 default, so a policy that overrides the calibrated threshold can quietly turn the detector into a no-op.
  • It reads text. It knows nothing about what your tools are permitted to do, and a correctly classified injection that your agent was allowed to act on is still an incident.
  • Maltese is the weakest language in the set, because it is absent from the base model’s pretraining. Its row is published rather than dropped.
  • This is not a substitute for scoping tool permissions. It is the check that tells you the text was hostile, not the control that stops the damage.

The full detector set, or the per-language numbers.