Somewhere in the Unicode standard sits a block of characters designed to be invisible. Not styled to be small, not colored white on white. Invisible. No font renders them. No screen displays them. Your eyes will never see them, but a computer reads them just fine. That gap between what you see and what the machine processes is the entire attack.
This isn’t a new idea. People have been hiding data in plain sight since long before the Internet existed. Bulletin board system (BBS) users in the 1980s and 1990s traded messages with hidden control characters and non-printing bytes to smuggle information past sysops and filters. The technique is old. What changed is the target.
What Are Unicode Tag Characters?#
Unicode reserves a range of code points called the tag block, originally meant to annotate text with metadata like language variants. Browsers and most applications don’t render them at all. They occupy the code point range U+E0000 through U+E007F, and they mirror the ASCII character set exactly, just shifted into invisible territory.
That mirroring is the trick. The tag character for “A” isn’t a random invisible glyph. It maps directly to the ASCII value for “A”, just encoded at a different code point. This means you can take any ASCII string, “ignore previous instructions” for example, and re-encode every character as its invisible tag equivalent. The result is a string of bytes that a text renderer skips over entirely, but that a machine parsing raw Unicode reads as the original message, character for character.
You can append this invisible payload to any normal, visible text. A user sees “Thanks for your order!” A language model or automated parser sees “Thanks for your order!” followed by an invisible, fully formed instruction it wasn’t supposed to receive.
From AI Red-Teaming to Everyday Spam#
ASCII smuggling first showed up in security research focused on large language models (LLMs). Researchers found that if you embedded invisible tag-encoded instructions inside a document, email, or web page, and a model ingested that content as part of its context, the model would sometimes follow the hidden instruction as if the user had typed it. This is a form of prompt injection, where an attacker’s text competes with the legitimate user’s intent for the model’s attention. Because the injected text was invisible to any human reviewing the source material before it reached the model, the attack was nearly impossible to catch through visual inspection.
That was the proof of concept. It didn’t stay confined to AI security circles for long.
Spammers picked up the same technique and applied it to a much older problem: getting past content filters. Email and messaging platforms have spent years building keyword-based and pattern-based filters to catch spam and phishing attempts. Words like “wire transfer,” “gift card,” or “urgent” get flagged. But a filter that scans visible text won’t catch a keyword if it’s encoded as invisible tag characters and interspersed with, or appended to, otherwise clean text. The email looks benign to a human reader and to any filter that tokenizes only what’s displayed. Meanwhile, the invisible payload might be read differently by downstream systems, including AI-powered inboxes, summarization tools, or automated triage systems that process the raw text rather than the rendered version.
This migration matters as a case study on its own. A technique proven in a niche context, adversarial testing of language models, moved into mainstream abuse within a short window once the mechanism became public. That’s the pattern with most offensive techniques. Once someone demonstrates that a class of attack works and publishes how, defenders in unrelated domains rarely get advance warning. The email security world and the AI security world don’t talk to each other by default, and this is exactly the kind of technique that falls through the cracks between them.
Why Visual Inspection and Keyword Filters Fail Here#
The core problem is that most filtering pipelines were built on an assumption: what the filter sees is what the human sees. Keyword matching, regular expressions, and even manual review all operate on the rendered or extracted text. Tag characters break that assumption cleanly. The bytes are present in the raw content, but they never surface in any visual representation of it.
Some filters do decode text before matching, stripping formatting and normalizing encoding. But normalization routines were designed to handle things like accented characters or full-width versus half-width forms, not to explicitly recognize and strip an entire block of code points meant to be invisible by design. If your filter doesn’t know the tag block exists, it will pass it straight through.
What Are the Inputs and What Are the Outputs?#
This is the question to ask about any system that ingests user-supplied or third-party text, whether that’s a chatbot, an email gateway, or a content moderation pipeline. If your input is “raw text,” you need to define what that actually means at the byte level, not just what it looks like on a screen.
Concretely, this means:
Explicitly strip the Unicode tag block (U+E0000 to U+E007F) from any text before it reaches a model, filter, or storage layer. Don’t rely on general Unicode normalization to catch this. Write an explicit rule that recognizes and removes these code points, the same way you’d write a rule to strip null bytes or control characters from an untrusted input.
Strip other invisible or zero-width Unicode ranges too, including zero-width spaces, zero-width joiners, and bidirectional control characters. These have been used for similar smuggling purposes and deserve the same treatment.
Do this sanitization at the earliest possible point in the pipeline, before the text touches a model’s context window, a search index, or a filter’s pattern matcher. Garbage in, garbage out applies here in its most literal sense. If the hidden payload never makes it past the front door, it never has a chance to influence anything downstream.
Don’t wait for provider-side patches. Model providers and email platforms will eventually harden their own systems against known encodings, but new invisible ranges and encoding tricks will keep surfacing. Sanitization you control and can audit will outlast any single vendor’s current mitigation.
The Practical Takeaway#
Invisible text isn’t a clever new invention. It’s an old idea, hiding data where the eye can’t follow, applied to a new set of machines that happen to read every byte we hand them. The lesson isn’t specific to AI or to email. Any system that treats “what renders” and “what gets processed” as the same thing has a blind spot, and that blind spot doesn’t stay a secret once someone publishes how to find it. Build your sanitization around the bytes, not the picture.
Recommended Reading#
If you found this post useful, you might also be interested in:
- AI Engineering: Building Applications with Foundation Models
- Ace the Data Science Interview: 201 Real Interview Questions Asked By FAANG, Tech Startups, & Wall Street
- The Web Application Hacker’s Handbook: Finding and Exploiting Security Flaws
Featured image by LumenSoft Technologies on Unsplash

