AI security · invisible Unicode

Invisible prompt injection and zero-width steganography

Invisible Unicode characters can hide text from the person reading a prompt, a web page, or a document while a language model still receives it. This page explains which characters matter, why they work differently from each other, and how to check text before an LLM reads it.

Check text for hidden characters

What is invisible prompt injection?

Prompt injection is text that tries to override the instructions an LLM application was given. It is most dangerous when it arrives indirectly: in a web page an assistant browses, an email it summarizes, a file it is asked to review, or a pasted snippet from someone else.

The invisible variant uses Unicode characters that most interfaces render as nothing. A reviewer sees an ordinary sentence. The model receives the sentence plus a payload the reviewer never saw. The attack does not need the characters to be secret from software — only from the human who would otherwise notice the instruction.

Which invisible characters matter, and why

Not all invisible Unicode carries the same risk. What matters is whether the model can read the hidden content as language without being asked to decode it.

TechniqueCharactersHow a model sees itRelative risk
Unicode Tag “ASCII smuggling”U+E0020–U+E007EEach tag mirrors one printable ASCII character. Some tokenizers and models treat a tag run as the text it mirrors.High — readable instructions with no decoding step
Variation-selector byte smugglingU+FE00–U+FE0F, U+E0100–U+E01EFBytes attached to an emoji or letter. The model sees opaque selectors; reading them needs an explicit decoding convention.Medium — mainly a hiding channel, sometimes paired with a visible “decode this” instruction
Zero-width binary encodingU+200B, U+200C, U+200D, U+2060, U+FEFFA string of invisible tokens representing bits. A model does not reliably turn these back into text on its own.Lower as hidden instructions
Zero-width word splittingSame zero-width characters, placed inside wordsBreaks a word into different tokens, so keyword filters and classifiers can miss a phrase the model still understands.Medium — evades filters rather than hiding the instruction
Bidirectional controlsU+202A–U+202E, U+2066–U+2069Reorders how text is displayed, so what a reviewer reads differs from what the model receives.Medium — see Trojan Source

Why Unicode Tags are the main concern

The Tags block was designed for invisible language labels and is now used almost only inside emoji flag sequences such as the flags of England, Scotland, and Wales. Because tag characters line up one-to-one with ASCII, an entire sentence can be written in them, copied into a chat box, and survive untouched. In January 2024 Riley Goodside showed that ChatGPT would follow instructions written this way, and Johann Rehberger named the technique and published a tool for crafting and decoding “ASCII smuggling” payloads. Many vendors now filter tags, but filtering is not universal across models, wrappers, and retrieval pipelines.

Why zero-width bit encodings are weaker as injections

Zero-width steganography encodes a message as a sequence of bits. To act on it, a model would have to recognize the pattern, map each character to a bit, group the bits into bytes, and decode the bytes — all without being asked. Rehberger's “Sneaky Bits” experiments, which write ASCII as binary using invisible-times and invisible-plus characters, gave the model the decoding scheme in the prompt and still reported mixed results without code-execution tools. Without such a visible instruction, a zero-width payload usually reaches the model as noise. That gap may narrow as models improve, which is another reason to strip these characters at the boundary. Zero-width characters still matter for security in two ways: they can split words to slip past keyword filters, and they can carry data out of a system, for example as a hidden marker in model output.

Where hidden text enters an LLM application

  • Copied prompts. “Prompt packs”, shared jailbreak lists, and snippets from forums can carry characters the person pasting them never saw.
  • Retrieved content. Web pages, search results, and documents pulled in by retrieval or browsing tools are untrusted input.
  • User-submitted files. Résumés, support tickets, reviews, and code submissions that an assistant is asked to summarize or score.
  • Tool and agent output. Text returned from another tool or agent before it is fed into the next model call.

How to detect and defend against invisible prompt injection

  • Inspect before you trust. Paste suspicious text into the Invisible Unicode Character Detector. It lists each invisible character with its position, reconstructs printable Unicode Tag runs and a common variation-selector byte convention as “Possible decoded payload”, and runs entirely in your browser.
  • Strip Tag characters at the boundary. Outside recognized emoji flag sequences, U+E0000–U+E007F has almost no legitimate use in model input. Remove or reject it before text reaches the model.
  • Normalize other invisible characters with care. ZWJ, ZWNJ, and variation selectors are required for emoji and for many writing systems. Removing them everywhere damages text; flag them for review or remove them only in contexts that do not need them.
  • Show what the model sees. Logs, review queues, and moderation tools should display invisible characters as visible markers so a human reviewer can see the payload.
  • Treat retrieved content as data. Clean input reduces risk but does not prevent visible prompt injection. Limit what an agent's tools can do, and require confirmation before actions that send, delete, or pay.

The StegZero command-line tool offers the same inspection and cleaning for scripts and pipelines — see the CLI documentation.

Is StegZero a prompt injection tool?

No. StegZero is a text steganography and watermarking tool for people: it hides a message or watermark ID that someone later reveals with StegZero. It is not designed or effective as a way to hide instructions from a model.

It does not emit Unicode Tag characters. The encoder only uses zero-width and invisible-operator characters (U+200B, U+200C, U+200D, U+2060, U+2062–U+2064, U+FEFF), never the ASCII-mirroring tag range behind ASCII smuggling.

Its payloads are not readable text. Every message is wrapped in a binary frame with a header and checksum, and the message bits are scrambled with a per-message seed before they are hidden. With a passphrase, the message is also encrypted with AES-256-GCM. Unlike the Sneaky Bits scheme, where each character is one bit of a plain ASCII letter, decoding StegZero's bits gives scrambled bytes, not plain-language instructions.

It makes hidden text easier to find, not harder. The same project ships the Unicode detector and a cleaner, and the Reveal tab flags any StegZero frame automatically.

It is open source and local. The source code is public, and encoding and decoding run in your browser, so anyone can check what it produces.

No text format can stop every misuse: someone could paste any text into a chatbot along with a request to decode it. That would be a visible instruction, though, and the kind of input the defenses above are built to catch.

Frequently asked questions

Can zero-width characters be used for prompt injection?

Sometimes, but they are not the main risk. They are mostly used to split words so filters miss them, or to carry a binary message that a model would have to be told to decode. Unicode Tag characters are the bigger concern.

What is ASCII smuggling?

Writing readable instructions in Unicode Tag characters (U+E0020–U+E007E). Each tag mirrors a printable ASCII character, renders as nothing in most interfaces, and can be read as text by models whose tokenizers keep tags.

Does removing invisible characters stop prompt injection?

It stops the invisible kind. Ordinary, visible prompt injection in retrieved content still needs application-level defenses such as limited tool permissions and human confirmation.

Does finding invisible characters mean text was written by AI?

No. Invisible characters come from keyboards, word processors, emoji, multilingual text, and copy-paste between apps. Their presence does not prove AI authorship, and removing them does not remove statistical model watermarks.