genai
SECURITY LAB
IncidentsData exfiltration

GitLab Duo Tricked into Leaking Private Source Code

High severityMay 2025LLM01: Prompt InjectionLLM02: Sensitive Information DisclosureLLM10: Improper Output Handling
Status: Reported to GitLab Feb 2025; fixed May 2025 (duo-ui!52) by blocking unsafe cross-domain rendering
On this page

Your AI pair-programmer reads the whole repo — including the instructions an attacker hid in it.

WhenMay 2025
TargetGitLab Duo (AI assistant)
VendorGitLab
ResearcherOmer Mayraz (Legit Security)
TechniqueRemote/indirect injection in repo content → markdown/HTML exfil
DisclosedReported Feb 12; public May 22, 2025; fixed (duo-ui!52)
Attack flow
  1. 1Attacker hides instructions in a merge request, commit, comment, or source file (invisible Unicode / encoding / white-text KaTeX)
  2. 2GitLab Duo ingests the project context and obeys them
  3. 3Duo leaks private code via a rendered image URL and injects malicious links into its answers

What happened

In 2025, Legit Security's Omer Mayraz found that because GitLab Duo analyses the whole project context, hidden instructions in merge-request descriptions, commit messages, issue comments, or source code were obeyed. Payloads were concealed with invisible Unicode, Base16 encoding, and white-text KaTeX. Duo could be made to leak private source code — base64-encoded into an attacker-controlled image URL rendered in its streaming output — and to inject malicious HTML and links into its answers. A demonstrated chain leaked code from a private iOS project. GitLab fixed it (duo-ui!52).

How the attack worked

Repo content is untrusted, but Duo consumed it as context, and Duo's markdown/HTML output rendered attacker-controlled URLs and tags. That gave the attacker both an instruction path in (hidden text in the repo) and a data path out (rendered images/links).

Root cause

Untrusted developer content sat in the model's context, and model output was rendered as active HTML to arbitrary domains.

What a test would have caught

Planting encoded or invisible instructions in repo artifacts and checking whether Duo exfiltrates data or renders attacker links is the exact test this class needs.

How to prevent it

  • Treat all repo content as untrusted input to the assistant.
  • Don't render model output as active HTML to arbitrary domains — GitLab's fix blocks non-gitlab.com img/form tags.
  • Encode output and strip invisible/encoded payloads before display.

Feel it yourselfThe replay lab plants an instruction in a repo file that a code assistant then follows.

FAQ

How does hidden text in a repo attack the AI?

Duo analyses the whole project context, so instructions concealed in a merge request, commit, comment, or even source code (via invisible Unicode, encoding, or white-text KaTeX) were read and obeyed as commands.

What was the impact?

A demonstrated chain leaked private source code — base64-encoded into an attacker-controlled image URL rendered in Duo's output — and let an attacker inject malicious HTML and links into Duo's responses.

Is it fixed?

GitLab blocked Duo from rendering unsafe tags pointing to non-GitLab domains (duo-ui!52), so the demonstrated exfiltration chain no longer works. A related Duo injection issue was separately tracked and patched.

Replay this attack
Plant an instruction in a repo file that a code assistant then follows — the GitLab Duo pattern.
Open the live lab
Runs as a live, sandboxed lab. Sign-in required — this replay is a Pro lab. Recreates the attack class, not this exact branded bot.