Plugin4Shell: Zero-Click RCE in 4 AI Coding Agents
Your coding agent pins every plugin to an exact commit hash. You reviewed that plugin three months ago. Nothing about the pin has changed since — and yet the code running on your machine this morning is not the code you reviewed.
That is Plugin4Shell in one sentence: a SHA-pinning bypass disclosed by Air Security on September 17, 2026, that turns four of the most widely used AI coding agents — Claude Code, Codex, GitHub Copilot, and Gemini CLI — into zero-click remote code execution targets through the one mechanism teams trusted most, the marketplace pin.
The researchers (Or Nevo, Dor Granat, and Niv Hoffman) describe the blast radius as millions of installed agents. Two of the four vendors had already patched months before the public write-up. One had not. And the fourth will never patch at all. Below: how the bypass works, exactly which versions are safe, and what to do today.
What Plugin4Shell breaks
Plugin marketplaces solved a real problem. Instead of pasting random install scripts from the internet, developers install plugins from a curated marketplace that records — pins — the exact commit the plugin was reviewed at. The agent is supposed to check out precisely that commit, every time, forever.
Plugin4Shell breaks the verification step, not the pin itself. Per Air Security’s disclosure:
The agent checks out the exact commit the marketplace pinned but never verifies it landed there.
The pin is still displayed. It still looks honored. The checkout just silently resolves somewhere else — to code the attacker controls. Every defense built on top of the pin (review gates, allowlists of pinned plugins, audit logs showing the pinned hash) keeps reporting green while the wrong code executes.
What you see What actually runs
───────────────────── ──────────────────────
marketplace pin: abc1234 ──→ checkout resolves to
"verified, reviewed" attacker's branch "abc1234"
audit log: pin honored pin display unchanged
If you have followed the MCP tool-poisoning story, the shape of this bug will feel familiar: the trust boundary nobody drew, except this time it is the install path rather than the description field. And if you have ever debugged a failed MCP server connection in Claude Code, you already know how much machinery sits between the agent and the thing it thinks it connected to. Plugin4Shell lives in exactly that kind of gap.
The two variants
Air Security demonstrated two ways to make a checkout resolve to the wrong code.
Variant 1: the hash-named branch (Bitbucket and self-hosted git). Git resolves ambiguous references with fallback rules, and the agent’s checkout command leans on those defaults instead of forcing an exact-commit resolution. The attacker creates a branch whose name is byte-identical to the pinned commit hash. When the agent fetches, the branch shadows the commit, and the checkout lands on the attacker’s branch. The pin string in the UI never changes.
Variant 2: the FETCH_HEAD branch (Gemini CLI). The agent’s install path fetches a ref literally named FETCH_HEAD. The attacker names the repository’s default branch FETCH_HEAD, so the fetch that was supposed to retrieve trusted content instead retrieves whatever the attacker’s default branch points at. It is the same class of mistake — trusting a name that the other side gets to choose — wearing a different hat.
Neither variant requires the victim to install anything new. That is what makes this a supply-chain bug rather than a phishing bug: the compromise happens upstream, in a repository the developer already trusted, and flows downhill through normal updates.
Why it is zero-click
Several of the affected agents auto-update installed plugins by default. That single product decision converts the bypass from “sophisticated” to “zero-click”:
- Months ago, a plugin passes marketplace review at commit
abc1234. You install it. - Later, the attacker gains control of that plugin’s upstream repository (compromised maintainer account, transferred repo, expired-domain takeover — the usual supply-chain routes).
- The attacker plants the hash-named branch or the
FETCH_HEADdefault branch. - Your agent’s next silent auto-update checks out
abc1234, lands on attacker code, and runs it with whatever permissions your coding agent holds — shell, filesystem, network, credentials.
Steps 2–4 involve zero action from you. No new install, no approval dialog, no diff to review. A plugin that was clean when you vetted it becomes the delivery vehicle, which is precisely why pinning existed in the first place — and precisely why a bypass of the pinning check is worse than no pinning at all, since it suppresses the suspicion the update would otherwise deserve.
Who is patched and who is not
| Agent | Status as of Sept 17, 2026 | Action |
|---|---|---|
| Claude Code (Anthropic) | Fixed in 2.1.179 (June 17, 2026) | Update to 2.1.179 or later |
| Codex (OpenAI) | Fixed in 0.146.0 (verified Aug 12, 2026) | Update to 0.146.0 or later |
| GitHub Copilot | No patch at disclosure | Treat plugin updates as untrusted until Microsoft ships a fix |
| Gemini CLI | Will never be patched — deprecated | Migrate to Antigravity per Google |
Three things worth noting in that table.
First, the timeline is what coordinated disclosure is supposed to look like: private report, vendor fixes shipping weeks to months ahead of publication, public write-up only after two of four vendors are fixed. Anthropic patched in June, OpenAI’s fix was verified in August, disclosure landed September 17.
Second, the Copilot row is the acute problem. Microsoft’s own figures put Copilot in nearly 90% of Fortune 500 companies. An unpatched zero-click RCE in the plugin path of that footprint, with no patch date announced, is the item to watch in the days after disclosure.
Third, Google’s answer is the starkest: Gemini CLI is deprecated, no fix is coming, migration is the fix. If you still run it, the deprecation notice just became a security deadline.
What to do today
In priority order:
- Check your versions. Claude Code ≥ 2.1.179, Codex ≥ 0.146.0. If you manage fleets, query versions centrally — developers who installed months ago and never updated are the exposed population even for the patched agents.
- Inventory Copilot plugins. With no patch available, enumerate installed plugins on Copilot seats, note which auto-update, and consider disabling auto-update until Microsoft ships a fix. Treat any plugin whose upstream changed recently with suspicion.
- Get off Gemini CLI. There is no patch coming. Migrate to Antigravity as Google directs, and audit what the CLI had access to (shell history, checked-out repos, stored credentials) on the assumption the install path was exposed.
- Verify pins independently. Where your tooling allows it, resolve the pinned commit out-of-band (
git rev-parse, signed tags, attestations) rather than trusting the agent’s checkout success message. The lesson of Plugin4Shell is that “checkout succeeded” and “checked out the right thing” are two different claims. - Watch the registries. The same SHA-pinning gap pattern could exist in IDE extension marketplaces and MCP server registries. If vendors announce audits or pinning-verification fixes in the coming weeks, apply them — this bug class is unlikely to be unique to these four agents.
The bigger pattern
Step back and Plugin4Shell rhymes with everything else in the 2026 agent-security story. Tool descriptions turned out to be executable code. Approval dialogs turned out to be rubber stamps. Now pinned commits turn out to be display strings. In each case the industry took a concept from conventional software — documentation, confirmation dialogs, version pins — assumed it carried its old meaning inside an agent system, and learned that the agent reinterprets it as something the attacker controls.
The fixes also rhyme: verify, don’t display. Pin the resolved bytes, not the requested name. Treat every string that crosses a trust boundary — descriptions, pins, refs, branch names — as attacker-controlled input until proven otherwise.
Plugin4Shell will be remembered less for its cleverness (branch namesquatting is an old git quirk) than for its placement: at the exact choke point the ecosystem built to make plugins safe. The pin was the seatbelt. The bug is that nobody checked whether it was buckled.