Rules / GL078
GL078 Invisible / bidirectional Unicode characters (Trojan Source)
Severity: warn
OWASP: CICD-SEC-4 – Poisoned Pipeline Execution
Risk
.gitlab-ci.yml files can carry invisible or bidirectional Unicode control characters that make the rendered text differ from what is actually parsed and executed — the "Trojan Source" class (CVE-2021-42574). A script: line can look benign in a reviewer's editor while running something else, or hide payload via zero-width characters that survive copy-paste.
What glsec checks
GL078 scans the raw bytes of the file (not the parsed YAML tree, where these characters are invisible) and flags any occurrence of:
Bidirectional control characters (reordering attacks):
| Range | Characters |
|---|---|
U+202A–U+202E |
LRE, RLE, PDF, LRO, RLO |
U+2066–U+2069 |
LRI, RLI, FSI, PDI |
U+061C |
Arabic letter mark |
Zero-width / invisible characters (hidden-payload / homoglyph smuggling):
| Code point | Character |
|---|---|
U+200B–U+200D |
Zero-width space / non-joiner / joiner |
U+2060 |
Word joiner |
U+FEFF |
Zero-width no-break space / BOM |
U+00AD |
Soft hyphen |
A single leading U+FEFF byte-order mark is allowed so BOM-prefixed files are not flagged; any later U+FEFF is reported.
Line breaks that only YAML sees:
| Code point | Character |
|---|---|
U+000D |
Carriage return not followed by a line feed (CRLF line endings are fine) |
U+0085 |
Next line (NEL) |
U+2028 |
Line separator |
U+2029 |
Paragraph separator |
The YAML parser starts a new line at each of these, but most editors, git diff and GitLab's file view don't. A file containing them is parsed into different lines than a reviewer reads, and the line numbers of findings after them, from glsec and from other tools, point at the wrong place. GL078 reports them with the line and column as an editor counts them (by line feeds).
Trigger example
A line that renders as a harmless comment but reorders under a U+202E (RLO) override, or a script: value with an embedded U+200B, produces a finding pointing at the line and column of the offending code point:
GL078 warn: invisible/bidirectional Unicode character U+202E (RIGHT-TO-LEFT OVERRIDE) at column 18 …
Safe alternative
Remove the control character, and use plain \n or \r\n line endings. CI configuration never needs bidirectional, zero-width or Unicode line-break characters; keep .gitlab-ci.yml to plain ASCII (plus ordinary accented text where genuinely required).
False-positive risk
Very low — these code points essentially never appear legitimately in a CI configuration.
Documentation for glsec 1.23.0. Source of this page · Rule implementation