Updated 06:25
Plugin4Shell: the commit Claude Code pinned was not always the one it installed
A plugin SHA-pinning bypass, made zero-click by background auto-update, fixed in Claude Code 2.1.179 and Codex 0.146.0, and by Air's account unfixed in Copilot and Gemini CLI.
On September 17, 2026, the research team at Air Security published Plugin4Shell, a flaw it found in the plugin installers of four AI coding agents: Anthropic's Claude Code, OpenAI's Codex, GitHub Copilot and Google's Gemini CLI. The authors (Or Nevo, Dor Granat and Niv Hoffman) describe it as "a plugin SHA-pinning bypass: the agent checks out the exact commit the marketplace pinned but never verifies it landed there."
Two of the four vendors have shipped fixes. According to Air, the other two have not, and will not in one case.
What the pin was supposed to guarantee
Plugin marketplaces for these agents pin each plugin to a reviewed git commit. The idea is that review happens once, at a specific SHA, and every install runs that code and nothing else. Air's write-up puts it plainly: "The industry's answer to exactly this kind of rug-pull is SHA pinning."
The bug is that the agents asked git to check out the pinned value and then trusted the result. Git can resolve the same string to something other than the pinned commit when the repository's author controls how the refs are named, and in the variants Air describes, the agent still "reports a successful install at the pinned commit." XT.PT is not reproducing the mechanics beyond that; Air's post has them, and the fix below is what matters for defenders.
The precondition is control of the plugin's upstream repository: either the attacker published the plugin themselves and got it accepted, or they took over a legitimate author's repository. Neither path requires control of the marketplace. Air notes that one variant depends on the git host: "GitHub rejects a 40-hex branch name outright - while others, Bitbucket among them, and any self-hosted git server, allow it."
Why it is called zero-click
Background plugin updates. Air's words:
What makes it 0-click is plugin auto-update. Agents update installed plugins in the background - in Claude Code and Codex this is the default - so when the pinned commit is swapped upstream, a plugin the user already trusts and already has installed is replaced with a malicious version without any user interaction: no install step, no prompt, nothing to notice.
Air Security, "Plugin4Shell"
The uncomfortable part for careful organizations is that the pin itself was the control. "Organizations that go beyond a community marketplace - reviewing plugins and pinning them to a reviewed commit - rely on SHA pinning as their safeguard, and Plugin4Shell quietly nullifies it," the post says.
Who fixed it, and how you would know
Air's disclosure timeline: found in May 2026 with a working proof of concept against all four agents, disclosed to all four vendors in June, then:
- Claude Code: "2026-06-17 Anthropic confirms the fix in Claude Code 2.1.179." The npm registry records 2.1.179 as published on 2026-06-16. Its changelog entry lists nine items (connection drops, WSL2 scrolling, sandbox globs, plugin loading performance in remote sessions) and none of them mentions plugin checkout verification or a security fix.
- Codex: "2026-08-12 Codex 0.146.0 verified fixed." The 0.146.0 release on GitHub, published 2026-07-29, does name it in its pull-request list: "#34644 Verify Git plugin SHA checkouts."
- GitHub Copilot: Air says it "disclosed the same flaw to Microsoft, which has not shipped a fix, so users have no patch." XT.PT found no Microsoft statement on this.
- Gemini CLI: Air says "Google has deprecated the Gemini CLI and will not patch it," citing a 2026-08-04 response. XT.PT could not find that position in a Google document. On 2026-09-22 the
google-gemini/gemini-clirepository on GitHub was not archived, its README carried no deprecation notice, and it had received a push that day. Treat the "will not patch" claim as Air's account of a private exchange.
The Claude Code gap is the one to note. A reader auditing a fleet by changelog would not have found this fix in the entry for the version Air names.
What to do
Air's recommended remedy is on the agent side, because, in its words, "the pin is resolved on the client, so no marketplace can enforce the guarantee it advertises." The check it proposes is a post-checkout assertion that the working tree's resolved HEAD equals the pinned SHA:
test "$(git rev-parse HEAD)" = "<pinned-sha>" || abort
For operators:
- Update Claude Code to 2.1.179 or later and Codex to 0.146.0 or later. Both are months old now; anything current is past them.
- For Copilot and Gemini CLI, treat marketplace plugin auto-update as untrusted until a vendor fix is documented. Reduce installed plugins to the ones you need, and prefer plugins whose repositories you, or someone you trust, control.
- If you run an internal marketplace, prefer GitHub-hosted plugin repositories for now. Air notes that hosting only on hosts that "reject SHA-shaped names" blunts the branch-name variant, while warning that it "does nothing for Gemini CLI's variant."
Air also sells a marketplace product it says was not affected, and the post says so twice. The disclosure's claims about vendor fixes are checkable for Anthropic and OpenAI through their release records; the claims about Microsoft and Google rest on Air's word.
Primary sources: Air Security, "Plugin4Shell", Claude Code CHANGELOG, npm registry: @anthropic-ai/claude-code, OpenAI Codex rust-v0.146.0 release, google-gemini/gemini-cli repository, read 2026-09-22.