Check G19 · agent surface family · severity CRITICAL · automatic · one of the 22 GitLab checks
The question this check asks: do the files an AI coding agent reads at the start of a session — AGENTS.md, CLAUDE.md, .cursorrules, an MCP configuration — contain characters that render as nothing? On gitlab.com the files are the same, and one more reader has joined them.
Code review is a visual process, and these files are written to be skimmed. The Rules File Backdoor, published by Pillar Security in March 2025, puts instructions inside an agent's rules file using codepoints that occupy no visible space — zero-width joiners, bidirectional overrides, the Unicode Tags block. The reviewer sees ordinary guidance and approves the merge request. The model reads the hidden text and does what it says. It needs no vulnerability, only a file a person skims and an agent obeys; both Cursor and GitHub initially declined responsibility for it.
The files that fit that description are the ones serious projects ship. In the Phase 0 controls 77 of the 80 most popular GitHub repositories carried an agent instruction file; on 19 September 2026, 18 of the 100 most-starred gitlab.com projects did, AGENTS.md on 16 of them. On gitlab.com that particular file has a reader built into the platform: GitLab Duo reads AGENTS.md from the project root and its subdirectories — in Chat since 18.7, generally available in 18.8 — with no untrusted-project warning in its documentation. A codepoint no reviewer sees in an AGENTS.md reaches the agent on your machine and the platform's own assistant alike. That is why having the file costs nothing and what is inside it is the check.
G19 fetches the agent files a project ships — CLAUDE.md, AGENTS.md, .cursorrules, .clinerules, .windsurfrules, .github/copilot-instructions.md, .cursor/rules/*.mdc, .mcp.json, .cursor/mcp.json and the .claude/ settings files — through gitlab.com's files API, /repository/files/:path/raw, at most eight a scan: the same check and the same code as C19, on a snapshot built from GitLab's API. It scans each for codepoints in U+200B–U+200F, U+202A–U+202E, U+2060–U+2064, U+2066–U+2069, U+FEFF and U+E0000–U+E007F. Any hit is CRITICAL, costs 45 points, and makes the verdict BLOCK; the default personal policy blocks on it, and strict organisation profiles lock that so no policy edit can lower it. The finding names the file, the count and the codepoint names — “3 invisible codepoints (ZERO WIDTH JOINER, RIGHT-TO-LEFT OVERRIDE) — Rules File Backdoor technique; instructions hidden from human review” — and never the decoded text. The evidence note in the scoring table:
“Rules File Backdoor; zero FPs observed”
On the 100 most-starred gitlab.com projects it fired on none: the 18 that carry agent files were read in full and no codepoint in the set was found. The presence of the file itself is a separate row, agent-config, weighted at 0 points for the reason above: “77/80 top repos ship CLAUDE.md/AGENTS.md in 2026 — presence is not signal”.
None observed — not in the 80 popular, 50 young and 20 binary-shipping GitHub control repositories of Phase 0, and not in the 100 most-starred gitlab.com projects. The one we expect to see eventually is a byte-order mark (U+FEFF) at the top of a file saved by a Windows editor. If that fires on yours, the finding will say exactly one codepoint, ZERO WIDTH NO-BREAK SPACE, at the start of the file — and we would like to hear about it, because it decides whether a BOM at offset zero should be exempted.
It scans the files on the list. A rules file under a name we do not know — GitLab Duo's own .gitlab/duo/chat-rules.md and a skills/<name>/SKILL.md are not on it yet — or one added to the project after you downloaded it, is not read. It looks for invisible characters: homoglyphs — letters from another script that look like Latin ones — are a different technique and are not caught here, and neither is an instruction hidden in plain, readable prose that a reviewer would have to think about rather than see. It reads the project's files, not your agent's own configuration outside it. And a project whose tree the API does not answer — one of the 100, spacecowboy/Feeder — has this check listed as not checked, not passed.
And RepoGates as a whole gates browser downloads only — it does not see git clone, package managers, curl, or fetches made by AI agents outside the browser. On gitlab.com the board and the download gate are a later, separate store release: today the verdict on a gitlab.com project is served by the API and the MCP server. A rules file that reaches your machine by clone is not seen by this check; the tools in the next section run on a clone and are the right answer there.
RepoGates runs the same 22 checks on a gitlab.com project that it runs on a GitHub repository, from gitlab.com's public API, under the key gl/{namespace…}/{project}. What that API withholds from an anonymous caller — fork status, a user namespace's account age, and OpenSSF Scorecard, which does not cover gitlab.com — is listed as not checked, never assumed. A self-managed GitLab is another hostname and is not assessed. The repository's code is not read on this tier: a PASS means the provenance and the declared execution surface are clean.
Without installing anything: open the file in an editor that renders invisible characters — VS Code highlights them by default; we have not verified what gitlab.com's own file view marks, so do not lean on it. From a terminal, fetch the files through the same API the check uses and scan them — the project path is URL-encoded, every / written %2F, and so is a path inside the project, so .claude/settings.json is .claude%2Fsettings.json:
P='NAMESPACE%2FPROJECT'; REF=main
for f in AGENTS.md CLAUDE.md .cursorrules; do
curl -sf "https://gitlab.com/api/v4/projects/$P/repository/files/$f/raw?ref=$REF" -o "$f"
done
perl -ne 'print "$ARGV:$.: $_" if /[\x{200B}-\x{200F}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{2066}-\x{2069}\x{FEFF}\x{E0000}-\x{E007F}]/' AGENTS.md CLAUDE.md .cursorrules
For a whole tree, the open-source anti-trojan-source scanner and SonarQube's rules S6389 and S7628 cover the same codepoints, and Pillar publishes a free rules-file scanner. Those run on what you already have; this check runs before the download.
My project has an AGENTS.md — does that fire this check? No. Having an agent instruction file costs 0 points — 77 of the 80 most popular GitHub repositories ship one, 18 of gitlab.com's 100 most-starred projects do, and GitLab Duo reads AGENTS.md by design, so presence is not a signal. G19 reads what is inside the file, and fires only on codepoints that render as nothing: zero-width characters, bidirectional overrides, invisible operators, the Unicode Tags block.
Can I see what was hidden? Not from the finding, deliberately. It names the file, the number of invisible codepoints and their Unicode names — never the decoded text, because rendering a hidden instruction into a report moves the payload to a second surface. Open the file in an editor that shows codepoints, or fetch it through the files API and run the one-line scan on this page.
Does RepoGates stop git clone? No. RepoGates gates browser-initiated downloads, and on gitlab.com the board and the download gate are a later, separate store release: today a gitlab.com project's verdict is served by the API and the MCP server. It does not see git clone, package managers, curl, or fetches made by AI agents outside the browser. A rules file that reaches your machine by clone is not seen by this check.
C19 Hidden Unicode — the GitHub original · G18 Agent config files — the files this check reads; presence alone is 0 points · G20 MCP shell-launch config — the same files, a different payload: a command that fetches and runs · G22 AI-agent provenance — a project carrying instructions for an agent and recommended by one.
Add RepoGates to Chrome Pricing
Numbers on this page: Pillar Security, March 2025 (the technique); Phase 0 controls of 14 August 2026 (150 GitHub repositories, zero hits; 77 of 80 carrying agent files); the 100 most-starred gitlab.com projects measured 19 September 2026 (18 with agent files, zero hits); GitLab's documentation for AGENTS.md in GitLab Duo; weights from the product's scoring table; codepoint ranges from the repository vetting standard.