RETRO

Software and AI · security · supply chain

Plugin4Shell: The AI Agents' Sealed Plugin

Plugin4Shell: The AI Agents' Sealed Plugin
Image: publisher's press kit

Picture a plugin that can slip into a disguise. That is exactly this month's subject: a security hole called Plugin4Shell. There's no great magic involved, just one missing check. Nothing more. But that one check turned out to be missing in four big AI coding agents at once! Let me say this up front: this piece is based on the researchers' report, the vendors' documentation and release notes, and the fix records in a code repository. We did not set this hole up and try it on our own machine.

First, what's the problem?

Today coding agents like Claude Code, Codex, Copilot and Gemini CLI (agent: an AI assistant that can run commands on its own) can be extended with plugins. And plugins come from a marketplace. For each plugin, the marketplace points to a specific commit, meaning it pins one particular moment of the repository with a 40-character SHA hash (a fingerprint). This is called "pinning". The logic is pretty solid: someone reviewed that commit, found it clean, and the marketplace stamped its seal on it: "this version of this plugin is safe". Whatever the repo owner changes the next day, you get the reviewed version.

That's the theory. Researchers Or Nevo, Dor Granat and Niv Hoffman, from a security company called Air Security, tell a different story in their write-up dated 17 September 2026. The agents check out the commit the marketplace points to, but they never look at whether the code they end up holding is actually that commit. The agent tells you "I installed the pinned, reviewed version", while something completely different could be sitting on your disk.

Why does this matter? Because the plugin runs with your permissions. It can reach your files, and the credentials lying around on your machine (API keys, cloud access credentials, I don't know, your SSH key). In the old days, for a program to rummage through your disk you had to run it with your own hands. Now the agent runs it for you, and on top of that it hands you the "everything's fine" report itself.

How does the trick work?

The whole trick lies in one of git's habits. When you give git a name, and that name could be both the name of a branch and the hash of a commit, git picks the branch. So can a branch be named with a 40-character commit hash? On some servers, it can!

That's the first method Air describes. The attacker creates a branch whose name is exactly the hash of the pinned commit and makes it the repo's default branch. When the agent says "fetch me this commit", git finds the branch and the checkout lands on the attacker's code. Claude Code, Codex and Copilot turned out to be open to this method.

In Gemini CLI the road is a little different. There the default branch is named FETCH_HEAD. FETCH_HEAD is a special name git uses itself: it points to whatever was fetched last. A branch with the same name cuts in front of the commit that was actually fetched. It looks like a cute little name clash, but the result is anything but cute.

The order of the attack is like the work of a patient con man, too. First a harmless plugin is published. Then you wait until users adopt it. Then the pin is moved to another harmless commit, and the marketplace reviews and approves that. Last of all, the malicious branch carrying that commit's name is added. Everyone doing a review sees a clean commit, and what goes out to the user is something else. Nobody seems to be lying, git is just following its own rules. That's exactly why it's so hard to spot.

Who did what, and when?

According to the timeline Air gives, the hole was found in May 2026, with a proof of concept that worked against all four agents. In June it was reported to all four vendors. After that, it depends on the vendor:

Anthropic, Claude Code: According to Air, Anthropic confirmed the fix on 17 June 2026 with Claude Code 2.1.179. But know this: the release notes for 2.1.179 don't mention this fix. The "it's fixed" information comes from Air.

OpenAI, Codex: Here the paperwork is in order. In the openai/codex repo, pull request number 34644, titled "Verify Git plugin SHA checkouts", was merged on 22 July 2026. What it does is exactly what should be done: after checkout, if the resolved HEAD doesn't match the pinned SHA exactly, it rejects the plugin source. Air confirmed on 12 August that Codex 0.146.0 is fixed. A fix whose code you can read out in the open is always more convincing than silence in a release note.

GitHub Copilot (Microsoft): As of mid-September there's no published fix. Air says it reported it in June. Microsoft didn't respond to The Register's request for comment. We couldn't check the situation after mid-September either, so I can't tell you anything certain about Copilot today.

Google, Gemini CLI: On 4 August Google said it would not ship a fix. It announced that it has deprecated Gemini CLI and is pointing users to Antigravity, which it says is protected. The Gemini CLI service for individual users ended in June 2026, but enterprise access carries on. Whether enterprise users will get a fix is unclear. (A tool sent into retirement, with its door left open. Around here we call that selling the house and leaving the key under the doormat.)

As of 18 September, no CVE number has been assigned to the hole. None of the four vendors has published a security advisory. And there's no known real-world attack.

GitHub's objection and the "zero-click" debate

The story was carried between 17 and 19 September by The Register, CSO Online, The Next Web and a research note from the Cloud Security Alliance. All of them repeated Air's framing as is: zero-click remote code execution (RCE: Remote Code Execution), the first attack of its kind on the AI supply chain. I suggest you read that framing with a bit trimmed off. Let me explain why.

First, the branch-name method only works on servers that allow hash-looking branch names: Bitbucket and git servers you set up yourself, for example. GitHub rejects such names. A GitHub spokesperson told The Register that this blocks exploitation on GitHub. Air disagrees, because marketplaces can be hosted elsewhere too. Air also argues that GitHub's rule doesn't explicitly block a branch named FETCH_HEAD. The Hacker News's report adds an important detail: every plugin in Anthropic's community catalogue, and those in the default catalogues of Claude Code and Copilot, point to GitHub. So the real-world danger narrows down mainly to marketplaces sitting on Bitbucket or on someone's own server.

Second, the "zero-click" claim. Air says that in Claude Code and Codex, automatic background updating of plugins is on by default, so disguised code can be installed without the user doing anything. Anthropic's and GitHub's documentation, however, say automatic updates are on by default only for the built-in, GitHub-hosted marketplaces. That's why the "zero-click" claim is debatable for third-party marketplaces. Going by the docs, the place where the branch-name trick works and the place where automatic updates are on by default don't overlap much.

Third, who's doing the talking. Air is a company selling its own products (Air Marketplace and Air Filter). In their write-up they also mention that organisations using those products weren't affected. The line "millions of agents affected" is Air's own estimate, too. The finding is serious and real, I'm not arguing with that. But at the end of the day what you're reading is a vendor's post, so keep that in a corner of your mind.

The real lesson: an unchecked seal is just decoration

What makes me think hardest about this hole is how simple it is, technically. The whole point of pinning is being able to say "what I have is the same as what was reviewed". The agents read the seal, but never checked whether the package matched it. The proposed fix is a one-line idea, too: after checkout, compare the resolved HEAD with the pinned SHA, and if they differ, stop. The marketplace can't do this, because it never sees where the code gets checked out. The check HAS TO live inside the agent. And that's exactly what Codex's merged fix does.

Then there's one more question to ask: does a plugin that's already installed and already disguised get cleaned up after the update, or does the update only block swaps from here on? None of the sources answers this. I'm not going to claim I know what I don't. Until the vendors write something about it, check your installed plugins yourself.

So what are you going to do?

Well, don't panic just yet. But don't sit on your hands either:

  • Update your agent. Bring Claude Code to 2.1.179 or later and Codex to 0.146.0 or later. You can't have a reason to stay below those two versions.
  • If you use Gemini CLI (especially on the enterprise side), know that you're working with a tool whose vendor says it won't ship a fix. Don't take plugins from third-party marketplaces, or give up the tool.
  • If you use Copilot, I'd suggest you don't take plugins from marketplaces outside GitHub until Microsoft announces a fix.
  • Look at where your marketplace lives. If you've added a marketplace hosted on Bitbucket or on your own git server, turn off automatic updates there. Update by hand, looking at what changed.
  • Don't leave your credentials lying around where the agent can reach them. This goes for every plugin, not just Plugin4Shell.
  • And most important of all: before you open a project to an agent, you MUST have a backup. The agent runs code in your place, and it deletes in your place too.

If you ask me, the cleanest part of this whole affair is the Codex side: the fix is public, its code can be read, what it does is clear. The darkest part is Gemini CLI. Deprecating a tool doesn't close its hole, it just announces that you won't be closing it. As for Claude Code, stuck in the middle: there seems to be a fix, but we're learning about it from the researchers, not from Anthropic's release notes. Telling users about a security fix should be part of the fix as well.

That's all from us. If you run into anything odd while going through your installed plugins, write to us (yes, I'm saying letters, but we'll settle for e-mail). See you next month, take care!

Sources

Contents · Issue 01 · September 2026