senn-techsenn-tech
Security
Security2026-09-29· By Franz Senn

Plugin4Shell: the commit-hash pin fails when the branch is named like a hash

Coding agents install extensions, the catalogues are called marketplaces, and the recommended guard against hijacked plugin repos is the pin to a commit id instead of a branch. That exact pin is where Plugin4Shell applies, which Air Security published on 18 September 2026 and which ran wide through The Hacker News on 21 September. The mechanism in one sentence: the agent is told to check out a commit, the string looks like a hash, and on a git host that allows such names as branch or tag, the name beats the object. The user sees a checkout whose reference formally matches the pin, while the content belongs to the attacker. Zero-click, because the ordinary install path is enough for it.

Where the lever sits, and where it does not

Resolving ref names before object ids is not a git bug, it is documented behaviour: git checkout 3f2a... first means "is there a ref with this name?", and only if no, "is there an object with this id?". That makes the attack host-dependent. GitHub refuses branch names of full hash length through its naming rules, so the variant does not work there. Bitbucket and any self-run git server do not do that by default, and that is where the class sits. The Gemini CLI was caught in the report via a branch named FETCH_HEAD, the same mechanism with a name git itself reserves.

The cross-check The Hacker News supplies with the report belongs right there as well: the shipped agent marketplaces point at GitHub repos, and auto-update is on by default only for those built-in marketplaces. Anyone installing exclusively from those is, per Air Security's and GitHub's account, not affected by the branch variant. It becomes relevant with custom marketplaces, mirror repos, and every setup pulling plugins from self-run sources.

What you can check without believing anything

  1. Measure versions instead of branch folklore. claude --version and codex --version, the report's thresholds are 2.1.179 and 0.146.0. A version you did not read off is not evidence.
  2. Your own git server is the scope: Check whether your host accepts ref names in hash form. On a self-run server the answer is almost always yes, and one pre-receive hook rejecting 40-character-hex refs closes the door for the whole fleet.
  3. Install means checking the object: after checkout, git cat-file -t HEAD should return commit, and the ids must be compared, otherwise the pin is a text comparison against a string the counterparty wrote itself.
  4. Read the marketplace references: the marketplace.json files name URLs. A source you do not control and whose naming rules you do not know is where the class applies.

What remains uncertain about the report

The patch version numbers come from a press article rather than from security advisories; for three of the four agents (Copilot, Gemini CLI without fix, Claude Code without a separate advisory text) the state is therefore less load-bearing than a vendor-advisory trail. Air Security demonstrated the mechanism, an independent reproduction confirmation stood at the state when we picked it up. And the term "zero-click" describes the install path, not the whole world: it presumes the agent pulls plugins from an attackable source. For setups that do not, the report is an explanation of why the hash pin carries a naming-rule precondition. For all others it is half an hour of work on pre-receive hooks and version checks.

Further sources

Questions?
Does that make the commit-hash pin worthless?+

No, but it is only as strong as the naming rules of the git host. git first checks whether the string exists as a ref name, only then as an object. A branch named like a 40-character hash wins that order. GitHub blocks the trick on itself through its naming rules, a git server you run yourself does not do that automatically.

Which versions are patched?+

Per The Hacker News report: Claude Code from 2.1.179, OpenAI Codex from 0.146.0. For GitHub Copilot no fix existed at the time of the report, and Google leaves the Gemini CLI variant via a branch named FETCH_HEAD unpatched. All four version statements come from a press report rather than vendor security advisories, which as of 29 September 2026 needs saying.

Are there attacks in the wild?+

Per the state of the report: no. Until 18 September 2026 there was no CVE and no vendor advisory for this mechanism, and no sign of real exploitation was visible. The report describes a mechanism; a running campaign was not visible.