Security

Plugin4Shell: A Pinned Coding-Agent Plugin Is Not Always Pinned

Plugin4Shell is a flaw in how four AI coding agents check out plugins pinned to a commit. Someone who controls a plugin's repository can name a branch after the pinned commit, so Claude Code, OpenAI Codex, GitHub Copilot and Gemini CLI fetch different code while the pin still looks honored. Claude Code 2.1.179 and Codex 0.146.0 carry fixes.

Plugin4Shell is the name Air Security gave to a flaw in how four AI coding agents install plugins that are pinned to a specific commit. Someone who controls a plugin’s repository can make the agent fetch different code while the pin still looks honored. The researchers named Claude Code, OpenAI Codex, GitHub Copilot and Gemini CLI. They published on September 17, 2026, after disclosing to the vendors in June.

This piece explains the trick in plain terms, where each agent stands, when it needs no click at all, and what an agency can check and change. It also lists what we could not confirm, because two of the four vendors have said little in public.

The short version: update Claude Code to 2.1.179 or later and Codex to 0.146.0 or later. Air Security reports no fix for GitHub Copilot as of its write-up, and Google is retiring Gemini CLI for most users rather than patching it. For every agent, the practical defense is the same: control who can add plugin sources, and know which repositories your pins point at.

How Plugin4Shell gets past a commit pin

A plugin marketplace is a catalog file. Each entry says where to fetch a plugin, often a Git repository. To stop a plugin from changing under you, the catalog can pin it to a full 40-character commit hash. If you are new to what these plugins bundle, our explainer on what AI skills are covers the building blocks.

The pin is meant to be a promise. That exact commit, and nothing else, gets installed. GitHub’s own Copilot CLI plugin reference describes a pinned install as immune to force-pushes and branch moves.

According to Air Security’s write-up, the agents checked out the pinned hash but never confirmed what they got. The attacker creates a branch whose name is the pinned hash itself, then makes it the repository’s default branch. When the agent runs git checkout with the hash, Git picks the branch. The working copy now holds the attacker’s code, and the pin still reads as honored.

Gemini CLI took a slightly different path, per the researchers. It fetched the pinned commit and then checked out FETCH_HEAD. A default branch literally named FETCH_HEAD won that lookup instead.

The attacker has to control the plugin’s repository. That can be a plugin author gone bad, a stolen maintainer account, or a repository that changed hands. The marketplace itself can be perfectly trustworthy.

Plugin4Shell status by agent

The table reflects what Air Security reported and what we could match against vendor pages on September 27, 2026.

Agent Fixed version What we could confirm
Claude Code 2.1.179 Release dated June 16 on GitHub; its notes do not mention the fix
OpenAI Codex 0.146.0 Public change “Verify Git plugin SHA checkouts” in the 0.146.0 changelog
GitHub Copilot None reported No changelog entry found that verifies the checked-out commit
Gemini CLI None planned Google moved consumer users to Antigravity CLI in June

Air Security’s timeline runs as follows. It found the flaw in May 2026 and disclosed it to all four vendors in June. Anthropic confirmed its fix on June 17. Google confirmed on August 4 that Gemini CLI is deprecated and will not be patched. Air Security verified the Codex fix on August 12.

No CVE identifier appears in the write-up. The Hacker News reported that, as of September 18, none had been assigned and none of the four vendors had published an advisory. We found none either in the pages we read.

Claude Code: fixed in 2.1.179, quietly

Air Security lists Claude Code 2.1.179 as the fixed release and says Anthropic confirmed the fix on June 17. The 2.1.179 release on GitHub is dated June 16. Its nine notes cover connection drops, scrolling and plugin loading speed. None describes the pin check.

That gap matters for anyone who reads release notes to decide when to update. This Plugin4Shell fix arrived without a line saying so. We have only the researchers’ account and Anthropic’s confirmation to them for the version number.

Claude Code has moved well past that release. Its changelog listed 2.1.283 at the top when we checked. Any install that auto-updates normally is far beyond the fix. The risk sits with pinned installs, container images and CI runners that were frozen before mid-June.

Claude Code’s marketplace reference documents the sha field on github, url and git-subdir plugin sources. It must be a full 40-character lowercase commit hash, and when both ref and sha are set, Claude Code checks out the sha.

OpenAI Codex: fixed in 0.146.0, in the open

OpenAI’s fix is public. Pull request 34644, titled "Verify Git plugin SHA checkouts," was merged on July 22. Its description says Git can treat a requested commit hash as a branch name when the remote’s default branch has that name. The change resolves HEAD after checkout and rejects the plugin source if it does not exactly match the pinned hash.

That is the check Air Security recommends against Plugin4Shell. The PR description does not credit the researchers or call it a security report.

The Codex 0.146.0 release lists the PR in its changelog. The release page is dated July 29. Air Security says it verified the fix on August 12.

Codex also has a workspace path for organizations. According to OpenAI’s plugin management page, workspace admins can import a plugin marketplace from GitHub. Git sources can select a ref or a full 40-character commit sha. New marketplaces check for updates daily by default.

GitHub Copilot: no fix reported, and the Git host matters

Air Security says it disclosed the flaw to Microsoft, which has not shipped a fix. Help Net Security’s September 18 coverage carries the same account. We found no GitHub or Microsoft advisory.

The Copilot CLI changelog shows plugin pinning is recent. Entries from July and August 2026 list pinning with a sha field to plugin sources, after the researchers’ June disclosure. We found no entry that verifies the checked-out commit afterward.

There is a real limit on the branch trick, and it favors GitHub. GitHub’s documentation says it does not allow branch or tag names that look like Git object IDs. So a plugin repository on GitHub.com cannot carry a branch named after a 40-character hash. The Hacker News reported the same limit, citing that documentation.

GitLab has a similar rule. A GitLab issue records that it added validation to block 40-character hex branch names for this class of conflict.

The gap is everywhere else. The Hacker News and The Next Web both name Bitbucket and self-hosted Git servers as hosts that accept such names. Copilot CLI’s url source type accepts any Git URL, so a marketplace entry can point off GitHub. The FETCH_HEAD variant is not hash-shaped at all, so a rule about hash-shaped names does not address it.

Gemini CLI: retired for most users, not patched

Google’s May 19 announcement said Gemini CLI would stop serving requests on June 18, 2026 for free tier users and Google AI Pro and Ultra subscribers. Extensions carry over as Antigravity plugins. Air Security says Google confirmed on August 4 that Gemini CLI will not be patched, and advised moving to Antigravity.

One group does not fit that story. The same announcement says organizations using Gemini CLI through a Gemini Code Assist Standard or Enterprise license keep their access, with continued support. We found no Google statement on whether those supported installs will get a Plugin4Shell fix. If a client uses Gemini CLI that way, ask Google directly.

For the wider move, our post on the Gemini CLI to Antigravity CLI transition covers what changed.

When Plugin4Shell needs no click

Air Security calls Plugin4Shell zero-click. The trigger is plugin auto-update. When a pinned commit changes, the agent fetches it in the background, with no prompt. The write-up says this is the default in Claude Code and Codex.

The vendor documentation adds detail. Claude Code’s plugin loading reference says auto-update is on by default for Anthropic’s official marketplaces, and off for most other marketplaces. An admin or user can turn it on for any marketplace. Copilot CLI updates plugins from its built-in marketplaces at session start in a trusted folder, and custom marketplaces can opt in.

So the no-click path depends on settings. A fresh install is still a code fetch, just one a person starts. Either way, an agent with an unpatched checkout routine installs whatever the plugin repository serves.

This sits next to the GitSpawn flaw we covered in September. There, a handed-over repository could run code at agent startup. Here, the code arrives through the plugin channel. Both treat the agent’s own setup as the attack surface.

What agencies should do about Plugin4Shell now

Most agencies serving nonprofits and associations run these agents on a handful of laptops, a CI runner or two, and maybe a shared container image. The steps below match what the vendors document today.

  • Update the agents: Claude Code to 2.1.179 or later, Codex to 0.146.0 or later. Check frozen installs in Docker images and CI, not only laptops.
  • Treat Copilot and Gemini CLI as unpatched: until a vendor says otherwise, limit their plugins to sources you control.
  • Restrict who can add plugin sources: in Claude Code, the managed strictKnownMarketplaces allowlist and blockedMarketplaces blocklist decide which marketplace sources plugins may come from. disableSideloadFlags blocks loading plugins from a local folder or URL.
  • Decide auto-update on purpose: Claude Code lets a managed marketplace entry set autoUpdate so users cannot flip it. Copilot CLI honors COPILOT_AUTO_UPDATE=false.
  • Review what is installed: claude plugin list and Copilot’s /plugins view show what each machine has.

The full list of Claude Code keys is on its plugin management page for organizations.

Where admin-level pinning helps

Pinning in the admin console is documented for two of the four agents. Codex workspace admins can pin an imported marketplace to a 40-character commit hash. Copilot CLI says a plugin or marketplace pinned by an organization or MDM policy cannot be repointed locally. Copilot’s enterprise-managed plugins reached public preview in May for Copilot Business and Enterprise.

Claude Code’s managed settings pin marketplace sources to a ref. Plugin-level sha pins live in the marketplace file itself, so whoever maintains that file sets them.

Keep one limit in mind. Pinning the catalog controls when the catalog changes. A plugin entry inside it can still point at someone else’s repository. Air Security’s argument is that no marketplace fully closes this, because the check has to happen in the agent. That is why the version updates come first.

If you already manage agent settings in version control, this fits the practice we described in agent configuration management. The allowlist belongs in the same reviewed file as everything else.

Checking your plugin repositories for Plugin4Shell branches

You can look for the trick directly. For each Git repository a pinned plugin entry references, list its branches and its default branch:

git ls-remote --symref https://example.com/team/plugin.git HEAD
git ls-remote --heads https://example.com/team/plugin.git

Look for two things. A branch whose name is 40 hex characters, and a branch named FETCH_HEAD. Neither has a normal reason to exist. On GitHub.com and GitLab the hash-shaped name should be refused already, so focus on Bitbucket, self-hosted servers and anything else.

If you build plugin caches for containers or CI with your own scripts, add the check Air Security recommends. After checkout, compare git rev-parse HEAD with the pinned hash and stop if they differ. The same habit applies to any pipeline that installs third-party code, as our coverage of the npm supply chain reaching build servers showed.

What is still unconfirmed about Plugin4Shell

Several points rest on one source, so treat them as reported rather than settled.

Open questions as of September 27, 2026. Anthropic has not described the 2.1.179 fix in public. GitHub and Microsoft have published no advisory or fix. Google has not said whether Gemini CLI installs under Code Assist Standard or Enterprise licenses will be patched. No CVE has been assigned that we could find.

Air Security’s headline says "millions of agents" were affected. The write-up gives no basis for that figure, so we have left it out of our own framing. Air Security also sells marketplace products and says their customers were not affected. We have not tested that claim.

Frequently Asked Questions

What is Plugin4Shell?

Plugin4Shell is Air Security’s name for a flaw in how AI coding agents install plugins pinned to a commit. A person who controls the plugin’s repository can make the agent check out different code while the pin still appears honored. It was published on September 17, 2026.

Which AI coding agents did Air Security name?

Claude Code, OpenAI Codex, GitHub Copilot and Gemini CLI. The write-up does not say which Copilot surface it tested. The documented plugin pinning we found is in Copilot CLI.

Which versions fix Plugin4Shell?

Claude Code 2.1.179 and Codex 0.146.0, per Air Security. Codex’s fix is visible in its public changelog. Claude Code’s release notes for 2.1.179 do not mention it. Air Security reported no fix for Copilot, and none is planned for Gemini CLI.

Does an attacker need to hack the marketplace?

No. The attacker needs control of the plugin’s own repository. A trusted marketplace can list a plugin whose repository later changes hands or loses a maintainer account.

Is a plugin hosted on GitHub.com safe from this?

From the hash-named branch trick, largely yes. GitHub’s documentation says it does not allow branch names that look like Git object IDs. That rule does not cover the FETCH_HEAD variant used against Gemini CLI, and plugins on other hosts are not covered by it.

Does Plugin4Shell have a CVE?

Not that we could find as of September 27, 2026. The Hacker News reported none assigned and no vendor advisory as of September 18.

Why is it called zero-click?

Because plugin auto-update can fetch a changed plugin in the background with no prompt. Whether that happens depends on each marketplace’s auto-update setting. A first install is still a fetch that someone starts.

Should we turn off plugin auto-update?

It depends on where your plugins come from. For marketplaces you do not control, turning it off means changes arrive only when someone chooses. In Claude Code, the fleet-wide switch DISABLE_AUTOUPDATER also stops Claude Code’s own updates, which is how security fixes like this one arrive. Setting autoUpdate per marketplace is the narrower option.

We still use Gemini CLI under a Code Assist license. What now?

Google says those licenses keep access and support. We found no statement on a Plugin4Shell fix for them. Limit plugins to repositories you control and ask Google for its position.

What can a small agency check in an afternoon?

Confirm every agent install, image and CI runner is on a fixed version. List the marketplaces each machine uses. For plugin repositories outside GitHub.com and GitLab, run git ls-remote --heads and look for branches named with 40 hex characters or FETCH_HEAD.

Digital Matters

Security Desk