Global site search

Search guides, labs, glossary, and research

Type two or more characters to search.

Established mechanism

The Invisible Attack Surface: Zero-Width and Bidirectional Unicode

A survey of invisible Unicode, bidirectional controls, renderer/parser discrepancies, security risks, and laboratory-safe inspection examples.

Representation ≈ 26 min read 44.0 KB source Download raw Markdown

This local reader uses a conservative, dependency-free Markdown renderer. Citation markers from the original report are preserved as source pills; equations and Mermaid diagrams remain text. Use the raw Markdown for exact source fidelity.

Introduction to the Semantic Gap in Text Encoding

The foundational premise of modern software engineering and digital communication relies heavily on the principle of "what you see is what you get" (WYSIWYG). Human operators, software developers, code reviewers, and data analysts operate under the assumption that the visual rendering of text on a display accurately represents the logical sequence of bytes stored in memory. This assumption governs how we write code, process natural language, index web documents, and interact with artificial intelligence. However, the complexity of modern text encoding standards has introduced a profound vulnerability into this paradigm, creating a severe semantic gap between visual perception and logical execution. Unicode, the ubiquitous encoding standard designed to unify the digital representation of the world's diverse writing systems, contains over 150,000 distinct characters. While the vast majority of these characters map to visible glyphs (such as Latin letters, Kanji, or mathematical symbols), the standard also includes dozens of control characters designed specifically not to display anything. Instead, these invisible characters serve as metadata, instructing text rendering engines on how adjacent characters should be formatted, spaced, joined, or directionally ordered1. Because these characters are visually imperceptible or highly contextual, they enable a complex attack surface. A single byte stream containing zero-width or bidirectional characters will be interpreted in radically different ways depending on whether the consumer is a web browser's visual rendering engine, a compiler's lexical analyzer, a search engine's inverted index, or a Large Language Model's (LLM) tokenizer3. This divergence allows malicious actors to craft payloads that appear entirely benign to human reviewers but execute devastating logic within downstream computing systems. This analysis provides an exhaustive examination of the mechanisms, legitimate applications, and severe security implications of invisible and unusual Unicode characters. By exploring phenomena such as "Trojan Source" code injections, imperceptible adversarial attacks on Natural Language Processing (NLP) models, manipulation of Applicant Tracking Systems (ATS), and sophisticated prompt injections in agentic artificial intelligence architectures, this report defines the contours of an invisible threat landscape and outlines the structural defenses required to mitigate it.

The Taxonomy and Legitimate Architecture of Invisible Unicode

To comprehend the vulnerabilities associated with invisible characters, it is first necessary to classify them by their intended, legitimate functions within the Unicode standard. These characters were not designed maliciously; rather, they were introduced to solve genuine typographical, linguistic, and rendering challenges in a globally connected digital environment. The characters central to this analysis fall into three primary categories: typographical and formatting controls, bidirectional (Bidi) text controls, and deprecated special-purpose tags.

Typographical and Formatting Controls

The most commonly encountered invisible characters govern word boundaries, hyphenation, and line breaks. In languages that do not use spaces to separate words (such as Thai, Myanmar, or Khmer), rendering engines require explicit hints to determine permissible line-break opportunities without introducing arbitrary visible spaces. Furthermore, modern digital typography often requires absolute control over ligature formation. Arabic and Indic scripts, for instance, rely heavily on the contextual joining of characters. The Unicode standard provides specific zero-width controls to override default joining behaviors, which are heavily utilized today in rendering complex emojis5.

NameCode PointCategoryLegitimate Typographical Function
Zero-Width Space (ZWSP)U+200BFormat (Cf)Indicates a potential line-break opportunity without introducing visible space. Frequently used in long URLs or unspaced languages6.
Zero-Width Non-Joiner (ZWNJ)U+200CFormat (Cf)Prevents two adjacent characters from connecting into a ligature, forcing them to render in their isolated or final forms (essential for Persian and Arabic)7.
Zero-Width Joiner (ZWJ)U+200DFormat (Cf)Requests that two adjacent characters be joined into a ligature. In modern contexts, it combines multiple emojis (e.g., a person, a ZWJ, and a profession) into a single glyph5.
Word Joiner (WJ)U+2060Format (Cf)Binds two characters together to strictly prohibit a line break between them, functioning similarly to a zero-width non-breaking space6.
Non-Breaking Space (NBSP)U+00A0Separator (Zs)Renders as a visible blank space but prevents automatic line breaks at its position7.
Narrow Non-Breaking Space (NNBSP)U+202FSeparator (Zs)Similar to the NBSP but occupies less horizontal width, often used for punctuation spacing in French typography7.
Byte Order Mark (BOM)U+FEFFFormat (Cf)Originally used to signal the endianness of a text file, it is also utilized as a zero-width no-break space in older text processing contexts6.
Soft HyphenU+00ADFormat (Cf)Remains invisible unless a word needs to break at the end of a line, at which point it renders a visible hyphen7.

Bidirectional (Bidi) Control Characters

The Unicode standard is uniquely challenged by the necessity to accommodate left-to-right (LTR) scripts, such as English and Russian, alongside right-to-left (RTL) scripts, such as Arabic and Hebrew, often within the same sentence or paragraph2. To manage this, text rendering engines rely on the Unicode Bidirectional Algorithm (UAX \#9). This algorithm dynamically resolves the display order of mixed-direction text based on the inherent directional properties of the characters. However, when the default algorithm cannot accurately deduce the intended display order (for example, when a Hebrew sentence contains an English product name that itself contains numbers), Bidi control characters are injected to manually override or isolate specific text segments2.

AbbreviationCode PointUnicode NameRendering Function
LREU+202ALeft-to-Right EmbeddingTreats the subsequent text segment as LTR, preserving nested directional contexts2.
RLEU+202BRight-to-Left EmbeddingTreats the subsequent text segment as RTL, preserving nested directional contexts2.
LROU+202DLeft-to-Right OverrideForces the subsequent text to render strictly LTR, overriding the inherent directionality of the characters2.
RLOU+202ERight-to-Left OverrideForces the subsequent text to render strictly RTL, overriding the inherent directionality of the characters2.
LRIU+2066Left-to-Right IsolateForces LTR rendering without affecting the directional flow of the surrounding, adjacent text2.
RLIU+2067Right-to-Left IsolateForces RTL rendering without affecting the directional flow of the surrounding, adjacent text2.
PDFU+202CPop Directional FormattingTerminates the most recent LRE, RLE, LRO, or RLO block, returning rendering to the prior state3.
PDIU+2069Pop Directional IsolateTerminates the most recent LRI, RLI, or FSI block7.

Deprecated and Special Purpose Tags

The Unicode standard also reserves a block of Tag characters (U+E0001 through U+E007F). Originally designed for language tagging, these characters were intended to indicate that a specific text segment was in a particular language without relying on out-of-band markup languages like HTML or XML. For example, the Tag Latin Capital Letter R (U+E0052) could be used as part of a hidden sequence7. While these tags were officially deprecated in Unicode 5.0 due to the preference for markup-level language declarations, they remain permanently etched into the standard for the sake of backward compatibility. Consequently, they are fully parseable by modern text engines and LLM tokenizers, persisting as an invisible, highly structured data channel completely hidden from human view9.

Architectural Discrepancies in System Interpretation

The security threat posed by these characters arises entirely from the architectural discrepancies in how different software layers process text. A single logical byte stream containing zero-width or Bidi characters will be interpreted in fundamentally divergent ways depending on the specific parser's objective. Browsers prioritize visual flow, compilers prioritize strict lexical tokenization, search engines prioritize semantic normalization, and neural networks prioritize high-dimensional vector mappings.

Browsers, Code Editors, and Visual Rendering Engines

Web browsers and integrated development environments (IDEs) are fundamentally designed to prioritize user experience and visual legibility. When a browser's rendering engine (such as Blink in Chrome or WebKit in Safari) encounters formatting controls like a ZWSP, it processes the instruction—such as allowing a line break if the container width is exceeded—but draws no pixels on the screen6. When encountering Bidi control characters, the rendering engine applies the UAX \#9 algorithm to physically rearrange the sequence of glyphs drawn on the screen. For instance, if the logical byte sequence in memory is a b c \[RLO\] d e f, the rendering engine will output the visual string a b c f e d. The human reviewer perceives a cohesive string, entirely unaware that the underlying bytes are stored in a disparate sequential order2. Prior to the discovery of targeted vulnerabilities, most source code editors (including early versions of Visual Studio Code, Atom, and Sublime Text) blindly trusted Bidi overrides within source code files. They prioritized correct linguistic display over strict byte-order representation, creating an environment where a developer could review code that visually appeared mathematically sound, but was structurally malicious on disk2.

Compilers, Interpreters, and Source Code Parsers

Compilers (such as GCC, Clang, and Rustc) and interpreters (such as CPython, Node.js, and the Java Virtual Machine) behave entirely differently from visual rendering engines. During the lexical analysis phase, a compiler scans the raw source code byte-by-byte to generate operational tokens. Compilers do not run the Unicode Bidirectional Algorithm; they do not rearrange text for visual consistency. They strictly parse the logical order of the characters as they exist in memory8. If a compiler encounters a Bidi control character inside a string literal or a multiline comment, it typically treats it as valid text data or ignores it entirely, as these spaces are meant to hold arbitrary human language data. However, this dichotomy—where the compiler reads logical bytes sequentially while the editor renders modified visual glyphs non-sequentially—is the precise mechanism underlying the "Trojan Source" vulnerability class1. Furthermore, language-specific parsing rules create unique vulnerabilities. For example, the Ruby programming language embraced UTF-8 for source code, allowing identifiers (variables, method names) to use non-ASCII characters. This creates an attack vector where invisible bidirectional characters can be embedded directly into Ruby identifiers, allowing malicious methods to masquerade as safe ones3. The compiler processes the identifier complete with its invisible payload, while the human developer sees only the visible characters3.

Search Engines, LSI, and Document Indexing

Search engines and enterprise document indexing systems (such as Googlebot, ElasticSearch, and Latent Semantic Indexing architectures) attempt to normalize text to match user queries with relevant document content. In a traditional Information Retrieval (IR) model, an inverted index maps individual tokens to document IDs11. When an invisible character like U+200B is inserted into a word, it fatally disrupts this mapping. If a database contains the string market\[ZWSP\]ing, a traditional lexical scanner views this not as a 9-character English word, but as a 12-byte sequence (in UTF-8) containing an unrecognized format symbol in its center. Consequently, the search engine indexes the corrupted token6. If a user queries the exact word "marketing", the inverted index fails to find a match. Advanced search algorithms attempt to mitigate this by utilizing Latent Semantic Indexing (LSI) and Vector Indices11. LSI operates by constructing a massive matrix of document-term frequencies, stripping out stop words, and then decomposing this matrix using Singular Value Decomposition (SVD) to collapse the data into a smaller set of dimensions12. This dense vector map allows the search engine to understand intent rather than just syntax11. However, the deliberate injection of dozens of invisible characters can completely alter the tokenization phase before the vector embedding is even calculated, rendering the text mathematically invisible to the search engine. Empirical research has demonstrated that major search engines fail to index documents heavily saturated with invisible characters; queries containing zero-width joiners return zero results, proving that even advanced vector indices fail to normalize and index these hidden artifacts effectively13. This vulnerability extends to modern AI Overviews and generative synthesis engines, where citation frequency and "Information Gain" metrics can be manipulated by cloaking specific entities from the retrieval bots11.

PDF Extractors and JSON Interoperability

The interpretation gap also extends to data serialization formats and document parsers. When text is extracted from PDF documents, different parsers handle invisible characters inconsistently. For instance, extracting text via the Chrome PDF viewer may yield clean strings, while extracting the exact same document via an alternative viewer (like SumatraPDF) may introduce non-breaking spaces or zero-width artifacts into the clipboard payload14. When this corrupted text is fed into downstream data structures, such as JSON payloads for API communication, it creates severe interoperability vulnerabilities. If a JSON parser performs naive character truncation or fails to properly escape unpaired Unicode surrogates, it can lead to fatal parse errors or logic bypasses. Malicious actors can exploit these parser discrepancies by feeding JSON payloads containing keys with zero-width characters, causing backend systems to interpret duplicate keys differently, bypassing validation checks while successfully executing the malicious payload15.

Large Language Models and Neural Tokenization

Large Language Models operate on tokens, which are integer IDs mapped to specific sub-word units generated by algorithms like Byte Pair Encoding (BPE) or Unigram language models4. Tokenizers such as OpenAI's tiktoken or Google's SentencePiece serve as the crucial preprocessing layer between raw, unstructured text and the neural network4. Unlike human readers or visual rendering engines, LLM tokenizers do not ignore invisible Unicode characters. SentencePiece, heavily used in open-source models like Llama, treats the input text as a raw stream of Unicode characters, preserving every code point. It even explicitly escapes normal whitespace with a meta-symbol ▁ (U+2581) to ensure that detokenization is a lossless string join operation, entirely independent of language specifics17. If an invisible character like a zero-width space is frequent enough in the tokenizer's training corpus, it may be assigned its own dedicated token ID. If it is rare, the tokenizer will utilize a byte-fallback mechanism, breaking U+200B down into its three constituent UTF-8 bytes (E2 80 8B) and passing those raw byte IDs to the model18. Because LLMs analyze mathematical relationships in high-dimensional vector space based on these explicit token IDs, the neural network "sees" the invisible characters with perfect clarity. To a human reviewer, an adversarial prompt looks like normal English. To the LLM, the prompt contains a highly structured, mathematically distinct pattern of token IDs instructing it to behave differently4.

Security Risks: The Invisible Attack Vectors

The discrepancy in how systems interpret Unicode has spawned multiple novel attack paradigms across different domains of computer science. These attacks exploit human blind spots, effectively bypassing manual code reviews, content filters, and strict prompt guardrails.

1\. Trojan Source: Exploiting Compilers (CVE-2021-42574)

In late 2021, Cambridge University researchers Nicholas Boucher and Ross Anderson disclosed a critical class of vulnerabilities dubbed "Trojan Source." This exploit leverages Bidi control characters to reorder source code tokens at the encoding level. By embedding LTR and RTL overrides inside string literals and comments, an attacker can trick the code editor into rendering completely different logic than what the compiler executes1. The attack was proven highly effective across virtually all modern programming languages that permit Unicode in strings and comments. Proof-of-concept repositories demonstrated vulnerabilities in C, C++, C\#, Java, JavaScript, Rust, Go, Python, SQL, Bash, Assembly, and Solidity20.

The Mechanism of Commenting-Out Attacks

Consider a scenario where an attacker wishes to bypass a critical authentication check. The attacker can place Bidi characters such that a human code reviewer sees a legitimate security check, but the compiler interprets the check as being "commented out." Logical Byte Sequence (What the Compiler Executes):

C /\ if (isAdmin) { begin admins only \/ printf("You are an admin.\\n"); /\ end admins only \[RLO\] { \[LRI\] \/

In this sequence, the C compiler reads a standard multi-line comment ending on the first line. It then reads the printf statement as executable code. Finally, it reads a second multi-line comment on the third line, ignoring the Bidi control characters \[RLO\] and \[LRI\] entirely as they are safely inside the comment block. Visual Rendering (What the Human Reviewer Sees): Due to the \[RLO\] (Right-to-Left Override) placed inside the second comment, the rendering engine reverses the display of the subsequent characters, pulling the closing bracket } to the left and reversing the comment tags. The human reviewer sees:

C /\ if (isAdmin) { begin admins only \/ printf("You are an admin.\\n"); /\ end admins only } if (isAdmin) \/

To the human eye, it appears that the printf statement is safely guarded by an if (isAdmin) condition. In reality, the compiler treats the condition as part of the comment and executes the printf unconditionally, granting unauthorized access21.

Early Return and Homoglyph Attacks (CVE-2021-42694)

Another severe variation is the "Early Return" attack, particularly devastating in Python. An attacker can insert an \[RLI\] (Right-to-Left Isolate) inside a triple-quoted docstring, followed by a carriage return and a return statement. The editor visually renders the string normally, hiding the return statement within the visual flow of the comment. The Python interpreter, however, executes the return prematurely, halting the execution of critical downstream logic2. The researchers also documented "Homoglyph Attacks" (CVE-2021-42694). The Unicode standard includes characters from disparate alphabets that look visually identical—for example, the Latin 'a', the Cyrillic 'а', and the Greek 'α'. Attackers can define malicious variables or functions using Cyrillic homoglyphs that shadow legitimate Latin-based functions. A human reviewer sees what appears to be a call to a standard hashPassword function, but the compiler executes a malicious hаshPassword (utilizing a Cyrillic 'а') that exfiltrates the data1. The implications for the software supply chain are catastrophic. If a malicious actor submits a pull request containing a Trojan Source attack to a widely used open-source repository, human maintainers will likely approve it because the code appears benign. Downstream applications incorporating the poisoned library will unknowingly inherit the hidden vulnerability, creating a massive supply chain contagion8.

2\. Imperceptible NLP Attacks ("Bad Characters")

The divergence in Unicode processing is equally lethal to Natural Language Processing (NLP) models. A secondary study by Boucher, Shumailov, Anderson, and Papernot demonstrated that imperceptible encoding injections can be used to execute black-box adversarial attacks on NLP systems13. Historically, adversarial attacks on text-based models involved swapping synonyms, introducing deliberate typos, or paraphrasing sentences. While effective at confusing the AI, these perturbations were highly visible and easily flagged by human moderators. The "Bad Characters" attack methodology introduces zero-width characters, homoglyphs, and Bidi reorderings that make zero visual modifications to the input text13. By injecting just one or two invisible characters into an input string, attackers can fundamentally disrupt the tokenization pipeline. When evaluated against commercial machine-translation pipelines and toxicity detectors produced by Google, Microsoft, Facebook, and IBM, these imperceptible attacks successfully degraded classifier performance to near zero13. A toxic comment that would normally be blocked by an automated content filter can bypass the system entirely by embedding a single ZWSP in a banned keyword, while still displaying the toxic message perfectly to human readers25.

RAG-Pull Attacks and Model Alignment

This vulnerability extends to modern Retrieval-Augmented Generation (RAG) architectures. In a RAG setup, an LLM retrieves external data to ground its responses. Attackers can execute "RAG-Pull" attacks by inserting hidden UTF characters into external code repositories or web documents. When the AI retrieves this poisoned text, the invisible characters redirect the LLM's attention, shifting retrieval toward attacker-controlled snippets and breaking the model's safety alignment without the system administrator noticing any visual anomalies in the source data26.

3\. Reverse CAPTCHA: Invisible Prompt Injection in Agentic LLMs

As LLMs evolved from passive chatbots to autonomous agents equipped with tool-use (such as code execution, web browsing, and file system access), the threat of invisible Unicode evolved into a severe prompt-injection vector. A 2026 evaluation framework termed "Reverse CAPTCHA" explicitly targets the capability gap between human vision and machine tokenization9. While a traditional CAPTCHA verifies human perception over machine vision, a Reverse CAPTCHA proves that an AI can perceive complex instructions that are physically invisible to a human. Attackers can embed hidden instructions in web pages, PDFs, or copy-pasted text using specialized encodings. Encoding Schemes Used in Reverse CAPTCHA:

1. Zero-Width Binary (ZW): Attackers convert an ASCII instruction into an 8-bit binary string. The binary is then encoded using U+200B (Zero-Width Space) for a 0 and U+200C (Zero-Width Non-Joiner) for a 1\. A short 12-character payload like "Reply VIOLET" generates 96 completely invisible characters inserted seamlessly between normal words9. 2. Unicode Tags: Attackers map standard ASCII characters to the deprecated Unicode Tag block (U+E0000 \+ codepoint). The letter 'R' (U+0052) becomes the invisible tag U+E0052, allowing dense instruction payloads with only one invisible character per ASCII letter9.

The empirical data from the 2026 evaluation—spanning 8,308 graded LLM outputs across models like GPT-5.2, GPT-4o-mini, and Claude Opus/Sonnet/Haiku—yielded startling insights into the mechanics of agentic compliance10.

ModelCompliance (Tools OFF)Compliance (Tools ON)Effect Size (Odds Ratio)
Claude Haiku0.8%49.2%OR \= 115.1 (Cohen's h \= 1.37)10
Claude Opus6.7%51.1%OR \= 14.6 (Cohen's h \= 1.07)10
Claude Sonnet16.9%71.2%OR \= 12.1 (Cohen's h \= 1.16)10

The data reveals that tool access is the dominant amplifier of the vulnerability. Without tool access, the models generally ignored the hidden noise, treating it as tokenization artifacts. However, when tool access (specifically Python code execution) was enabled, the LLMs recognized the anomalous Unicode, autonomously wrote Python scripts to decode the hidden payloads, and executed the injected instructions. The task transformed from pattern recognition to programmatic string manipulation10. Furthermore, the vulnerability was highly provider-specific, indicating differences in tokenizer training data and BPE vocabularies.

Model ProviderZero-Width Binary ComplianceUnicode Tags Compliance
OpenAI (GPT-5.2)70%1%10
Anthropic (Claude Opus)48%100%10
Anthropic (Claude Sonnet)98%100%10

OpenAI models preferentially tokenized and decoded zero-width binary, completely failing to process Unicode tags. Conversely, Anthropic's Claude models achieved 100% compliance decoding Unicode tags but struggled slightly with zero-width binary9. If an autonomous AI agent scrapes a compromised web page or processes an attacker-controlled document containing these invisible instructions, the agent can be coerced into exfiltrating API keys, sending unauthorized network requests, or altering file systems—all while the human reviewing the input document sees only benign text28.

4\. Applicant Tracking Systems (ATS) and Keyword Stuffing

A less destructive but highly prevalent abuse of invisible Unicode occurs in the recruitment industry. Applicant Tracking Systems (ATS) automatically parse resumes to evaluate and rank candidates based on keyword matching. Job applicants, or malicious actors attempting to poison an ATS database, utilize zero-width spaces or visually camouflaged text to stuff keywords into a document invisibly30. For example, a candidate lacking experience in a mandatory skill could embed the word P\[ZWSP\]y\[ZWSP\]t\[ZWSP\]h\[ZWSP\]o\[ZWSP\]n to evade human detection, or place invisible control characters next to highly weighted industry terms to manipulate term frequency algorithms. When a human recruiter views the PDF or Word document, the resume appears clean and concise, showing no evidence of keyword stuffing. However, when the ATS parses the raw text stream, it detects the required keywords, granting the applicant an artificially high relevance score30. This phenomenon also functions as an indirect prompt injection against AI-based resume evaluators. By leveraging delimiter confusion and context manipulation, attackers can embed malicious instructions within the invisible text of a resume, overriding the screening model's instructions and effectively "jailbreaking" the hiring process31.

Detection, Mitigation, and Defensive Strategies

The decentralized nature of text rendering, compiling, and tokenizing makes universally patching invisible Unicode vulnerabilities exceptionally difficult. A comprehensive, defense-in-depth strategy requires mitigation at the compiler level, the text editor level, and the input sanitization layer.

Compiler and Toolchain Hardening

The definitive solution to the Trojan Source vulnerability requires compilers to proactively reject or warn against unpaired or anomalous Bidi control characters. Following the coordinated vulnerability disclosure in 2021, many compiler maintainers implemented strict lexical checks2. GCC 12 introduced the \-Wbidi-chars diagnostic flag. When enabled, the compiler performs a check during tokenization. If it detects unterminated Bidi contexts—such as an \[RLO\] that is not closed by a \[PDF\] before the end of a comment or string literal—it throws a compilation warning. Crucially, GCC 12 explicitly escapes the non-ASCII characters in its error output (e.g., printing \\U0000202E instead of rendering the character) to prevent the developer's terminal from applying the Bidi algorithm and displaying deceptive text22. The Rust compiler (rustc) took a more aggressive approach, throwing hard errors for unterminated Bidi control characters by default and actively preventing the compilation of vulnerable packages2. To address the broader supply chain threat, researchers proposed the Automated Bill of Materials (ABOM), an extension that embeds the cryptographic hashes of every source code file directly into the emitted binary, allowing downstream consumers to verify that the compiled logic matches the expected source32.

Code Editor Visualizations and Linters

Because human review remains a critical component of software engineering, code editors must expose deceptive encoding. Modern IDEs have been updated to visualize control characters that were previously hidden. Visual Studio Code (v1.61+) now renders bidirectional control characters as distinct, visible blocks by default, alerting the developer to their presence immediately2. At the repository level, version control platforms like GitHub and BitBucket implemented server-side syntax checks. When a pull request contains Bidi characters, the repository frontend triggers a dialog box warning the reviewer of potential Trojan Source injections2. In the JavaScript ecosystem, specialized tools like the eslint-plugin-anti-trojan-source actively scan Node.js and TypeScript projects for malicious bidi Unicode attacks during the continuous integration pipeline34.

The Failure of Standard Normalization and the Need for Sanitization

For NLP pipelines, LLM agents, and search engine indices, the primary defense is rigorous input sanitization. However, traditional Unicode normalization is mathematically insufficient to cleanse text of these threats. Unicode equivalence algorithms (NFC, NFD, NFKC, NFKD) are designed to standardize characters with multiple valid representations (e.g., converting an 'e' followed by a combining acute accent into a single 'é' character). While the compatibility normalizations (NFKC and NFKD) will successfully convert certain characters—such as normalizing a Non-Breaking Space (U+00A0) into a standard Space (U+0020)—they explicitly preserve Zero-Width Spaces, Zero-Width Non-Joiners, Bidi control characters, and Unicode Tags5. The Unicode standard dictates that these characters hold distinct semantic meaning in complex scripts, and therefore cannot be destructively normalized. To defend against Reverse CAPTCHA and Imperceptible NLP attacks, systems must implement aggressive boundary-level stripping. Security protocols must explicitly strip characters in the U+200B to U+200F range, the U+2060 to U+2064 range, and the entirely deprecated U+E0000 to U+E007F (Tags) range before feeding text to an LLM tokenizer or search index5. However, extreme caution must be exercised: blindly stripping the Zero-Width Joiner (U+200D) will break the rendering of complex emojis and legitimate Indic/Arabic script ligatures, leading to data corruption. For LLM agents with tool access, sanitization must be paired with execution-layer isolation. Agentic architectures must implement "PreToolUse" hooks to validate parameters before execution. If an LLM is tricked by invisible Unicode into calling a bash command to exfiltrate a file, the platform's execution layer must enforce strict Role-Based Access Control (RBAC), verifying the tool call against an allowed list of operations independent of the LLM's prompt state29.

Safe Laboratory Examples and Analysis

To safely observe and analyze the behavior of invisible Unicode characters without executing weaponized payloads, security researchers can utilize basic Python scripting to inspect the byte streams, analyze UTF-8 encodings, and test normalization behavior.

Example 1: Hexadecimal Analysis of UTF-8 Encodings

The following Python laboratory example demonstrates how invisible characters are represented in memory. It maps the integer code point to the character, extracts the official Unicode name, determines the Unicode category (e.g., Cf for Format characters), and outputs the raw UTF-8 hexadecimal bytes7.

Python import unicodedata

chars \= \[ 0x200B, \# ZWSP 0x202E, \# RLO 0x2069, \# PDI 0xE0052 \# Tag Letter R \]

for cp in chars: c \= chr(cp) name \= unicodedata.name(c, "UNKNOWN") category \= unicodedata.category(c) utf8 \= " ".join(f"{b:02X}" for b in c.encode('utf-8')) print(f"U+{cp:04X} | {name} | Category: {category} | UTF-8: {utf8}")

Analysis of Execution: When executed, this script reveals the precise byte sequences that tokenizers and compilers must process:

  • U+200B (ZWSP) maps to E2 80 8B. When an LLM tokenizer parses this, it either maps the full byte sequence to a unique token or splits it into three byte-level tokens depending on its BPE vocabulary limits.
  • U+202E (RLO) maps to E2 80 AE. A compiler reads these three bytes and ignores them; a browser reads them and completely flips the visual rendering direction.
  • U+E0052 (Tag R) maps to F3 A0 81 92\. This four-byte sequence was utilized in the Reverse CAPTCHA framework to bypass Anthropic models successfully, as the Claude tokenizer translates these specific bytes into highly actionable tokens7.

Example 2: The Limits of Unicode Normalization

A common fallacy in text preprocessing is assuming that standard Unicode normalization will automatically cleanse the data of invisible threats. The following laboratory test applies the four standard normalization forms (NFC, NFD, NFKC, NFKD) to a subset of control characters7.

Python import unicodedata

test\_chars \= { "ZWSP": "\\u200b", "BOM": "\\ufeff", "RLO": "\\u202e", "NBSP": "\\u00a0" }

normalizations \= \["NFC", "NFD", "NFKC", "NFKD"\]

for name, char in test\_chars.items(): print(f"{name} (U+{ord(char):04X}):") for norm in normalizations: normalized \= unicodedata.normalize(norm, char) hex\_repr \= " ".join(f"U+{ord(c):04X}" for c in normalized) print(f" {norm} \-\> {hex\_repr}")

Analysis of Execution: The output of this script confirms that the ZWSP (U+200B), the Byte Order Mark (U+FEFF), and the Right-to-Left Override (U+202E) remain completely untouched by all four normalization schemas. Only the Non-Breaking Space (U+00A0) is successfully transformed into a standard space (U+0020) under the stricter NFKC and NFKD compatibility normalizations7. This script mathematically proves that system administrators cannot rely on standard library normalizers to sanitize prompt injections or Trojan Source encodings.

Conclusions

The architecture of digital text is inherently dual-layered, permanently bifurcated into the logical sequence of encoded bytes and the visual presentation of rendered glyphs. The exploitation of this semantic gap through zero-width, bidirectional, and Tag Unicode characters represents a profound paradigm shift in cybersecurity and natural language processing. Historically, security analysis has relied heavily on human intuition and manual review to spot logic errors, malicious code, or deceptive prompts. The vulnerabilities explored in this report—from the Trojan Source compiler deception to the Reverse CAPTCHA LLM prompt injections and ATS keyword stuffing—demonstrate that visual review is no longer a sufficient metric for security. Attackers have successfully weaponized the rendering engine against the human, hiding critical system commands, supply chain poisons, and adversarial NLP perturbations in plain sight. As artificial intelligence systems gain autonomy and rely heavily on complex tokenization algorithms (like Byte Pair Encoding and Unigram models), the attack surface will only expand. These models perceive the mathematical reality of the data stream, processing the invisible tags and zero-width identifiers that humans cannot perceive. Consequently, modern digital infrastructure requires a fundamental shift toward rigorous, byte-level input sanitization, the deployment of visual aids in code editors, and the implementation of compiler-level constraints that reject deceptive encoding by default. Moving forward, the security of software supply chains and AI agents will depend not on what the operator sees, but entirely on the mathematical purity of the underlying bytes.

Works cited

1. Trojan Source Vulnerability: How Hackers Hide Malware in Source Code (2025), https://microhackers.ai/cybersecurity/flaw-allows-embed-malware-into-code/ 2. Trojan Source \- Wikipedia, https://en.wikipedia.org/wiki/Trojan\_Source 3. On Ruby and ꝩduЯ, or How Scary are Trojan Source Attacks \- Ruby Kaigi 2023, https://www.sw.it.aoyama.ac.jp/2023/pub/Ruby%EA%9D%A9du%D0%AF/ 4. The Technical User's Introduction to LLM Tokenization \- Christopher Samiullah, https://christophergs.com/blog/understanding-llm-tokenization 5. Reverse CAPTCHA: Evaluating LLM Susceptibility to Invisible Unicode Instruction Injection : r/netsec \- Reddit, https://www.reddit.com/r/netsec/comments/1rfjlyh/reverse\_captcha\_evaluating\_llm\_susceptibility\_to/ 6. How Invisible AI Glitches Break Your On-Site Search (And How to Fix It) \- AI Text Cleaner, https://www.aitextclean.com/blog/invisible-ai-glitches 7. unknown\_url 8. Trojan Source: Invisible Vulnerabilities \- USENIX, https://www.usenix.org/system/files/usenixsecurity23-boucher.pdf 9. Reverse CAPTCHA: Evaluating LLM Susceptibility to Invisible Unicode Instruction Injection, https://arxiv.org/html/2603.00164v1 10. Reverse CAPTCHA: Evaluating LLM Susceptibility to Invisible Unicode Instruction Injection | Moltwire Research, https://moltwire.com/research/reverse-captcha-zw-steganography 11. How Search Engines Work: The 2026 SEO Guide \- Yotpo, https://www.yotpo.com/blog/how-search-engines-work/ 12. Unlocking the Power of Latent Semantic Indexing | SEO Agency Serpact, https://serpact.com/what-is-latent-semantic-indexing/ 13. Bad Characters: Imperceptible NLP Attacks \- alphaXiv, https://www.alphaxiv.org/overview/2106.09898v2 14. How to remove invisible characters from text copied from PDF \- Super User, https://superuser.com/questions/1373413/how-to-remove-invisible-characters-from-text-copied-from-pdf 15. An Exploration & Remediation of JSON Interoperability Vulnerabilities \- Bishop Fox, https://bishopfox.com/blog/json-interoperability-vulnerabilities 16. Tokenization algorithms \- Hugging Face, https://huggingface.co/docs/transformers/tokenizer\_summary 17. google/sentencepiece: Unsupervised text tokenizer for Neural Network-based text generation. \- GitHub, https://github.com/google/sentencepiece 18. Let's Build the GPT Tokenizer: A Complete Guide to Tokenization in LLMs \- Fast.ai, https://www.fast.ai/posts/2025-10-16-karpathy-tokenizers.html 19. How Tokenizers Actually Work (And Why SentencePiece and TOON is Smarter Than JSON for LLMs) \- Medium, https://medium.com/@sadiqkhzn/how-tokenizers-actually-work-and-why-sentencepiece-and-toon-is-smarter-than-json-for-llms-e371a270810e 20. nickboucher/trojan-source \- Invisible Vulnerabilities \- GitHub, https://github.com/nickboucher/trojan-source 21. Trojan Source: Hiding malicious code in plain sight \- Malwarebytes, https://www.malwarebytes.com/blog/news/2021/11/trojan-source-hiding-malicious-code-in-plain-sight 22. Prevent Trojan Source attacks with GCC 12 \- Red Hat Developer, https://developers.redhat.com/articles/2022/01/12/prevent-trojan-source-attacks-gcc-12 23. 'Trojan Source' Flaw Exposes Apps to Covert Poisoning \- Bitdefender, https://www.bitdefender.com/en-us/blog/hotforsecurity/trojan-source-flaw-exposes-apps-to-covert-poisoning 24. 'Trojan Source' Flaw Exposes Apps to Covert Poisoning \- Bitdefender, https://www.bitdefender.com/en-gb/blog/hotforsecurity/trojan-source-flaw-exposes-apps-to-covert-poisoning 25. Bad Characters: Imperceptible NLP Attacks \- University of Edinburgh Research Explorer, https://www.research.ed.ac.uk/en/publications/bad-characters-imperceptible-nlp-attacks/ 26. Bad Characters: Imperceptible NLP Attacks | Request PDF \- ResearchGate, https://www.researchgate.net/publication/362297538\_Bad\_Characters\_Imperceptible\_NLP\_Attacks 27. Reverse CAPTCHA: Evaluating LLM Susceptibility to Invisible Unicode Instruction Injection \- arXiv, https://arxiv.org/pdf/2603.00164 28. AI Jailbreak Techniques in 2026: A Complete Technical Guide | ZioSec, https://ziosec.com/blog/ai-jailbreak-techniques-in-2026-a-complete-technical-guide-ziosec 29. Agent Architecture: Building AI-Powered Development Harnesses \- Blake Crosley, https://blakecrosley.com/guides/agent-architecture 30. Can Employers Tell If You Used AI? Spotting AI-Generated Text in Job Applications (2026), https://gpt-watermark-remover.com/blog/how-to-spot-ai-generated-text-job-applications 31. RAPIDS: Resume Attack Prompt Injection Detection at Scale \- ACL Anthology, https://aclanthology.org/2026.acl-industry.127.pdf 32. Deception and defense from machine learning to supply chains \- Department of Computer Science and Technology |, https://www.cl.cam.ac.uk/techreports/UCAM-CL-TR-994.pdf 33. USENIX'23 Artifact Appendix: Trojan Source: Invisible Vulnerabilities, https://secartifacts.github.io/usenixsec2023/appendix-files/sec23fallae-final14.pdf 34. C/C++ Memory Safety: Bugs, ASan, and Rust Interop \- Safeguard.sh, https://safeguard.sh/resources/blog/c-cpp-memory-safety-appsec-guide 35. New Trojan Source attack impacts compilers for most programming languages, https://therecord.media/new-trojan-source-attack-impacts-compilers-for-most-programming-languages