Some Unicode characters take up no visible space at all. Zero-width spaces, zero-width joiners, and the invisible characters in the Unicode Tags block render as nothing on screen, yet they are still real characters in the underlying text. Steganography is the practice of hiding a message inside something that looks ordinary, and with these characters an attacker can hide instructions in plain sight, invisible to a human reader but still readable by a language model.
What zero-width characters are
Zero-width characters were added to Unicode for legitimate typography: joining or separating letters in scripts like Arabic and for controlling how text wraps. Because they have no visible glyph, a string can contain many of them between ordinary letters and still look completely normal. Copy that string, paste it into a plain text box, and the hidden characters travel with it.
How the attack works against LLMs
An attacker writes a harmful instruction, converts it into a sequence of invisible characters, and embeds it inside a harmless looking message, a web page, or a document. A person reviewing the content sees nothing unusual. When a language model processes the text, it may still read the hidden characters and act on the concealed instruction. This is especially dangerous for indirect prompt injection, where the model ingests external content such as a retrieved document or a web page that a person never inspects character by character.
In Reveal Trace you can encode a phrase into invisible characters and then decode it back, which makes the hidden payload visible and shows exactly how much text can hide inside what looks like an empty space. These methods live in the hidden and invisible category of the prompt injection cheat sheet.
Why it is hard to catch
The whole point of the technique is that a human sees nothing. Standard review, screenshots, and even careful reading all fail, because the payload has no visible form. A filter that only checks visible text will pass the message, and the length of the visible text gives no hint that hundreds of hidden characters are attached.
How to detect and defend
Detection is actually straightforward once you look for it. Strip or flag characters that carry no visible meaning: zero-width spaces and joiners, the Unicode Tags block, and other invisible control characters. Any text destined for a model should be run through a normalization step that removes these unless there is a clear reason to keep them, such as genuine Arabic or Indic typography. Measuring the gap between the visible length and the true character count is another cheap, reliable signal.
See it in action
Hide and reveal text with the invisible character methods in Reveal Trace, then try a hidden text injection against a real model in the labs. The cheat sheet lists the full set of concealment techniques alongside the encodings and ciphers attackers combine them with.