Skip to main content

MAL-TROJAN Trojan-Source Unicode Attacks

A trojan-source attack inserts invisible Unicode control characters so the code a reviewer sees, and a diff renders, differs from the code the compiler or interpreter runs. Human review cannot catch it; a byte-level scan can.

What Vulkro detects​

Three classes, one finding per file per class:

  • MAL-TROJAN-001 (High): a bidirectional control character (U+202A to U+202E, U+2066 to U+2069, U+061C) anywhere in a source file. These reorder how text displays without changing byte order, which enables the commenting-out and stretched-string attacks. Source essentially never needs one, so presence alone is High.
  • MAL-TROJAN-002 (Medium): a byte-order mark (U+FEFF) anywhere but byte offset 0. A leading BOM is a benign encoding marker.
  • MAL-TROJAN-003 (Medium, review only): a zero-width character (U+200B, U+200C, U+200D) directly against an ASCII identifier character, which can make two identical-looking names bind to different symbols. Emoji and some languages use these legitimately.

Source files under the scan root are walked (skipping node_modules, .git and common vendored or build directories), reporting the first offending line per class. The check is deterministic, but it cannot tell you the intent behind a character.

How to fix​

  • Open the line with invisible-character rendering on and decide whether the codepoint belongs.
  • Strip BiDi overrides and stray zero-width characters from source.
  • Add a CI check that rejects them.

References​

See also: Confidence model.


This page is generated by vulkro rules export <out-dir> from Vulkro's built-in detector catalogue. Edits made by hand are overwritten on the next regeneration.