prompt.hidden_text
The text contains zero-width, bidi-control, Unicode Tag, variation-selector, filler or private-use characters that hide content from a human reader.
Source: rules.
What it looks at#
Invisible or near-invisible Unicode, in these categories (data.matches[].rule):
- zero_width — zero-width space/joiner/non-joiner, word joiner, BOM, Mongolian vowel separator.
- bidi_control — left-to-right/right-to-left/Arabic letter marks and embedding/override/isolate controls.
- format — soft hyphen and the invisible math operators.
- unicode_tag — characters in the Unicode Tag block (U+E0000–U+E007F), the documented “ASCII smuggling” channel: these render as nothing in virtually every font, but many tokenizers round-trip them as if they carried the shadowed ASCII text, making them a way to hide an entire instruction from anyone reading the rendered text.
- variation_selector — a run of two or more variation selectors.
- filler — Hangul fillers (U+115F, U+1160, U+3164, U+FFA0) outside Hangul text and the Braille blank (U+2800).
- braille — a run of Braille pattern characters that decodes to readable text.
- private_use and unassigned — runs of two or more private-use or unassigned code points. A single private-use character (the Apple logo, an icon-font glyph) is ignored.
Ordinary whitespace is never flagged. These are deliberately excluded because they are invisible but not evasive: a zero-width joiner inside a real emoji sequence (👨👩👧👦) or between Arabic/Indic letters, a single variation selector after an emoji, left-to-right/right-to-left marks next to right-to-left script, a BOM at the very start or end of the text, Hangul fillers inside Hangul text, and the tag sequence in subdivision-flag emoji.
When hidden characters decode to readable text the run is reported as
prompt.unicode_smuggling instead — one
finding per run.
Why it matters#
Every category here exists to make text render differently, or render nothing at all,
compared to what a model actually processes. /v1/spam’s equivalent check treats this as
evasion for splitting a blocked word; here the risk is bigger — hiding an entire
instruction inside text that looks empty or ordinary to a human reviewer.
What to do#
High severity — on its own this pushes the verdict to block. There is essentially no
legitimate reason for ordinary user-facing text to contain Tag-block characters at all;
zero-width/bidi characters have rare legitimate uses (Mongolian text, genuinely
bidirectional content), so check data.matches[].rule before assuming intent.