The attempt is the easy half.
Everyone catches "ignore your previous instructions". The question is what happens when something got through, and when the instruction arrived inside data your agent was told to read.
Rules plus a model you host.
Three places to look
| Where | What it catches | ATLAS technique |
|---|---|---|
| The prompt | The attempt. Normalization and decoding first, then patterns, Prompt Guard 2 and DeBERTa in parallel — any one of them firing blocks the call before anything else runs. | AML.T0051 LLM Prompt Injection |
| The reply | Whether it worked. A model that has been taken over says so in its output, and a canary token proves extraction outright. | AML.T0069 Discover LLM System Information |
| The tool response | The one nobody guards. A poisoned page or record becomes an instruction on the way back to the model. The same detectors can be pointed at a tool's reply — a rule you write. | AML.T0110 / AML.T0099 AI Agent Tool Poisoning |
Why the identifiers
Those are technique IDs from MITRE ATLAS, MITRE's knowledge base of adversary tactics against AI systems. It holds 16 tactics, with techniques and sub-techniques under them, drawn from real attacks and red-team work, and agentic AI is a platform of its own there. It ships monthly. We cite them so you can check the claim: open the technique, read what it is, and judge whether the control answers it.
The canary
# The gateway watches every response for this token.
canary_system_prompt:
all:
- path: "event.type"
op: eq
value: "llm.input"
- path: "event.data.endpoint.is_guardrails_enabled"
op: eq
value: true
effects:
verdict: approved
priority: 50
state_changes:
user:
change_counters:
total_requests: 1
response:
canary: "swcanary-{{ event.entity_id }}" A per-user token goes into the system prompt on the way in. If that token ever turns up in a response on the way out, the system prompt was extracted. Not a probability — a string that should not be there.
Decoding, and more than one language
It decodes before it matches. An attacker does not send the instruction in plain text. They send it double-escaped, or buried in the JSON arguments of a tool call. Swiftward decodes those first: a literal \uXXXX sequence a client escaped twice, and the JSON source inside a tool call's arguments. A detector run on an undecoded payload finds nothing, which is why an attacker escapes it.
It works outside English. Two detectors run in parallel rather than one, because the best-known open injection detector gets much weaker outside English and the second one covers what it misses. If your users write in more than one language, the second detector is what makes the control work at all.
The detector reports, the rule decides
A detector returns a number. Your rule decides what that number means for this endpoint, this agent, this customer, and it is versioned like every other rule. Swapping a detector is a change to one input rather than a rewrite of your policy, which matters because detectors go stale faster than policies do.