Expose invisible reordering characters
Unicode has a set of bidirectional (BiDi) control characters that silently
change the visual order of text — essential for mixing right-to-left scripts like
Arabic and Hebrew with left-to-right Latin, but dangerous when abused. A single
Right-to-Left Override (U+202E) can make gpj.exe display as exe.jpg, or make
source code render differently from how it is stored (the “Trojan Source”
attack). This inspector finds every such character, names it, and shows where it
sits.
How it works
The tool scans the input code point by code point and checks each against the
complete set of Unicode bidirectional formatting and override controls:
LRM U+200E, RLM U+200F, ALM U+061C, LRE U+202A, RLE U+202B, PDF
U+202C, LRO U+202D, RLO U+202E, and the isolates LRI U+2066, RLI
U+2067, FSI U+2068, PDI U+2069. Each match is reported with its standard
name, its U+XXXX value and its index in the string. The inline view replaces
each control with a visible labelled marker so you can see exactly where the
reordering is injected, and a “stripped” output removes them all.
Example
A filename stored as invoicegpj.exe (with an RLO before gpj.exe)
renders to the eye as invoiceexe.jpg. The inspector flags one character — RLO
(U+202E) at the override position — making it obvious the file is really a .exe.
Tips and notes
- Code hosting platforms now warn about BiDi characters in diffs; this tool lets you check a snippet or filename before you trust it.
- The PDF (
U+202C) and PDI (U+2069) characters close an override or isolate; an unbalanced override with no matching close is a strong red flag.
When do legitimate BiDi characters appear?
Normal Arabic or Hebrew text embedded in an otherwise left-to-right document does not need explicit BiDi controls — Unicode’s bidirectional algorithm handles layout automatically using the inherent directionality of each character. Explicit controls are typically only needed when you are mixing a right-to-left run inside a longer sequence in a way the algorithm does not handle naturally, such as punctuation at a boundary or a quoted string whose direction differs from its surrounding paragraph. In practice, finding explicit override or isolate characters in source code, filenames, or commit messages is almost always a red flag, not a legitimate editorial need.
The Trojan Source attack in more detail
Trojan Source (CVE-2021-42574, disclosed 2021) demonstrated that many code editors, diff viewers, and code-review platforms display BiDi-overridden text visually reordered from how it is stored on disk. An attacker could submit a pull request in which a comment contains code — hidden by an RLO that makes it appear to the reviewer as an innocuous comment — while the compiler reads the bytes in storage order and executes the injected logic. The fix is for editors and platforms to render BiDi controls visibly, but checking untrusted code snippets with a tool like this one provides an independent second opinion. The inspector catches the specific overrides (RLO U+202E, LRO U+202D) most commonly exploited in the original research.
Reference: Unicode BiDi controls detected
| Character | Code point | Name | Direction |
|---|---|---|---|
| LRM | U+200E | Left-to-Right Mark | Forces LTR |
| RLM | U+200F | Right-to-Left Mark | Forces RTL |
| ALM | U+061C | Arabic Letter Mark | Arabic context |
| LRE | U+202A | Left-to-Right Embedding | Start LTR embed |
| RLE | U+202B | Right-to-Left Embedding | Start RTL embed |
| U+202C | Pop Directional Formatting | Close LRE/RLE/LRO/RLO | |
| LRO | U+202D | Left-to-Right Override | Force LTR reorder |
| RLO | U+202E | Right-to-Left Override | Force RTL reorder |
| LRI | U+2066 | Left-to-Right Isolate | Isolate LTR run |
| RLI | U+2067 | Right-to-Left Isolate | Isolate RTL run |
| FSI | U+2068 | First Strong Isolate | Heuristic isolate |
| PDI | U+2069 | Pop Directional Isolate | Close LRI/RLI/FSI |