Plugin4Shell: Git Reference Shadowing Defeats Reviewed Plugin Pins
Air Security demonstrated that AI coding clients could install different plugin code from the commit reviewed by a marketplace. An attacker controlling an already trusted plugin repository could shadow a pinned SHA with a default branch of the same name, or shadow FETCH_HEAD in Gemini CLI. Background updates then loaded malicious code without a fresh install decision. The defect is verification of the resolved working-tree commit, not a failure to review the marketplace entry; both repository control and a compatible client/hosting path are material prerequisites.
Threat Analysis
SHA pinning is supposed to bind a reviewed plugin to one immutable Git commit. The researchers found clients that requested the pin but did not check the commit actually installed. For the background-update scenario, a benign plugin is already installed, the marketplace approves a new benign commit, and the attacker controls the plugin repository. A separate repository takeover can supply that control, but the takeover figures from other Air research are not Plugin4Shell victim counts.
Claude Code, Codex and GitHub Copilot were tested with a default branch whose 40-hex name equals the approved SHA. On compatible Git hosts, cloning creates that local branch and checkout resolves the name as a ref. The commit can remain benign while the branch tip contains malicious code. A non-default branch does not create the same local resolution behavior. GitHub's rejection of 40-hex branch names limits this variant; it does not establish that every supported host is safe.
Gemini CLI used a different route: fetch the correct pinned object, then checkout FETCH_HEAD. A default branch named FETCH_HEAD could win that lookup. The graph keeps the variants as alternatives. Comparing the resulting HEAD commit to the approved SHA before executing anything closes the specific resolution defect; verifying only the requested ref or successful Git exit status does not.
The public vulnerability identifier CVE-2026-86063 applies to the Claude Code pinning flaw, with versions below 2.1.179 affected and 2.1.179 patched. OpenAI's 0.146.0 release also records Git-plugin SHA verification. The research's September 17 statements about GitHub Copilot and Gemini CLI are dated status, not a verified October 23 assurance about all releases. Initial plugin adoption remains required even when a later background update needs no additional click. The report provides controlled demonstrations, not a confirmed malicious campaign against every installed client.
Applicable AIDEFEND Defenses (7)
What Defenders Should Do Now
- Inventory the exact client binaries, plugin loaders, marketplace sources and update processes actually used. Upgrade affected Claude Code and Codex to supported fixed builds, verify the running versions, and test both a SHA-shaped default branch and the product-specific FETCH_HEAD route in an isolated repository.
- Until a loader's fix is verified, disable the affected plugin installation/update route through managed policy. Restricting hosts that accept SHA-shaped branches can reduce one variant, but does not address FETCH_HEAD shadowing.
- For controlled clients, verify the resolved HEAD and an independently approved exact package digest before imports or hooks execute. Stage and load the same immutable bytes, cover every search path, and reject incomplete inventory or stale allowlists.
- Stop clients from cloning publisher repositories at all: serve plugins from an enterprise install broker or internal marketplace that installs reviewed, digest-bound snapshots, and treat every marketplace re-pin or default-branch change as a trigger to re-run admission before any update ships.
- Through MDM-managed client settings, limit marketplaces to approved sources hosted where SHA-shaped branch names are rejected and turn off background plugin auto-update, so a new pin applies only after a logged install action.
- Run clients, background updaters and plugin hooks within a verified outer sandbox that excludes developer secrets and production authority. Keep the containment boundary outside the plugin's own configuration.
- Run a read-only integrity check of installed plugin directories against the approved SHA and file manifest after every update. On a confirmed substitution, preserve the bytes, remove the plugin and its cached clone from every affected client, deny the malicious digests at the broker, and reinstall only from the reviewed snapshot.
Conclusion
Last updated: