NS-024
documentedrendering-diverges-from-bytes
Bidirectional control characters make source read differently than it compiles
- reads as
- A reviewer reads the diff and the early return is plainly inside a comment. Conclusion drawn: the change is inert.
- actually
- Unicode bidirectional overrides (U+202A to U+202E, U+2066 to U+2069) reorder the display of tokens without changing their logical order. Compilers and interpreters adhere to the logical ordering of source code, not the visual order, so the code executed is not the code rendered. Catalogued as CVE-2021-42574, with a homoglyph variant as CVE-2021-42694.
- blind because
- Reading a file means reading a rendering of it. The terminal, the editor and the diff viewer all apply the same bidi algorithm as the attack, so the instrument and the exploit agree with each other and disagree with the compiler.
- the check
- Search for the characters instead of reading the text: `grep -rlP '[\x{202A}-\x{202E}\x{2066}-\x{2069}]' path/` names files containing them and prints nothing for files that do not. Verified against a planted sample and a clean file.
- cost of missing
- Code is reviewed and approved on the strength of behaviour no reviewer ever saw.
- mitigation
- Compilers now detect this where asked: rustc's text_direction_codepoint_in_literal lint and gcc's -Wbidi-chars. Enable them rather than relying on reading.
- generalises to
- Any check performed on a rendering of an artifact rather than on its bytes.
- source
- trojansource.codes