
Plugin4Shell Bypasses Hash Pinning—Audit Every Agent Plugin Path

To reduce exposure to Plugin4Shell, verify the commit and files a coding agent actually installs before allowing a plugin to run. AIR Security’s technical disclosure describes how control of a plugin repository can redirect a pinned checkout to different code in Claude Code, Codex, GitHub Copilot and Gemini CLI under the conditions it tested. A pin records the intended revision; it does not, by itself, prove what landed on disk.
Audit every route through which a plugin can be installed or refreshed, including marketplaces, direct repositories, local copies and automated updates. Compare the installed result with an independently recorded approval, then limit the files, credentials and network destinations the plugin can reach. These checks address both the substitution described in the disclosure and the damage executable plugin code could cause if an integrity check fails.
Find every installation and update route
Inventory enabled agents on developer machines and in CI. For each plugin, record its marketplace entry or installation command, source repository and owner, approved commit, installed location, agent version and update setting. Inspect both user-level and project-level configuration: a central marketplace list will miss plugins installed directly or supplied through a repository’s configuration.
Trace who can change the source repository, its default branch and any marketplace record that supplies a pin. Separate an approved commit from a mutable branch or tag, and identify whether a refresh requires a person’s action. An unattended update deserves particular attention because a changed upstream source can reach an existing installation during an ordinary agent session. Record where the agent gets its plugin files after checkout; the directory it executes may be a cache or copy rather than the Git working tree.
Compare the checkout with the approved commit
The Cloud Security Alliance’s technical analysis identifies an unverified post-checkout state as the shared failure across the affected implementations. For Claude Code, Codex and Copilot, a default branch named like the pinned commit can redirect checkout on a Git host that permits such names. Gemini CLI’s described route instead uses a default branch named FETCH_HEAD, which can take precedence over the commit just fetched. GitHub’s rejection of hash-shaped branch names narrows the former route, but does not establish protection against the Gemini route.
Use the approved full commit ID from a record outside the plugin’s writable directory. Immediately after installation or refresh, resolve the checkout’s actual HEAD to a commit object and require it to equal that ID exactly. Reject the installation on a mismatch, even if the checkout command succeeded or the marketplace still displays the expected pin. The requested reference and the resolved commit are different pieces of evidence; the bypass exploits treating them as interchangeable.
Run that comparison before the agent loads the plugin, and repeat it after every refresh. If a client cannot enforce the check at that point, put the install or update behind a separate gate that can. A periodic inventory can reveal drift, but it cannot prevent code from executing between a bad checkout and the next scan. Keep the approved revision and the observed revision with the install record so a failed comparison is actionable.
Verify the files the agent can execute
A matching HEAD establishes which commit Git checked out; it does not prove that every file the agent loads still matches that commit. Inspect modified and untracked files, including ignored paths that a routine Git status check may omit. Compare executable plugin files with a clean artifact built from the approved revision, allowing only explicitly documented generated files. This file-level check is an additional safeguard beyond the specific reference-resolution flaw.
If installation copies files out of Git into a cache, verify the copy rather than stopping at the source checkout. A manifest of approved file hashes can identify a changed command, hook or plugin configuration after copying. Review submodules, dependencies fetched during installation and install hooks as separate inputs: their content may not be established by the top-level commit comparison. Keep the verified directory from being rewritten between the check and execution, or reverify it immediately before loading.
Limit the plugin’s runtime reach
Treat provenance and permission as separate decisions. Review the plugin’s commands, hooks, downloads and connected services before enabling it. Run the agent with access to the repository and services needed for the task, rather than the developer’s entire home directory or every mounted workspace. Keep production credentials, unrelated source trees and broad cloud tokens outside that boundary; when credentials are necessary, scope them to the task and limit their lifetime.
A sandbox helps only when its mounts, identity and network rules constrain the plugin as well as the agent that invokes it. Restrict outbound connections to required destinations and retain egress logs. These controls do not correct a wrong checkout, but they reduce what substituted code can read or send. Where a plugin source cannot be verified, disabling its unattended refresh removes a background delivery route while the installation is assessed; an existing copy still needs an integrity check.
Read patch claims as disclosure-period evidence
The Hacker News’s September 18, 2026 disclosure review found no formal vendor advisory or CVE at publication, reported fixes in Claude Code 2.1.179 and Codex 0.146.0, found no Copilot client fix then, and noted uncertainty about continued Gemini CLI enterprise updates. Those findings describe the disclosure period, not every build now deployed.
Compare each deployed client with current vendor release information and look for an explicit check of the resolved checkout. Where that behavior cannot be established, retain the independent install gate and narrow the plugin’s permissions. Updating a client may stop future substitutions, but a version number alone does not establish the integrity of plugin files installed earlier. Rebuild an uncertain installation from an approved revision and verify its final payload before loading it.
Monitor changes and respond to a mismatch
Record each install and refresh with the source, approved commit, resolved HEAD, payload digest, agent version and update initiator. Watch for a changed repository or default branch, an unexpected executable file, a digest mismatch or outbound traffic outside the plugin’s permitted destinations. Keep enough history to identify which workspaces loaded a suspect copy and when the installed files changed.
If verification fails, stop the plugin from running and preserve its directory and install logs for investigation. Reinstall from a known revision only after the source and payload pass the same checks. Review the repositories and credentials the agent could reach while the suspect copy was present, and rotate secrets if exposure cannot be ruled out. The useful audit result is a traceable connection between the approved source, the files that ran and the permissions they had.
Also read:
Related articles


Copilot CLI Now Honors Content Exclusions—but Symlinks Still Slip Through

GitHub CLI’s Linux Key Expires Now—Verify Images Before the Next Build

Gitea’s RCE Is Now Exploited—Open Registration Widens the Door

Slackforce Makes Conversations Executable—Define the Agent Boundary First

Copilot Can Approve Pull Requests—Do Not Let One Agent Close the Review Loop
Subscribe to our newsletter
Get the latest Web3, AI, and crypto news delivered straight to your inbox.