.png)
Plugin4Shell - Zero Click RCE Vulnerability found in top 4 most popular coding agents, millions of agents affected
Air Security researchers found that AI coding agents (Claude Code, Codex, GitHub Copilot, Gemini CLI) that SHA-pin plugins from marketplaces never verify the checked-out commit actually matches the pin, letting an attacker who controls a plugin's upstream repo create a branch named after the 40-hex SHA (or, for Gemini CLI, named FETCH_HEAD) so git resolves the ref to attacker-controlled code instead of the pinned commit. Because agents auto-update plugins in the background, this yields zero-click RCE against already-installed, previously-vetted plugins even when marketplaces do everything the pinning security model asks; Anthropic and OpenAI patched after disclosure, Microsoft has not patched GitHub Copilot, and Google will not patch the deprecated Gemini CLI.
What to do
The summary states who patched but not the version boundaries or the fix. Update to at least:
- Claude Code — 2.1.179 (Anthropic patched after disclosure)
- Codex — 0.146.0 (OpenAI patched after disclosure)
- GitHub Copilot — Microsoft has shipped no fix; no patch available.
- Gemini CLI — deprecated, will not be patched; migrate to Antigravity, which has no marketplace plugin SHA pinning and so is not reachable by this attack.
The page gives the one-line agent-side assertion that closes both variants — it must run after checkout and compare the resolved HEAD, not the requested ref:
test "$(git rev-parse HEAD)" = "<pinned-sha>" || abortHow it works (detail the summary omits)
The vulnerable install sequence is a plain clone plus checkout:
git clone <plugin repo> ./
git checkout aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaWhen a name is both a valid ref and an object id, git prefers the ref, emitting only a refname is ambiguous warning — so a default branch named as the 40-hex SHA wins over the actual commit. The branch-name variant only works where a host allows 40-hex branch names: git check-ref-format accepts them, Bitbucket and self-hosted git allow them, GitHub rejects them outright. Anthropic's own docs list Bitbucket and self-hosted git as valid marketplace backends, so this is a supported configuration, not an edge case.
Gemini CLI's variant differs — it fetches the right commit into .git/FETCH_HEAD but git checkout FETCH_HEAD resolves to a default branch literally named FETCH_HEAD if one exists, discarding the fetched commit.
Preconditions
The victim only needs a previously-vetted, marketplace-pinned plugin already installed. Background auto-update — the default in Claude Code and Codex — re-runs the same checkout when the marketplace bumps the pin, making it zero-click. The attacker needs control of the plugin's upstream repo (via Method 1: publish-then-poison, or Method 2: repo takeover), not the marketplace.
Caveats
A marketplace cannot fully close this — the pin resolves client-side. A marketplace can blunt the branch-name variant by allowing GitHub-only hosts, but that bans officially-supported backends and does nothing for the Gemini FETCH_HEAD variant. (The "Air Marketplace/Air Filter customers unaffected" and demo pitch are vendor framing.)
Organisations named here
- Plugin4Shell
- RepoJacking
- The Story of Skills
Technologies named here
- Air Marketplace
- Claude Code
- OpenAI Codex
- Air Filter
- GitHub Copilot
- git
- Gemini CLI
- Google Antigravity
- Codex
Techniques named here
- Plugin4Shell - FETCH_HEAD checkout bypass
- Zero-click compromise via plugin auto-update
- Method 1
- Method 2
Threat actors named here
- SkillJacking
Related in AI Security
