CamoLeak: Silent Private-Repo Theft via GitHub Copilot Chat
On this page
Invisible text in a pull request turned a developer's own AI assistant into a channel for stealing their private code.
| When | October 2025 |
|---|---|
| Target | GitHub Copilot Chat |
| Researcher | Omer Mayraz (Legit Security) |
| Technique | Indirect prompt injection + Camo/CSP-bypass exfiltration |
| CVE | CVE-2025-59145 — CVSS 9.6 (Critical) |
- 1An attacker hides instructions in an invisible markdown comment in a PR or issue
- 2The victim's GitHub Copilot Chat ingests the content and follows the hidden instructions
- 3Copilot reads private-repo data and leaks it via a dictionary of GitHub-signed Camo image URLs
What happened
In 2025, Legit Security's Omer Mayraz disclosed CamoLeak (CVE-2025-59145, CVSS 9.6): a critical flaw that let an attacker exfiltrate a victim's private source code through their own GitHub Copilot Chat. Instructions hidden in an invisible markdown comment in a pull request were read by Copilot as an indirect prompt injection. GitHub fixed it in August 2025.
How the attack worked
The hidden instructions told Copilot to search the victim's private repositories (for example, for AWS keys) and encode what it found. To defeat GitHub's content-security policy — which routes images through a 'Camo' proxy precisely to block image-based exfiltration — the researcher pre-computed a dictionary of validly-signed Camo URLs, one per character. Copilot spelled out the stolen data character by character as the browser fetched those trusted image URLs.
The clever partThe exfiltration channel was the very control meant to prevent it: legitimately-signed Camo image URLs the CSP already trusted.
Root cause
Untrusted repository content (a PR comment) was allowed to instruct the assistant, and the assistant's output could trigger outbound image fetches that carried data — so the CSP's own allowlist became an exfiltration path.
What a test would have caught
An indirect-injection test that plants hidden markup in ingestible content and checks whether the assistant will read privileged data or emit encoded outbound URLs would have surfaced both halves before shipping.
How to prevent it
- Strip and normalise invisible markup before content reaches the model.
- Treat repo content as untrusted; don't let it act as instructions.
- Deny data-bearing egress — even signed image URLs — from model-influenced output.
Feel it yourselfThe replay lab recreates the exfiltration class CamoLeak abused — get an assistant to leak its context through a rendered image URL.
FAQ
How does hidden text in a PR reach Copilot?
GitHub markdown supports comments that render invisibly to humans but are still read by the model. When Copilot Chat ingests the PR/issue, those hidden instructions become an indirect prompt injection the user never sees.
Why is bypassing the Camo proxy the clever part?
GitHub's content-security policy normally blocks image-based exfiltration by routing images through its 'Camo' proxy. The researcher pre-generated a dictionary of validly-signed Camo URLs, one per character, so the stolen data could be spelled out through image fetches the CSP still trusted.
How do you defend against it?
Treat any repo content the assistant reads as untrusted, strip/normalise invisible markup before it reaches the model, and don't let model-influenced output mint outbound requests (even 'trusted' image URLs) that can encode data.
Sources
- CamoLeak: Critical GitHub Copilot Vulnerability Leaks Private Source Code — Legit Security
- CVE-2025-59145 (GHSA-5fvm-p68v-5wmh) — GitHub Advisory Database