Great work!

XP to next level

BugEater

Invisible Characters

Some of the most insidious input bugs come from characters that do not occupy visible space on screen. They can be typed accidentally, injected by tools, or copied from sources that embed them invisibly. Standard validation code misses them. Users cannot detect them visually.

The Zero-Width Space (U+200B)

The zero-width space (ZWSP) has no visible width. It is used in CJK text to indicate line-break opportunities in languages that don't use spaces. It enters user input through:

  • Copy-paste from web pages (many CMS systems insert them)
  • Copy-paste from mobile devices (some keyboards insert them)
  • Programmatic injection in email campaigns and phishing pages

A username admin​ (with invisible ZWSP after n) appears identical to admin on screen but is a different string. The user who submitted it cannot log in later by typing admin manually. The stored value contains a character they cannot reproduce.

The bug is completely invisible to the user and to any human reviewer. It is only detectable by examining the raw bytes or by length comparison.

The Non-Breaking Space (U+00A0)

The non-breaking space looks identical to a regular space in most fonts and contexts. It is used to prevent line breaks between words. It enters input via:

  • The macOS keyboard shortcut Option+Space
  • Copy-paste from word processors (Microsoft Word uses non-breaking spaces between abbreviations)
  • Auto-correct on some mobile keyboards

Unlike regular space, U+00A0 is not removed by Java String.trim(). A username like admin where the final space is a non-breaking space will survive trim(). Every downstream check for trailing spaces will miss it.

Test by submitting a value where the trailing "space" is typed with Option+Space on macOS or via a raw request with the byte 0xC2 0xA0 (UTF-8 encoding of U+00A0).

The Ideographic Space (U+3000)

The ideographic space is the full-width space used in Chinese, Japanese, and Korean typography. It is visually about twice as wide as a regular space. Users from CJK locales may use it accidentally, especially on input methods that default to full-width mode.

Standard trim() does not remove U+3000. A CJK user who enters their username with an ideographic space instead of a regular space will not be able to log in later with a manually typed entry that uses a regular space.

The Byte-Order Mark (U+FEFF)

The UTF-8 BOM is the invisible character U+FEFF prepended to text files by some tools (historically, Notepad on Windows was famous for this). When users paste text from BOM-marked sources, the BOM character arrives as the first character of the input.

U+FEFF (ZERO WIDTH NO-BREAK SPACE, repurposed as BOM) has zero visible width. An input field that receives admin (BOM + admin) displays admin. The stored value is different from a typed admin. Every equality check fails.

Directional Override Characters

Unicode includes directional control characters that change text rendering direction:

  • U+202E: RIGHT-TO-LEFT OVERRIDE — forces following text to render right-to-left
  • U+200F: RIGHT-TO-LEFT MARK — suggests RTL context to bidirectional algorithm
  • U+200E: LEFT-TO-RIGHT MARK — suggests LTR context

These are invisible and can cause filenames and usernames to visually display content in an unexpected order. A filename that appears to say document.pdf might actually end with .exe that is rendered right-to-left using U+202E to appear as fdp.document. This is a security-relevant case.

How to Test for Invisible Characters

Because these cannot be detected visually, testing requires checking the actual stored or returned value by examining its length or raw bytes:

  1. Length test: If a 5-character word has length = 6, there is an invisible character.
  2. Roundtrip test: Submit a value; retrieve it; compare byte-by-byte. Any mismatch indicates a stored character that wasn't visible on submission.
  3. Raw HTTP test: Submit a request with a known-invisible character embedded. Check the API response for the stored value. Decode the response bytes and look for unexpected characters.
  4. Copy-paste from a document: If a document-sourced username fails authentication when retyped manually, invisible characters in the pasted value are the likely cause.

The absence of visible difference is the defining challenge. These bugs are found through systematic raw input testing, not through looking at the screen.

Quiz

A user copies a name from a PDF and pastes it into a search field, but no results appear even though the name exists. What is the most likely cause?

Which Unicode character is most commonly responsible for invisible-character bugs from word processors and PDFs?

A password is set by pasting secr​et from a chat message containing a zero-width space (U+200B). The user then types secret manually at login. What happens?

What is the most reliable way to test whether a system correctly handles invisible characters in user input?