Your AI Coding Agent Pinned That Plugin to a Commit Hash. It Never Checked Where It Landed.

On September 18, 2026, Air Security disclosed Plugin4Shell: a zero-click remote code execution flaw in Claude Code, OpenAI Codex, GitHub Copilot and Gemini CLI. All four ask git for an approved commit. None of them verified they got it. Two are now patched. Two are not.

What Actually Happened

On September 18, 2026, researchers at Air Security published Plugin4Shell, a zero-click remote code execution flaw affecting the four most widely used AI coding agents: Anthropic Claude Code, OpenAI Codex, GitHub Copilot and Google Gemini CLI.

The flaw does not live in a model. It lives in two lines of git plumbing that every one of those agents got wrong in the same way.

Plugin marketplaces lock a reviewed plugin to a specific 40-character commit hash. The hash is the security control: a commit hash is content-addressed, so pinning to one is supposed to mean the code can never change underneath you. Air found that all four agents request the pinned commit and then never verify that the working tree they ended up with actually matches it.

Anyone who controls the plugin repository can exploit that gap. No click, no reinstall, no approval prompt, no new permission. The next routine auto-update is enough, and auto-update is on by default in Claude Code and Codex.

4 AI coding agents affected: Claude Code, Codex, Copilot, Gemini CLI
2 Still without a fix as of disclosure: Copilot and Gemini CLI
0 Clicks required, and zero CVE identifiers assigned at publication
134,000 Agents reached by SkillJacking, the prior study on plugin distribution scale

How SHA Pinning Was Supposed To Work

Every plugin or skill marketplace serving AI agents follows roughly the same model. A plugin is published, someone reviews it, and the approved version is recorded as a git commit hash. From then on, installs and updates reference that hash rather than a branch or a tag.

That design is borrowed straight from software supply chain security, and it is the right design. A branch moves. A tag can be re-pointed. A commit hash is derived from the content itself, so it is immutable by construction. Pin to the hash and you have pinned the code.

That is the theory. The implementation is where it fell apart.

The Exploit: Git Resolves a Name Before It Resolves a Hash

Variant 1: A Branch Named Like a Commit Hash

Claude Code, Codex and GitHub Copilot install a plugin with the pattern every developer has typed a thousand times: clone the repository, then check out the pinned commit.

# What the agent runs git clone https://<host>/<owner>/<plugin>.git git checkout 9f2c1a… # the approved 40-character SHA

The problem is what git checkout does with an argument that could be two different things. Git resolves reference names before raw object IDs. If a branch exists whose name is the same 40-hex string as the pinned commit, git checks out the branch.

So the attacker creates a branch literally named 9f2c1a... — the full approved hash — points it at malicious code, and makes it the default branch. The agent asks for the reviewed commit, git hands it the attacker's branch, the agent reports the approved version, and the malicious code executes.

Variant 2: A Default Branch Named FETCH_HEAD

Gemini CLI uses a different install path and needed a different trick. It fetches the pinned commit, then checks out FETCH_HEAD.

# Gemini CLI's install path git fetch origin 9f2c1a… git checkout FETCH_HEAD # expects the commit just fetched

Air found that a repository whose default branch is named FETCH_HEAD wins that resolution too. The checkout lands on the attacker's branch, and the correctly fetched, legitimately pinned code is silently discarded.

The Missing Line

In both variants the fix is the same single assertion after checkout, comparing what you asked for against what you actually got:

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

A Pin Is a Request. Verification Is the Control.

This is the whole bug, and it generalizes well beyond AI agents. Asking a system for a specific artifact is not a security control. Confirming that you received that specific artifact is. Package managers learned this the hard way and answered with checksums and lockfile integrity hashes; TLS learned it and answered with certificate validation. Every one of those controls exists because the request and the response are two different things, and only the second one is what you actually run. Four independent engineering teams, building four competing products, all shipped the request without the confirmation — because nothing ever failed loudly. A checkout that lands on the wrong code returns exit code zero and a clean working tree. Correctness and security diverged silently, which is exactly the failure mode that survives code review.

What the Attacker Gets

Air's framing is the one that matters operationally: a plugin runs with the same access as the person using the agent. It is not sandboxed away from your work. It is your work.

That means, at minimum:

There are two realistic paths in. Publish a clean plugin, pass review, build an install base, then turn it malicious. Or take over an existing repository that has already been reviewed and approved — an abandoned project, a lapsed domain behind a maintainer's email, a stolen maintainer credential.

Review happens once. Distribution happens every day. The whole point of pinning to a reviewed hash was to make the second one safe without repeating the first one. When the pin is never verified, approval becomes a one-time snapshot of code the repository owner can replace at any moment afterward.

Where Each Agent Stands

AgentStatusFixed In
Anthropic Claude CodePatched2.1.179 (June 17, 2026)
OpenAI CodexPatched0.146.0 (August 12, 2026)
GitHub CopilotNo fix shipped—
Google Gemini CLIWill not be patchedDeprecated; migrate to Antigravity

Air reported the findings in May 2026 and coordinated with vendors through June 2026. Public disclosure came on September 18, roughly four months later. The researchers credited are Or Nevo, Dor Granat and Niv Hoffman. No exploitation in the wild had been observed at the time of publication.

Google's position is the awkward one. Gemini CLI is being retired, so the answer to the vulnerability is a product migration to Antigravity rather than a patch. That is a defensible business decision and a bad security outcome: every installation still running Gemini CLI stays exposed permanently, and deprecated tools linger in developer environments for years.

Where Your Plugins Come From Decides Your Exposure

One detail meaningfully changes the risk picture. GitHub rejects branch and tag names that look like full commit hashes, precisely because this ambiguity in git is known. If your agent installs plugins from GitHub-hosted repositories, variant 1 does not work there.

Bitbucket and self-hosted git servers do not enforce that restriction. Neither does a plain git daemon someone stood up internally. So the practical question for your organization is not "which agent do we use" but:

If the answer to the last one is yes — and in most teams running coding agents it is — then the host-level protection you are relying on is a default that anyone can opt out of.

02
The Architecture Read

No Marketplace Can Enforce a Pin It Does Not Resolve

Air's sharpest observation is structural: the pin is resolved inside the agent, on the client, so no marketplace can guarantee it. You can build the most rigorous plugin review process in the industry, sign every approved commit, maintain an immaculate allowlist — and none of it binds, because the component that decides what code actually runs is the git invocation on the developer's laptop. That is the same lesson client-side validation taught web security twenty years ago, reappearing in an ecosystem that rebuilt its trust model from scratch in eighteen months. AI agent tooling is currently retaking the supply chain security curriculum at high speed, and it will keep arriving at the same answers the hard way: verify at the point of execution, or do not claim to have verified at all.

What is still unclear. No CVE identifiers had been assigned when the research was published, which makes this harder to track through normal vulnerability management. Air has not detailed exactly which marketplaces and plugin sources each agent resolves by default, GitHub has not published a timeline for a fix, and the patch dates in this article come from Air's own writeup and its press coverage rather than from vendor advisories. Verify against your own agent's release notes before reporting status internally.

What To Do Now

1. Update the Two Agents That Have a Fix

Claude Code to 2.1.179 or later, Codex to 0.146.0 or later. Both fixes are months old, which means the exposure in most organizations is not the vendor's patch cadence but your own rollout. Check the installed version on every developer machine, not just yours.

2. Constrain Plugin Sources on the Two That Do Not

For GitHub Copilot, restrict plugin installation to GitHub-hosted sources, where branch names shaped like commit hashes are rejected at the platform level. For Gemini CLI, treat the migration to Antigravity as a security task with a deadline, not a roadmap item.

3. Turn Off Plugin Auto-Update Where You Cannot Vouch for the Source

Auto-update is what makes this zero-click. On unpatched agents pulling from hosts that allow hash-shaped branch names, auto-update converts a reviewed plugin into a standing remote execution path. Move to a manual update workflow until the source is trustworthy.

4. Inventory Which Plugins Are Actually Installed

Most teams cannot answer this question today. Enumerate the plugins, skills and extensions loaded by every coding agent in the organization, record the source host for each, and flag every one that resolves from anywhere other than a platform you trust to enforce refname restrictions.

5. Treat the Agent's Environment as a Credential Boundary

Assume a plugin can read everything the developer can. Move secrets out of shell environment variables and into a broker that requires an explicit request, scope cloud credentials on developer machines to the minimum, prefer short-lived tokens, and alert on credentials used from unexpected contexts. This is the same control that limits the API key theft described in Anthropic's September threat report.

6. Add Agent Tooling to Your Vulnerability Management Scope

Coding agents and their plugins are production software running with developer privileges, and right now most of them sit outside the asset inventory, outside patch SLAs and outside the CVE feeds your team monitors. Plugin4Shell shipped without a CVE. If your only detection mechanism is a CVE feed, you would not have seen this at all.

The uncomfortable part is not the bug. It is how ordinary the bug is. Four well-resourced teams independently built the same plugin installer, and all four skipped the same verification step, in tooling that runs with full developer privileges on millions of machines. This is not an exotic AI failure mode. It is textbook supply chain security, rebuilt from zero by an ecosystem moving too fast to read the previous decade's incident reports.

Frequently Asked Questions

What is Plugin4Shell?
Plugin4Shell is a zero-click remote code execution vulnerability disclosed by Air Security on September 18, 2026, affecting Claude Code, OpenAI Codex, GitHub Copilot and Gemini CLI. All four agents install plugins pinned to a specific git commit hash but never verify that the checked-out code matches that hash, so anyone controlling a plugin repository can substitute malicious code while the agent still reports the approved version.
How does the attack actually work?
Git resolves reference names before raw object IDs. For Claude Code, Codex and Copilot, an attacker creates a branch whose name is the same 40-character hex string as the pinned commit and points it at malicious code, so checking out that SHA lands on the branch instead of the commit. Gemini CLI fetches the commit and then checks out FETCH_HEAD, so naming the repository's default branch FETCH_HEAD achieves the same substitution. In both cases the correct pinned code is fetched and then discarded.
Which versions are patched?
Claude Code is fixed in 2.1.179, released June 17, 2026, and OpenAI Codex in 0.146.0, released August 12, 2026. GitHub Copilot has shipped no fix. Google will not patch Gemini CLI because the tool is being retired, and points users to Antigravity instead. No CVE identifiers had been assigned at the time of publication.
Am I protected if my plugins come from GitHub?
Partly. GitHub rejects branch and tag names that look like full commit hashes, which blocks the main variant at the platform level. Bitbucket and self-hosted git servers do not enforce that restriction, so plugins resolved from those hosts remain exploitable on unpatched agents. Since many teams allow developers to add custom plugin sources, GitHub's restriction is a default rather than a guarantee.
What can a malicious plugin access?
A plugin runs with the same privileges as the person using the agent: source code in every readable repository, environment variables and the secrets in them, cloud credentials and SSH keys on the developer machine, every connected MCP server, CI runner and internal API, plus write access to the codebase itself. There is no separate sandbox between the plugin and the developer's session.
Has Plugin4Shell been exploited in the wild?
No exploitation had been observed when Air Security published the research on September 18, 2026. Air reported the findings to vendors in May 2026 and coordinated disclosure through June, giving the two vendors that patched roughly three to four months of lead time before public release. The two unpatched agents remain exposed now that the technique is public.

My Take

I have written about one line in a repository running attacker code inside seven AI coding agents and about a swarm of agents breaching 395 organizations. Plugin4Shell belongs to the same family, and the family is getting predictable: the model is never the vulnerability. The plumbing around the model is.

What makes this one worth your attention is the shape of the mistake. Nobody misunderstood cryptography here. Everybody understood that a commit hash is immutable and that pinning to one is the correct control. They just never checked that the control engaged. The padlock was closed. It simply was not holding anything.

The industry response tells you where agent tooling sits on the maturity curve. Two vendors patched within weeks of disclosure, quietly, months ago. One has shipped nothing. One decided the vulnerability is a migration prompt. That spread — in a single class of product, from a single piece of research — is what an ecosystem looks like before security expectations have settled.

Meanwhile the install base keeps growing. The prior research Air cites reached 26,000 agents from one proof-of-concept plugin, and the SkillJacking study counted 925 hijacked skills across 134,000 agents. Those are not distribution numbers you can treat casually. Every plugin marketplace serving coding agents is a supply chain, and most of them are younger than the average unpatched vulnerability.

The practical takeaway is small and boring, which is usually the sign it is the right one: find out what version your agents are running, and find out where their plugins come from. Most teams cannot answer either question today.

So — do you know which plugins your coding agent loaded this morning, and which host they came from?

Related Articles:

Kodjo Apedoh

About the Author

Kodjo Apedoh

Network Engineer & AI Entrepreneur

Founder of TechVernia & SankaraShield. Certified Network Security Engineer with 4+ years of experience specializing in network automation (Python), AI tools research, and advanced security implementations. Also builds iOS and Android applications. Holds certifications from Palo Alto Networks, Fortinet, and Cisco. Based in Arlington, Virginia.

Connect on LinkedIn →