RTLO Unicode Remediation
Overview
Right-to-left override (U+202E) and related bidirectional control characters reverse how text renders without changing what the compiler sees. An attacker hides them in comments, strings, or identifiers so reviewers read a benign line while the compiler processes a malicious one. This is the Trojan Source class of attack. The remediation is to strip or reject these characters at the source level and enforce that rejection in CI.
Related Detector: RTLO Unicode
Recommended Fix
Before (Vulnerable)
// This line contains a hidden RTLO character that reverses display:
// What reviewers see: require(msg.sender == admin);
// What compiles: require(msg.sender == attacker);
require(msg.sender == admin);
After (Fixed)
// Source files contain only plain ASCII / well-defined Unicode.
// No bidirectional control characters are present, so the rendered
// line and the compiled line are identical.
require(msg.sender == admin);
The fix removes ambiguity between display and execution. When no bidirectional control characters exist in the file, what an auditor sees is exactly what the compiler executes.
Alternative Mitigations
- Add a CI check that rejects any file containing U+202A through U+202E and U+2066 through U+2069. Fail the build rather than warn.
- Configure editors and code-review tooling to highlight or refuse to render bidirectional control characters so reviewers notice them.
- Compile with a recent Solidity release; the compiler emits a warning for these characters. Treat that warning as an error in the build configuration.
Common Mistakes
- Relying on visual review alone. The whole point of the attack is that the malicious version looks benign on screen.
- Whitelisting an entire Unicode block for legitimate Arabic or Hebrew string content, which also re-admits the dangerous control characters. Restrict the exception to string literals and still ban the override codepoints.
- Treating the compiler warning as informational and shipping anyway.