Variation selectors behind a character

unicode.variation-selector

Invisible selectors that normally pick a glyph variant, and can instead be chained behind one base character to carry an arbitrary byte payload.

How the text is hidden

Two ranges: VS1 to VS16 at U+FE00–U+FE0F, and VS17 to VS256 at U+E0100–U+E01EF. Their designed job is to select a variant of the character they follow — emoji presentation, or an Ideographic Variation Sequence in CJK typography — and they draw nothing of their own. Because there are 256 of them, each one can stand for a byte, so a chain of selectors trailing a single visible character carries an arbitrary byte string with no visible trace on the page.

Why a model still reads it

The selectors are ordinary codepoints in the string, so extraction copies them and a model's tokeniser sees whatever they produce. A reader sees one base character and nothing else.

What we do about it

The pack class variation-sel matches both ranges, is declared highConfidence: false, and is therefore graded informational by the confidence-band mapping — recorded, not verdict-moving, and still enough to withdraw certified. The characters are stripped from text.canonical, and for DOCX from the cleaned file. The finding reports a count and an escaped excerpt through renderVisible.

How often it fires

0.56% of 1,244 real documents — 400 web pages (distinct hosts), 630 PDFs (contracts and web), 150 government Word documents, 65 SEC filings, measured 2026-08-21.

This is an alert-volume number and nothing else. It says how often the alarm sounds on documents as found — not how often it is right, and not whether what it found was harmless. Documents as found may themselves carry concealment. Read it against the population named above rather than as a property of documents in general.

next

Check your own file

Three commands: a key, credit, a verdict.

Start with the API