Редакция · очередь апрува · temporary preview
Draft / Preview — not published

Plugin4Shell: when SHA pinning fails on Claude Code, Codex, Copilot, and Gemini CLI

Air Security’s Plugin4Shell disclosure (public Sep 17, 2026) is the supply-chain note I wish every desk running coding agents had already filed. The bug is not “don’t install shady plugins.” It is: you install a reviewed plugin, the marketplace pins a commit, the agent checks out that pin — and still lands attacker-controlled code. Zero click once auto-update is on. Full host compromise for whatever the agent can reach.

That hits the four names most production fleets actually use: Anthropic Claude Code, OpenAI Codex, GitHub Copilot (CLI path), and Google Gemini CLI. Same design miss across the board — checkout the pin, never assert that git rev-parse HEAD equals the pinned SHA. Git’s ref-vs-object ambiguity does the rest.

What actually breaks

SHA pinning was the industry answer to rug-pulls after SkillJacking / RepoJacking: review commit aaa…, pin it, trust immutability. Plugin4Shell voids that guarantee on the client.

Variant A (Claude Code, Codex, Copilot). Agent clones and runs git checkout <40-hex-sha>. Attacker who controls the plugin repo creates a branch named exactly like that SHA and makes it the default branch. Git prefers the ref over the object when names collide (you get a quiet “refname is ambiguous” warning). Working tree is malicious; the agent still reports a successful install at the pin. Auto-update (default on Claude Code and Codex) re-runs the same checkout when the marketplace bumps the pin — so already-installed plugins flip without a prompt.

Variant B (Gemini CLI). Fetch the right commit into FETCH_HEAD, then git checkout FETCH_HEAD. If the repo’s default branch is itself named FETCH_HEAD, checkout resolves to the branch and discards the fetched commit.

One client-side assertion closes both: after checkout, abort unless the resolved HEAD equals the pinned SHA. Marketplaces cannot fully enforce this — the pin is resolved inside the agent. Hosts help only partially: GitHub (and GitLab) reject 40-hex branch names; Bitbucket and self-hosted git often do not. Anthropic’s own docs still list Bitbucket / self-hosted as valid marketplace backends.

Patch status as of the disclosure window

  • Claude Code — fixed in 2.1.179 (Anthropic confirmed Jun 17, 2026).
  • Codex — fixed in 0.146.0 (“Verify Git plugin SHA checkouts”; Air verified Aug 12, 2026).
  • GitHub Copilot — disclosed; no client patch shipped at disclosure. Treat auto-update as a live risk; inventory Git hosts behind every marketplace.
  • Gemini CLI — deprecated; Google will not patch. Migrate (Air points at Antigravity, which has no marketplace SHA-pin path to bypass).

Private disclosure to all four was June 2026; public write-up mid-September. No CVE was assigned at disclosure — do not wait for a CVE number before inventorying.

Ops checklist for a production agent fleet

I care less about the PoC video and more about a two-column spreadsheet: agent version × Git host behind every marketplace plugin source.

  1. Version gate. Claude Code ≥ 2.1.179; Codex ≥ 0.146.0. Anything older is not “legacy,” it is unpatched RCE on plugin update.
  2. Copilot path. Disable marketplace auto-update where you can (autoUpdate / COPILOT_AUTO_UPDATE=false). Prefer GitHub/GitLab-hosted marketplace repos (reject SHA-shaped refs). Treat Bitbucket and self-hosted plugin remotes as elevated risk until a client fix lands.
  3. Gemini CLI. Do not keep it in the fleet for marketplace plugins. Migrate; do not “pin harder” on a client that will never ship the HEAD check.
  4. Assume plugin = code execution. Same blast-radius family as Muse Secure VM and OpenRouter shell: secrets stay at the boundary; agents never hold long-lived CRM/calendar passwords; network default-deny where you host sandboxes.
  5. Rotate after uncertain exposure. If engineers ran unpatched agents with auto-update on third-party plugins, rotate tokens those agents could see (GitHub PATs, cloud keys in env, MCP credentials).
  6. Marketplace inventory. List every plugin source: official vs community vs internal. Who can merge pin bumps? Who owns the upstream repos? Hijack of a trusted author’s repo plus Plugin4Shell is the zero-click path — SkillJacking already showed takeovers at scale.

Where this sits next to the rest of the stack

This month’s drafts keep circling the same production shape: cheap flash loops for interactive turns, sandboxed shell/Files for blast radius, Batch for overnight eval economics, credential surrogates so the agent never sees the password. Plugin4Shell is the distribution-layer sibling — the agent fleet’s plugin path is part of the trust boundary, not an IDE convenience.

OpenRouter weekly usage through Sep 22 still screams coding-agent volume on the apps side (Hermes / Claude Code / Kilo / Cline) while model volume sits on flash: GLM 5.3 Flash #1 (~18.4T, +61%), DeepSeek V4.1 Flash #2 (~17.8T, +122%), Hy4 preview #3 (~12.9T), GPT-5.6 Luna #4 (~8.67T), DeepSeek V4 Flash 0731 #5 (~8.64T). Those agents are exactly the class of tools Plugin4Shell targets. Ranking adoption without hardening the plugin checkout is how you buy more blast radius at a discount.

What I would do this week

  • Force-minimum versions for Claude Code and Codex in the fleet image / brew pin / Nix flake — not a Slack reminder.
  • Export the plugin list from every engineer machine that runs marketplace installs; flag non-GitHub/GitLab remotes.
  • Turn Copilot marketplace auto-update off until Microsoft ships a HEAD-equals-pin check.
  • Retire Gemini CLI marketplace use; document the migration target.
  • Add “plugin SHA verify” to the same security review that already covers MCP and shell egress.

Doing the “right” thing — review, pin, install from a trusted marketplace — is exactly the posture Plugin4Shell defeats until the client asserts HEAD. Update the agent. Inventory the Git host. Assume auto-update is an attack surface, not a convenience flag. Say hello.

Related drafts: Muse Secure VM credentials, OpenRouter shell + Files API, OpenRouter Batch API, OpenRouter rankings in production, phone stack teardown.

Sources: Air Security — Plugin4Shell (Sep 17, 2026); CSA research note — Plugin4Shell; The Register coverage; OpenRouter rankings (usage through Sep 22, 2026).