prompt.unicode_smuggling
Invisible Unicode characters that decode to a readable message addressed to the model.
Source: rules.
What it looks at#
Runs of characters that render as nothing but carry data, decoded and tested for readable text (valid UTF-8, mostly printable, at least four letters):
- unicode_tag — Tag-block characters (U+E0000–U+E007F) shadowing ASCII. The most widely demonstrated “ASCII smuggling” channel.
- variation_selector — a run of two or more variation selectors (U+FE00–FE0F, U+E0100–E01EF), each encoding one byte. A single selector after an emoji or a CJK ideograph is normal and ignored.
- zero_width — a run of 16+ zero-width characters drawn from two symbols, read as a bit stream.
- braille — a run of Braille pattern characters read as a byte stream.
Legitimate uses are left alone: the subdivision-flag emoji (a Tag sequence after U+1F3F4), ZWJ inside emoji and Arabic/Indic text, variation selectors on emoji.
Why it matters#
A human reviewer sees an empty-looking string; a model may read the whole message. This
is the channel used to hide instructions in documents, web pages and tool output that an
agent is about to read. Unlike prompt.hidden_text,
which says “there are invisible characters here”, this says the invisible characters are
an actual message.
What to do#
High severity — on its own this pushes the verdict to block. Text that is hidden and
readable is hard to produce by accident. The response never echoes what the characters
decoded to (design rule 1); location is the span of the hidden run in your original
text, and data.matches[].rule names the channel. When the decoded message also matches
an instruction phrase list, this single finding covers the run — it is not reported
twice.