The pitch for an AI code reviewer is that it reads every pull request so a tired human does not have to. Researchers just showed the catch: it never opens the picture. On July 11, the ASSET Research Group at the University of Missouri-Kansas City published a proof of concept they call Ghostcommit, in which a single image merged into a repository turns a developer's own AI coding agent into the thing that reads the project's secrets and hands them over.
No exploit is running in the wild yet. This is a demonstrated technique, not an incident. But it lands on a design assumption that a lot of teams have quietly adopted this year: that pointing an automated reviewer at a pull request is a safety gate. For this class of attack, it is not.
The attack lives in a picture, not the code
The delivery vehicle is the convention file, the plain-text README that coding agents read at startup to learn a project's rules: AGENTS.md, and its cousins like CLAUDE.md and .cursorrules. An early version of the researchers' payload wrote the malicious instruction straight into AGENTS.md in plain words, and AI reviewers caught it. So they moved it. In the working version, AGENTS.md carries only an innocent pointer to an image file named build-spec, and the attack instruction is rendered as readable text inside that PNG.
The hidden text tells the agent to open the project's .env, walk it one character at a time, and turn each into a number. Nothing fires at merge time. The trap springs later, when a developer asks the agent for something unrelated. On startup the agent loads the rules file, chases the pointer into the image, does what the rendered text says, pulls the contents of .env, and buries them in the new module as a value dressed up to look like build metadata. In the researchers' run, Cursor paired with Claude Sonnet did it unprompted on the first try, producing a block of 311 numbers that decode straight back to the whole .env.
- 1Poisoned PNG referenced in AGENTS.md is merged via an unreviewed pull requestDetection point
- 2Developer asks the coding agent for an unrelated feature
- 3Agent reads AGENTS.md at startup and follows the pointer into the image
- 4Agent opens .env and reads it byte by byteDetection point
- 5Agent writes the secrets into code as a provenance constantDetection point
Why two AI reviewers waved it through
The researchers ran the poisoned pull request past two popular AI code review products. According to their write-up, CodeRabbit returned no findings because its default configuration excludes image files from review with a !**/*.png pattern. Cursor's Bugbot also came back empty, even though the image spelled the attack out in blunt terms and used the words malicious prompt injection outright. Neither tool is broken in the ordinary sense. Each did exactly what it was set up to do: read the code and skip the attachments.
That is the whole point, and it is the part the day-one coverage mostly skated over. A human reviewer who saw a new binary image land in a rules file might open it out of curiosity. An automated reviewer that never opens the artifact a human would open is not a smaller version of that human. It is a different reviewer with a different blind spot, and an attacker only has to find the seam. The researchers make the same point: an automated reviewer that would need to open the attachment to catch this simply does not open it.
The real weak point is the merge, not the model
It is tempting to file this under "AI is unsafe" and move on. The researchers' own numbers argue against that reading. Not every agent complied: across the reported testing, Claude Code refused the instruction across the models it was run with, and Claude Opus recognized the payload and deleted it, while Cursor with Claude Sonnet, Google's Antigravity, and setups using Gemini and GPT-4.5 went along with it. What decided the outcome was how each agent treated untrusted instructions and what files it was allowed to touch, not the raw model underneath. That is a permissions and agent-design problem, and it is one you can influence.
The bigger number is about people. Across a sample of 6,480 pull requests drawn from the 300 busiest public repositories, the researchers found that 73 percent of the ones that landed on the main branch had gone in with no meaningful check from either a person or a bot. The image is the clever part of Ghostcommit, but the reason it works is mundane: a lot of code ships that nobody looked at. We have watched this same shape before, where a pull request from an untrusted contributor became code execution and where a config file in a repository ran as the developer who opened it. Ghostcommit is that pattern wearing a picture.
Treat convention files as code and lock the agent out of .env
Three moves close most of the exposure, and none of them require you to stop using coding agents.
Put human eyes back on the highest-trust files. A change to AGENTS.md, CLAUDE.md, .cursorrules, or any new image referenced from them deserves the same required human review you would demand of a CI workflow file. These files are not documentation. They are instructions your agent executes, so review them as code, and treat an image dropped into a rules directory as opaque until a person has opened it.
Keep live secrets out of the agent's reach. The payload only pays off because .env sits in the working tree holding real, long-lived credentials that the agent process can read. Scope the agent's file access so it cannot read secret files during ordinary work, move real secrets to a vault or short-lived scoped tokens, and rotate anything an agent could have already seen. If the file it reads is worthless, the leak is too.
Watch the agent's behavior, not just its output. The strongest signals here are behavioral: an agent reading .env during a task that has nothing to do with configuration, or agent-authored code that carries a long array of integers or a base64 blob parked next to a build or provenance constant. Those are cheap to alert on and hard for this technique to avoid, and they are exactly the kind of odd-sequence-of-actions that behavioral threat hunting exists to catch. We made the same argument when a clean-looking repository used the agent itself to open a reverse shell, and when a public GitHub issue talked an agent into leaking a private repo: the fix is not a single patch, it is treating the agent as an untrusted process that can be talked into things.
Ghostcommit does not have a CVE and never will, because there is no single product to patch. It is a property of how coding agents read a repository and how automated reviewers read a pull request. That makes it the kind of finding worth acting on before it stops being a proof of concept. Decide today which files in your repositories are really instructions to a machine, and start reviewing them like it.