AI agents · OpenClaw · self-hosting · automation

Quick Answer

What Is Plugin4Shell? Zero-Click RCE in AI Coding Agents

Published:

The short version

Plugin4Shell is a plugin SHA-pinning bypass in the four most-used AI coding agents — Claude Code, OpenAI Codex, GitHub Copilot and Gemini CLI — disclosed by AIR Security on September 18, 2026. The agents check out the exact commit a marketplace pinned but never confirm the checkout landed there. An attacker who controls the plugin’s repository can make git resolve that pin to a branch of malicious code while the pin still looks honoured. Because plugin auto-update runs in the background (the default in Claude Code and Codex), the swap reaches already-installed plugins with no click, no prompt and nothing to notice.

AIR calls it “the first supply chain vulnerability of the AI agent ecosystem.” Previous agent-security research attacked the model or the agent; Plugin4Shell attacks the distribution layer underneath them.

Status by agent (September 19, 2026)

AgentVendorVariantFixStatus
Claude CodeAnthropicBranch named as pinned SHAPatched in 2.1.179Update
CodexOpenAIBranch named as pinned SHAPatched in 0.146.0Update
GitHub CopilotMicrosoftBranch named as pinned SHANo patch shippedExposed
Gemini CLIGoogleDefault branch named FETCH_HEADNot patched — tool deprecatedExposed indefinitely; move to Antigravity

AIR found the bug in May 2026, built working proof-of-concept exploits against all four agents, and disclosed to each vendor in June 2026. Three months later two vendors have shipped fixes, one has not, and one retired the product instead.

How the bypass works

SHA pinning is supposed to be the end of the rug-pull problem: review a plugin at one commit, pin that commit, and trust that only that code will ever run. Plugin4Shell shows the pin is written but never enforced.

Variant 1 — the pinned commit becomes a branch (Claude Code, Codex, Copilot)

These agents install a plugin with the equivalent of:

git clone <plugin repo> ./
git checkout aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

The attacker, who controls the upstream repository, creates a branch whose name is the 40-hex pinned SHA and makes it the repository’s default branch. The clone brings that branch down locally. When a name is both a valid ref and an object id, git prefers the ref and only prints a “refname is ambiguous” warning. The working tree is now attacker-controlled, and the agent reports a successful install at the pinned commit.

Two conditions make this work: the host must allow a branch to be named like a hash, and the branch must be the default. GitHub rejects 40-hex branch names outright; Bitbucket and any self-hosted git server allow them, and Anthropic’s own documentation lists both as supported marketplace backends.

Variant 2 — the pin is fetched but never checked out (Gemini CLI)

Gemini CLI pins with --ref in three steps: a shallow clone, git fetch origin <sha>, then git checkout FETCH_HEAD. The fetch retrieves the right commit, but if the repository’s default branch is itself named FETCH_HEAD, the checkout resolves to the branch and silently discards the fetched commit.

The five-step attack

  1. Plant — publish a genuinely benign plugin pinned at commit aaa…. It passes review.
  2. Adoption — users install it, each pinned to the reviewed commit.
  3. Version bump — ship a routine, still-benign update; the marketplace re-pins to bbb….
  4. Rug-pull — create a branch named bbb…, make it the default, point it at malicious code. The real commit can stay untouched.
  5. Auto-update to RCE — the changed pin triggers every agent’s background update; the checkout resolves bbb… to the branch, and it runs.

The attacker does not need to persuade anyone to install anything new. They only need a benign plugin to already be there — and AIR has shown that step is easy: a plugin it built spread to 26,000 agents before being pulled, and its SkillJacking research found 925 skills already in use had been hijacked from their maintainers, reaching 134,000 agents.

Why a marketplace cannot fix this alone

The pin is resolved inside the agent, on the developer’s machine. A marketplace can blunt the branch-name variant by only allowing GitHub-hosted plugins, but that bans backends the agents officially support and does nothing for Gemini CLI’s FETCH_HEAD variant. The only complete fix is one assertion inside the agent after checkout:

test "$(git rev-parse HEAD)" = "<pinned-sha>" || abort

It has to check the resolved HEAD, not the ref that was requested — that distinction is exactly what the Gemini variant slips through.

What to do today

  • Claude Code: run claude --version; anything below 2.1.179 is vulnerable. Update.
  • Codex: anything below 0.146.0 is vulnerable. Update.
  • GitHub Copilot: no patch. Disable or remove marketplace plugins you do not strictly need; treat auto-updates as untrusted until Microsoft ships a fix.
  • Gemini CLI: Google’s guidance is to migrate to Antigravity, which was built without the plugin-pinning mechanism this attack relies on. Every remaining install stays exposed.
  • Everyone: turn off background plugin auto-update until you have confirmed your version, prefer GitHub-hosted marketplaces, and if you maintain a plugin, enable branch protection and 2FA on the repository — takeover of the upstream repo is the precondition for both attack paths.

For the broader hardening checklist — pinning, allow-lists, sandboxing and auto-update policy — see the companion guide on securing AI coding agent plugins and skills.

Sources