Security

Bidi Text Attack

Exploiting Unicode bidirectional control characters to disguise malicious code or filenames. The 'Trojan Source' attack (CVE-2021-42574) uses bidi overrides to hide backdoors in source code.

What is a Bidirectional Text Attack?

A bidirectional text attack (also called a Bidi attack or Trojan Source attack) exploits the Unicode Bidirectional Algorithm (UBA) to make text appear to have different content than it actually contains. Because developers, reviewers, and administrators read text through rendering engines that apply the Bidi algorithm, they may see a safe-looking string while the underlying bytes contain something entirely different.

The Unicode Bidirectional Algorithm

The Unicode Bidirectional Algorithm (UAX#9) allows a single string to contain mixed left-to-right and right-to-left text — for example, an English sentence with an embedded Arabic phrase. It achieves this through invisible control characters that shift the rendering direction. The key control characters include:

  • RLO (U+202E) — Right-to-Left Override: forces all following characters to render right-to-left
  • LRO (U+202D) — Left-to-Right Override: forces left-to-right rendering
  • RLE (U+202B) — Right-to-Left Embedding
  • PDF (U+202C) — Pop Directional Formatting (ends an override or embedding)
  • RLI (U+2067), LRI (U+2066), FSI (U+2068) — isolate variants (safer)
  • PDI (U+2069) — Pop Directional Isolate

Trojan Source — CVE-2021-42574

In November 2021, researchers Nicholas Boucher and Ross Anderson published Trojan Source, demonstrating how Bidi control characters can be used to inject malicious code into source files in a way that is invisible during code review but interpreted differently by the compiler.

The classic Trojan Source example uses a comment to hide a string that contains an early string terminator and malicious logic:

// The attack (conceptual — do not copy literally into editors)
// access_level = "user\u202E \u2066// Check if admin\u2069 \u2066"

// What the compiler sees:  access_level = "user"  // followed by active code
// What reviewers see (rendered):  access_level = "user  // Check if admin"

The RLO and isolate characters cause the code review tool to reverse the display of a portion of the string, making the comment appear to close before the malicious content but actually not doing so in the source bytes.

RLO-Based Filename Disguise

Long before Trojan Source, attackers used U+202E (RLO) to disguise executable file extensions in filenames. A file named:

Invoice_[U+202E]gpj.exe

is displayed by Windows Explorer as Invoice_exe.jpg — the extension appears to be .jpg because RLO reverses the display of the characters after the control character. Users double-clicking the "image" run the .exe file.

GitHub and GitLab Mitigations

Following the Trojan Source disclosure, major code hosting platforms introduced countermeasures:

  • GitHub added a warning banner on any file view that contains Bidi override or embedding characters, stating "This file contains bidirectional Unicode text that may be interpreted differently than what appears below."
  • GitLab implemented similar warnings in the diff view and file viewer.
  • gcc and clang compilers added warnings for Bidi control characters in string literals and comments.
  • CVE-2021-42574 was issued and patched in multiple compilers and editors.

Defense Strategies

  1. Lint for Bidi control characters — add a pre-commit hook or CI check that rejects files containing U+202A–U+202E, U+2066–U+2069
  2. Configure editors — VS Code, JetBrains IDEs, and Vim can be configured to render Bidi control characters visibly
  3. Audit existing code — search codebases for the hex byte sequences: E2 80 AA through E2 80 AE (UTF-8 for U+202A–U+202E)

Quick Facts

Property Value
CVE CVE-2021-42574 (Trojan Source)
Researchers Nicholas Boucher and Ross Anderson, Cambridge
Publication date November 2021
Key control chars U+202E (RLO), U+202D (LRO), U+202B (RLE)
Attack surfaces Source code review, filenames, web content, emails
Compiler mitigations gcc -Wbidi-chars, clang warning added
Platform mitigations GitHub/GitLab Bidi warning banners
Unicode standard UAX#9 — Unicode Bidirectional Algorithm

Related Terms

More in Security