Hidden Unicode Check · comparison

Hidden Unicode Check vs. reading the file by hand

A careful reviewer genuinely catches what renders visibly wrong. This page names no company or product — reading a file before trusting it is a habit most developers already have, not a competing tool.

What a careful read catches reliably

A typo, a stray visible character, an oddly-spaced word, an obviously garbled line — anything that actually changes what appears on screen is exactly what a careful reviewer is good at noticing. This tool does not replace that kind of reading.

What a careful read cannot catch, by construction

CaseReading by handThis tool
A zero-width space, joiner, or Hangul filler characterRenders as nothing — there is no glyph to see, whether or not the character is present in the fileFlags the exact codepoint, name, and byte offset regardless of whether it draws anything
A Unicode Tag character run (U+E0000–U+E007F)Attaches invisibly to ordinary-looking visible text; the sentence you read carries no visual sign a second message is riding along with itDecodes the hidden run back to the plaintext it spells out, not just a "something is here" flag
A bidi override (RLO/LRO and the embedding/isolate family)The whole mechanism is that the renderer displays a different order than the bytes are stored in — reading the screen shows you the renderer's choice, not the stored orderReports the control character itself and its position, independent of how any particular renderer chooses to display it
A variation selector used as a smuggling channelSelectors from the Variation Selectors Supplement block render as nothing extra on their own, attached silently to a visible anchor characterFlags each selector by codepoint and position, distinct from ordinary emoji-variation use

The gap that matters most: these characters are defined to be unreadable

This isn't a case of a reviewer missing something a careful enough read could have caught. A zero-width character is defined by the Unicode Standard to draw no glyph and occupy no width; a bidi override is defined to make the rendered order disagree with the stored order. Both behave exactly as specified whether or not anyone is reviewing the file — there is no reading strategy that makes an invisible character visible, because invisibility is the character's whole job. A mechanical scan over the raw codepoints, rather than the rendered screen, is not a more careful version of reading; it's a different question asked of a different layer of the file.

When to still read the file yourself

This tool only reports the exact codepoints on its list at the exact positions they occur. It is not a security audit, it does not understand what the surrounding visible text means, and it says nothing about a prompt-injection technique built entirely from ordinary, ASCII text. Judging whether a flagged character's context is actually malicious, and everything a scan of raw codepoints cannot see, is still a job for reading the file yourself.

Common questions

What does reading a file carefully actually catch?

A reviewer catches what renders visibly wrong: a typo, a stray character, an oddly-spaced word. Those are real defects and a careful read finds them the same way it always has. This tool does not replace that kind of reading -- it looks for a different, narrower class of problem.

Why can't a careful read catch a zero-width character?

Because it renders as nothing. A zero-width space, a zero-width joiner, a Hangul filler character -- every one of them is defined by the Unicode Standard to occupy no visible width and draw no glyph. There is no way to see one by looking at rendered text in a normal editor or diff view; the file simply looks like it has no character there at all, whether or not one is present in the underlying bytes.

Why is a Unicode Tag character worse than a zero-width one?

A run of Tag characters (U+E0000-U+E007F) doesn't just hide -- it spells out an entire hidden ASCII message, one Tag codepoint per hidden character, attached invisibly to whatever visible text sits next to it. A sentence that reads as an ordinary instruction to a human reviewer can carry a second, completely different instruction in Tag characters that only a program reading the raw codepoints ever sees -- which is exactly what an AI coding agent reading a pasted file does.

Why can't a careful read catch a bidi override?

Because a bidi override (RLO/LRO and the rest of the 2021 Trojan Source family) is a control character whose entire purpose is to tell the renderer to display stored characters in a different visual order than they are stored in. Reading the screen shows you the order the renderer chose to draw, not the order the bytes are actually stored in -- which is the whole mechanism, not a rendering bug.

Does a clean scan mean the file is safe?

No. This tool only reports the exact codepoints on its list at the exact positions they occur. A clean result means none of them were found in the text pasted in -- it is not a security audit, and it says nothing about a prompt-injection technique built entirely from ordinary, visible characters.

Scan a file