Zero-width characters in text

unicode.zero-width

Codepoints that occupy no width sitting inside ordinary text, removed from the text we hand back and reported as a low-confidence record rather than an alarm.

How the text is hidden

Five codepoints carried in the character string itself: U+200B zero-width space, U+200C zero-width non-joiner, U+200D zero-width joiner, U+2060 word joiner and U+FEFF. None of them draws anything, so the page a person reads is unchanged whether they are present or not. Because they live in the string rather than in the format's styling, they are the one concealment family that survives extraction into plain text — the engine's own comment calls this the family that is "carried in the string itself". They can also break a caller's exact-substring matching: one of them inside a word means a search for that word finds nothing.

Why a model still reads it

The characters are part of the text, not a property of the file, so every extractor copies them through verbatim and the model tokenises whatever they produce. Nothing in the extraction path has a reason to drop them.

What we do about it

The rule pack carries a zero-width class in unicodeClasses whose pattern is the five codepoints; stripFamilyC runs every class in the pack over the joined canonical text, records each match position, and removes it. The text is STRIPPED — the caller's text.canonical no longer contains these characters, and for DOCX the cleaner runs the same pass over the file's own text elements so the cleaned bytes lose them too. The class is declared highConfidence: false, and codepointFindings grades a low-confidence class informational: it is recorded, it does not move the verdict, and it still withdraws certified. One character between two digits matches BOTH this class and zero-width-in-number, so such a document carries two findings counting the same character.

How often it fires

1.4% of CUAD — 510 real commercial contracts (EDGAR EX-10 exhibits), bulk-converted from HTML by Aspose/EVO, measured 2026-08-17.

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.

Seen in the wild

7 Oct 2026 · Barracuda · incident
Threat Spotlight: Email attacks target both humans and AI in the same message

A phishing campaign hid a block of text in an invoice email telling the recipient's AI summariser to add a fake priority action changing vendor payment details; Barracuda names four ways such instructions are hidden — HTML comments, CSS-invisible text, Base64 inside an image data string, and zero-width characters — but does not say which one this email used.

10 Mar 2026 · Cloud Security Alliance · research
Hidden Unicode Instruction Injection in AI Agent Skills: Invisible Adversarial Payloads in Tool Descriptions, Skill Files, and MCP Servers

Instructions written in Unicode Tags block characters and zero-width characters, invisible in every standard interface but read as tokens by the model, were placed in agent skill markdown files and MCP tool descriptions, and production agent platforms executed the shell commands they carried.

18 Mar 2025 · Pillar Security · research
New Vulnerability in GitHub Copilot and Cursor: How Hackers Can Weaponize Code Agents

The configuration files that steer AI coding assistants carried instructions written in zero-width joiners and bidirectional text markers — unreadable to a human reviewer, fully parsed by the model — and Copilot and Cursor generated backdoored code from them without mentioning it.

Every recorded incident, across all techniques.

next

Check your own file

Three commands: a key, credit, a verdict.

Start with the API