Abstract technical illustration on a dark navy field: a tall translucent boundary plane stands at the left edge, drawn as a thin pale outline with a frosted fill. A single white line crosses it and runs to the right through four identical glowing cyan modules arranged in a shallow arc, each carrying an identical white hexagonal badge floating above it. The third module has shifted half a step to the left, leaving a faint pale ghost outline where it previously sat, and the hexagonal badge above it glows amber. No text, people or organisation logos appear. The OrcaRouter logo is composited in the bottom-right corner.
AI Safety Incidents

Plugin4Shell: Four AI Coding Agents Trusted a Pin They Never Checked

Author

Alistair Wren

Date Published

Latest models · 20View all models →
Benchmarks: Artificial Analysis · updated daily
Back to all posts

On 17 September 2026, AIR Security, a startup that builds security tooling for enterprise AI agents, published research describing Plugin4Shell — a zero-click remote code execution flaw in four AI coding agents: Anthropic's Claude Code, OpenAI's Codex, GitHub Copilot and Google's Gemini CLI. The bug is not in any model. It sits in the git checkout each agent performs when it installs a plugin, and in the fact that none of the four verified that the code it received was the code it had pinned. Two of the four had a patch by the time the research went public. Two did not. This incident is one entry in the Orca AI Incident Archive, which records it as a high-severity supply-chain vulnerability with no exploitation reported.

What the agents actually did wrong

Each affected agent installs plugins from a marketplace, and each marketplace pins a plugin to a specific git commit — a 40-character SHA — once the plugin has been reviewed. That pin is the whole security model: a reviewer approves one immutable version, and the agent is supposed to keep running that version even if the repository behind it later changes. AIR describes the flaw as a plugin SHA-pinning bypass. The agent checks out the exact commit the marketplace pinned but never verifies that the working tree it ends up with is that commit. In the researchers' words, the agent "checks out the exact commit the marketplace pinned but never verifies it landed there, so an attacker who controls the plugin's repo makes the checkout resolve to malicious code while the pin still looks honored."

Git supplies the gap. When a name is both a valid branch and a commit object, git prefers the branch and only prints an ambiguity warning. An attacker who controls the plugin's repository creates a branch whose name is exactly the 40-hex pinned SHA, points it at malicious code, and makes it the repository's default branch. A plain clone then brings that branch down locally under the SHA-shaped name, and the subsequent checkout resolves to it. The pinned commit itself can stay untouched, so nothing about the reviewed version looks wrong. According to AIR, two conditions have to hold: the SHA-named branch must be the default branch, because a non-default branch is fetched only as a remote-tracking ref and the checkout would fall back to the real commit; and the git host must accept a 40-hex branch name. GitHub rejects those names outright. Bitbucket and self-hosted git servers do not.

Gemini CLI failed by a different route. It fetched the pinned commit, recorded it in the repository's FETCH_HEAD file, and then ran a checkout of FETCH_HEAD — a checkout that does not have to read that file. A repository whose default branch is itself named FETCH_HEAD redirects the checkout to attacker-controlled content and silently discards the commit that was fetched. Cybersecurity News' account of the mechanism matches AIR's, including the distinction between the two variants.

Why nobody had to click anything

The same checkout runs again during background plugin auto-update, which is the default in Claude Code and Codex. That is what makes the attack zero-click rather than merely quiet: when a marketplace bumps a pinned SHA to a routine new version, every agent that already has the plugin installed re-runs the checkout with no prompt and no user action. AIR's point is that the victim does not have to install anything carelessly. They have to have installed one plugin, from a marketplace they trust, that was reviewed and pinned exactly as the design intends.

There are two ways to reach that position, and neither requires controlling the marketplace. In the first, an attacker publishes a genuinely benign plugin that passes review, builds an install base, ships a normal update, and only then creates the maliciously named branch. In the second, the attacker takes over the repository behind a plugin someone else wrote and that the marketplace already trusts, then pushes the malicious version out to everyone who has it installed.

The numbers behind those two routes come from AIR's earlier work, not from Plugin4Shell. In a campaign the company calls The Story of Skills, it says a plugin it built spread to more than 26,000 agents before being pulled. In SkillJacking, it reported that 925 skills already in active use had been taken over from their original maintainers, reaching 134,000 agents. AIR's headline for the Plugin4Shell post claims "millions of agents affected"; the research gives no count of exposed installations, and no third party has published one.

The timeline, and where the fixes landed

HTML card headed 'Six weeks from proof of concept to public' with kicker 'Plugin4Shell · AIR Security · disclosure sequence'. A vertical timeline in cyan lists six dated entries: May 2026, working proof-of-concept against all four agents; June 2026, coordinated disclosure to Anthropic, OpenAI, Google and Microsoft; 17 June 2026, Anthropic confirms the fix in Claude Code 2.1.179; 4 August 2026, Google confirms no fix will ship because Gemini CLI is being deprecated; 12 August 2026, Codex 0.146.0 verified fixed; 17 September 2026, AIR Security publishes the research. A seventh entry in amber marks 18 September 2026, when The Register, Help Net Security, InfoWorld and Cybersecurity News reported it. An amber box headed 'Still open at publication' records that no CVE identifier had been assigned, no vendor security advisory had been published, and no source answers whether updating an affected agent removes a plugin that has already been swapped. A footer cites the AIR Security disclosure timeline and the outlets that reported it. The OrcaRouter logo is composited in the bottom-right corner.

AIR says it found the flaw in May 2026 with working proof-of-concept exploits against all four agents, and disclosed it to each vendor the following month under coordinated disclosure. Anthropic confirmed its fix in Claude Code 2.1.179 on 17 June. Google told AIR on 4 August that no fix would ship, because Gemini CLI is being retired. Codex 0.146.0 was verified fixed on 12 August. Microsoft has not shipped a fix for GitHub Copilot.

The patch versions are the only public confirmation that the flaw was real in the two products that fixed it. Anthropic's published changelog entry for 2.1.179 lists connection-drop handling, WSL2 scrolling, sandbox glob and interface fixes, and does not mention pinning, plugin verification or a security fix of any kind. The Hacker News made the same observation, according to The Next Web's account. As of the research's publication, no CVE identifier had been assigned, and the Cloud Security Alliance's research note on the flaw repeats that no identifier existed three months after vendors were notified.

Four vendors, three different answers

HTML card headed 'One flaw, four agents, two patches' with kicker 'Plugin4Shell · vendor status at disclosure · 17 September 2026'. A four-row table gives agent, vendor, status and mechanism variant: Claude Code from Anthropic, fixed in 2.1.179 on 17 June 2026, branch named as the pinned SHA; Codex from OpenAI, fixed in 0.146.0 and verified on 12 August 2026, same branch variant; GitHub Copilot from Microsoft, no fix shipped at disclosure, same branch variant; Gemini CLI from Google, no fix and the product deprecated as of 4 August 2026, separate FETCH_HEAD variant. A note beneath reads that the branch-named-as-a-hash variant needs a git host that accepts a 40-character branch name, which GitHub does not and Bitbucket and self-hosted git do, that background auto-update is on by default only for Claude Code and Codex, and that Antigravity, the replacement Google points to, has no marketplace plugin SHA pinning to bypass. A footer cites AIR Security, The Register and Help Net Security. The OrcaRouter logo is composited in the bottom-right corner.

Google went further than declining to patch. It deprecated Gemini CLI, which means existing installations stay exposed for as long as people keep running them. Its advice is to migrate to Antigravity, the newer agentic development environment, which AIR says the attack does not reach because it has no marketplace plugin SHA pinning to bypass.

GitHub's position is different again. A GitHub spokesperson told The Register that the platform does not allow users to create branch or tag names that resemble commit SHAs, and that "this mitigation ensures the reported vulnerability cannot be exploited on GitHub." AIR disputes the scope of that mitigation rather than its existence: marketplaces can be hosted on other platforms such as Bitbucket, the researchers told The Register, and GitHub Copilot still supports marketplaces from those platforms, so the branch-name variant remains reachable for Copilot users. AIR also says Anthropic's own documentation lists Bitbucket and self-hosted git as valid marketplace backends; Anthropic's current marketplace documentation describes adding a marketplace from a git repository URL, not only from GitHub. Microsoft did not respond to The Register's request for comment, and AIR said it had received no response from Microsoft since reporting the issue in June, citing the volume of disclosures the company is handling.

This is a disagreement about the width of the exposure, not about whether the bug exists. GitHub's mitigation is a host-level restriction; AIR's finding is that the check has to happen inside the agent, because the pin is resolved on the client.

What is established, and what is not

• Established: the mechanism. AIR's write-up gives the exact git commands, the ref-over-object resolution rule, the two conditions the branch trick needs, and the separate FETCH_HEAD variant for Gemini CLI. The Register, Help Net Security, Cybersecurity News, InfoWorld and The Next Web all report it the same way.

• Established: two patched versions. Anthropic confirmed Claude Code 2.1.179 on 17 June 2026 and OpenAI's Codex 0.146.0 was verified fixed on 12 August 2026, per AIR's disclosure timeline.

• Established: two products had no patch at disclosure. Google will not patch Gemini CLI and is retiring it; Microsoft has not shipped a Copilot fix.

• Not established: independent reproduction. Every published account traces back to AIR's own blog post, and the Cloud Security Alliance's research note explicitly does not describe a third-party technical validation or independent reproduction of the exploit. The archive grades this record's confidence at B for that reason.

• Not established: how many installations were actually exposed. "Millions" is AIR's characterisation in its headline, not a measured figure.

• Not established: whether updating an affected agent removes a plugin that has already been swapped, or only prevents the next swap. No published source resolves it.

• Not established: any real-world use. No source in the record reports exploitation, probing or attacker infrastructure, and the archive records real harm as false. That is an absence of reporting, not evidence that nothing happened.

One third-party check does narrow the practical picture. The Next Web, summarising checks by The Hacker News, reports that plugins in Anthropic's community catalogue and in the default Claude Code and Copilot catalogues point at GitHub repositories, and that auto-update is on by default mainly for those built-in marketplaces. Since GitHub refuses SHA-shaped branch names, the branch-name variant is harder to reach for users who stay on the default catalogues. That reasoning does not cover Gemini CLI's FETCH_HEAD variant, which does not depend on how the host names branches.

What a fix has to look like

Abstract technical illustration on a dark navy field: a white hexagonal badge floats at the top centre, and from it a single white line descends through three translucent horizontal planes, passing through the middle of each. At the lowest plane the line passes a small hollow white ring, then splits — one branch continues straight down to a filled white dot on the plane, the other turns amber and runs off to the left, ending at a small dark unlit block that sits outside the stack. A faint pale outline of that block is drawn on the plane where it should have sat. No text, people or organisation logos appear. The OrcaRouter logo is composited in the bottom-right corner.

AIR's recommended fix is a single assertion: after checkout, resolve the commit actually present in the working tree and abort unless it equals the pinned SHA. The researchers stress that it has to check the resolved HEAD rather than the ref that was requested, because that distinction is exactly what the Gemini CLI variant slips through, and that it has to run inside the agent, because the pin is resolved on the client and no marketplace can enforce the guarantee it advertises.

Practical advice for teams running these agents, drawn from AIR, Cybersecurity News and the analyst commentary in InfoWorld:

• Update Claude Code to 2.1.179 or later and Codex to 0.146.0 or later. Updating is the only complete mitigation where a patch exists.

• Disable automatic plugin updates on any agent that has no patch. That reduces the flaw from zero-click to a manual reinstall, which is a reduction in exposure rather than a fix.

• Migrate off Gemini CLI rather than waiting for a patch that Google has said will not come.

• Audit the plugin inventory and restrict marketplace sources where possible. AIR notes that a marketplace can blunt the branch-name variant by allowing only hosts that reject SHA-shaped names, effectively GitHub-only, but that this bans hosts the agents officially support and does nothing for the Gemini variant.

• Treat the workstation as the exposure boundary. Plugins inherit the permissions of the agent, so a successful exploit reaches source code, SSH keys, cloud credentials, CI/CD tokens and internal repositories with the developer's own authority. Pareekh Jain, principal analyst at Pareekh Consulting, told InfoWorld that security teams should be looking at EDR, git, CI/CD, cloud IAM and authentication logs for unusual processes, unexpected plugin files, changed repositories and suspicious git activity — and added that these steps reduce risk without fixing the underlying flaw, which he attributes to vendor code. "Enterprises can put controls around plugin usage," he told InfoWorld, "but they cannot fix a flaw in the way the coding agent validates the code it checks out."

Why a pinning bug is the one that mattered

SHA pinning was the industry's answer to precisely the kind of takeover AIR had already demonstrated: if a public repository is compromised, the agent keeps running the audited hash instead of pulling whatever the attacker pushed. Plugin4Shell does not break the hash. It shows that the agents resolved the pin to a branch name that merely looked like the hash, and never compared the result. Everything downstream of that assumption — review processes, internal allowlists, the confidence developers place in a pinned version — inherits the failure.

What the record does not support is a claim that anything was taken. This is a vulnerability that was found and, in two of four cases, fixed; no source in it reports an intrusion, and the products that did not ship a patch are still waiting. The open question is the least satisfying one: for anyone who ran a plugin on an unpatched agent, there is no published way to tell whether the code that ran was the code they approved.