Skip to main content

Guides

Trojan Source: Invisible Unicode Vulnerabilities in Source Code

CleanPastedText editorial · Updated

Text workbench

Try it on your text

Cleaning mode

Removes hidden characters and standardizes AI-style punctuation.

Try a real example

Each sample contains a problem you cannot see.

Original

Pasted text

0 chars · 0 words

Cleaned

Ready to copy

0 changes

Text stays in this browser

Same words · No AI rewriting · No content logging

What is the Trojan Source attack?

Trojan Source is a technique for making source code compile or execute differently from how it appears to a human reader. Nicholas Boucher and Ross Anderson of the University of Cambridge published the technique on November 1, 2021, showing that Unicode bidirectional (BiDi) control characters — the same characters covered on this site's BiDi character remover page — can be placed inside a comment or string literal to visually reorder the code around them, without changing what the compiler actually reads byte-for-byte.

The underlying cause is the Unicode Bidirectional Algorithm, built so a line can mix left-to-right scripts like English with right-to-left scripts like Arabic or Hebrew and still display in the correct reading order. Source-code parsers were never designed to guard against that same mechanism being used adversarially, so an override character such as U+202E (right-to-left override) can make a stretch of source display in reverse order on screen while the compiler still processes it left to right, byte by byte.

How "Early Return" and "Commenting-Out" work

The paper names two concrete exploitation patterns. In Early Return, an attacker hides a functional return statement inside what looks like an inert comment or string; because BiDi controls only affect display order, not the underlying byte sequence, the compiler still executes the hidden statement and the function exits before the code the reviewer sees ever runs. In Commenting-Out, the trick runs in reverse: BiDi characters make a live line of code — a permission check or an input validation, for example — display as though it sits safely inside a comment, so a reviewer reads past it as dead text while it keeps executing normally.

Both patterns rely on the same small set of invisible characters: U+202AU+202E (the embedding and override controls) and the newer isolate controls U+2066U+2069. None of them have a visible glyph of their own — they only change how the characters around them are drawn — which is exactly what makes them invisible in a normal code review.

CVE-2021-42574, CVE-2021-42694, and who it affects

The disclosure carries two CVE identifiers. CVE-2021-42574 covers the BiDi override technique described above. A second, related identifier, CVE-2021-42694, covers a separate technique from the same paper that swaps identifiers for visually near-identical homoglyphs instead of reordering them — the same family of substitution covered in more depth on the homoglyph attack detection page. Because dozens of compiler vendors, language maintainers, and code-hosting platforms received the report under coordinated disclosure before the public date, both CVEs are cited broadly across advisories rather than tied to one specific product.

Language testedResult in the paper
C / C++Vulnerable — both techniques compiled and ran as hidden
C#Vulnerable
JavaScriptVulnerable
JavaVulnerable
RustVulnerable
GoVulnerable
PythonVulnerable

The authors noted the root cause sits in how source files are parsed relative to the Unicode Bidirectional Algorithm, not in any one compiler's bug — so any language accepting UTF-8 or UTF-16 source with BiDi characters allowed inside comments or strings is a plausible candidate, not only the eight tested.

How GitHub and editors catch it today

GitHub shipped detection the same day the vulnerability went public: since October 31, 2021, any file or pull-request diff containing bidirectional Unicode control characters gets a visible warning banner, prompting a reviewer to inspect the raw bytes before approving. The banner is informational only — it does not block a merge on its own — so a reviewer still has to click through and act on it. Editors add a second layer: Visual Studio Code highlights BiDi control characters inline by default, and dedicated scanners such as the researchers' own reference detector can be run in CI to fail a build outright rather than just warn.

Checking a snippet before it goes in a commit

Most Trojan Source characters don't arrive through a targeted attack — they ride along in code copied from a chat assistant, a forum post, a PDF, or a webpage that mixed scripts somewhere upstream, the same way tag-character smuggling and stray BiDi marks do. Paste a snippet into the hidden character checker above to see every directional control character by code point and count without changing anything, or run it through the BiDi character remover to strip them outright before it reaches version control. For code, JSON, and CSV generally, see sanitizing copied text for code, JSON, and CSV.

Common questions

Frequently asked questions

What is the Trojan Source attack?

Trojan Source is a technique for making source code display one way to a human reviewer while compiling or interpreting a different way. It works by inserting Unicode bidirectional (BiDi) override characters — such as U+202E (right-to-left override) — inside a comment or string literal. Because BiDi controls are designed to let left-to-right and right-to-left scripts mix on one line, an editor or diff viewer visually reorders the characters that follow, hiding real code inside what looks like an inert comment. Nicholas Boucher and Ross Anderson of the University of Cambridge published the technique on November 1, 2021.

What is CVE-2021-42574?

CVE-2021-42574 is the coordinated-disclosure identifier covering the Trojan Source BiDi-override technique itself, used across the dozens of compilers, interpreters, and code-hosting tools that received advance notice before the November 2021 public disclosure. A closely related identifier, CVE-2021-42694, covers a second technique from the same paper that uses homoglyphs (visually near-identical characters) instead of BiDi controls to disguise identifiers.

Which programming languages are affected?

The original paper demonstrated working exploits against C, C++, C#, JavaScript, Java, Rust, Go, and Python, and the authors noted the underlying issue — the Unicode Bidirectional Algorithm being applied inside source files not designed to guard against it — likely affects most languages that accept UTF-8 or UTF-16 source files and allow BiDi characters inside comments or strings.

How does GitHub protect against Trojan Source today?

GitHub added detection the same day the vulnerability was disclosed: since October 31, 2021 it displays a visible warning banner on any file or pull request diff containing bidirectional Unicode control characters, prompting the reviewer to inspect the raw bytes before merging. The warning does not block a merge by itself, so reviewers still have to act on it, and editors like Visual Studio Code separately highlight BiDi control characters inline by default.

What are the 'Early Return' and 'Commenting-Out' techniques?

They are the two exploitation patterns described in the original paper. Early Return hides an extra, functional return statement inside what displays as a comment or string, so the function exits before the reviewer's visible logic runs. Commenting-Out uses the same BiDi reordering trick in reverse: it makes an active line of code — such as a permission check — display as if it were safely wrapped inside a comment, while the compiler still executes it.

How do I check pasted code for hidden BiDi characters before committing it?

Paste the snippet into a tool that scans specifically for directional control characters, such as CleanPastedText's hidden character checker, before it goes into a commit. It lists every BiDi character found by code point and count without altering anything else in the snippet, so you can confirm a file is clean or see exactly what an automated formatter stripped.

Continue reading

Related guides & tools