Plugin4Shell — Multi-Vendor AI Coding Agent Plugin SHA-Pinning Bypass

Zero-click RCE breaking plugin SHA pinning across Claude Code, OpenAI Codex, GitHub Copilot, and Gemini CLI · disclosed by Air Security 2026-09-17/18
Severity
HIGH — 0-CLICK, NO CONFIRMED ITW
Type
AI Agent Plugin Supply Chain
Access
Zero-Click (background auto-update)
CVE
None identified in public sources as of 2026-09-18
Version
v0.1 (Draft) · 2026-09-18
Author
HuntPack
Confidence
Medium-High (vendor-corroborated mechanism; no ITW telemetry)
01

Executive Summary

Plugin4Shell is a zero-click remote-code-execution flaw affecting the plugin/marketplace systems of all four major AI coding agents — Anthropic Claude Code, OpenAI Codex, GitHub Copilot, and Google Gemini CLI — disclosed by Air Security researchers Or Nevo, Dor Granat, and Niv Hoffman on 2026-09-17/18. It breaks SHA pinning, the mechanism a marketplace uses to lock an installed plugin to one reviewed commit forever after. Every affected agent checks out the pinned commit but never verifies the checkout actually landed there. An attacker who controls a plugin's upstream repository can make that checkout resolve to a malicious tree — via a branch named identically to the 40-hex pinned SHA (Claude Code, Codex, GitHub Copilot) or via a default branch literally named FETCH_HEAD (Gemini CLI) — while the pin still displays as honored.

What makes it zero-click is plugin auto-update, on by default in Claude Code and Codex: the same checkout logic re-runs in the background whenever the marketplace bumps the pinned commit, silently swapping code inside a plugin the victim already trusts and already installed. No install step, no prompt, nothing to notice. The victim only needs one plugin, installed from a marketplace they trust, that was reviewed and pinned exactly as the security model intends — doing everything right does not protect you.

Patch status: fixed in Claude Code 2.1.179 and OpenAI Codex 0.146.0. GitHub Copilot remains unpatched — Microsoft has not shipped a fix, and exposure persists wherever Copilot supports marketplaces hosted on Bitbucket or self-hosted git (GitHub.com itself structurally blocks SHA-shaped branch names). Google has deprecated Gemini CLI and will not patch it; installs under Gemini Code Assist Standard/Enterprise licensing keep running and stay exposed indefinitely, with migration to Antigravity as the only mitigation.

There is no public report of in-the-wild exploitation and no published malware indicators for Plugin4Shell as of this pack's build. This is deliberately a behavioral + exposure hunt: find vulnerable installs, watch the plugin-update/checkout mechanic itself for the anomaly the attack requires, and catch the post-exploitation behaviors — an unexpected shell spawned from git or from inside a plugin directory, credential-store access, anomalous egress — that a real exploitation attempt would produce on an EDR-visible endpoint even though the exploit's actual "flip" happens server-side, off the endpoint.

Defender priority: patch Claude Code and Codex fleet-wide today (§12, Immediate tier) — that closes two of four vendors completely. For Copilot and Gemini CLI, since no patch exists, the durable mitigation is marketplace-host restriction (GitHub-only) plus the behavioral detections in §8 (Q5/Q6/Q7 are Custom IOA candidates).
02

Source Review & Web Hunter Notes

TierSourceKey FindingCarry Forward
1 · Primary researchAir Security — "Plugin4Shell"Full technical writeup: attack chain, both exploitation variants, code-level checkout commands, timeline, per-vendor patch statusYes
2 · Trade pressHelp Net SecurityCorroborates core mechanism; researcher quotes; independent framing of the two attack variantsYes
2 · Trade pressThe RegisterOn-record GitHub spokesperson statement disputing exploitability on GitHub.com; Air's rebuttal re: Bitbucket/self-hosted exposure; "~90% of Fortune 500 use Copilot" (Microsoft stat); Microsoft did not respondYes
3 · AggregatorMallory.aiCross-check of vendor patch table, timeline, and researcher namesPartial (cross-check only)
1 · Vendor changelogClaude Code official changelogConfirms version 2.1.179 exists, dated June 16, 2026; no explicit security callout in the public entry (silent-fix pattern — common for supply-chain fixes)Yes
1 · Vendor changelogCodex GitHub release rust-v0.146.0Confirms version 0.146.0 and the specific merged fix, commit-titled "Verify Git plugin SHA checkouts" (PR #34644) — direct engineering-level corroboration of the AIR reportYes
1 · Vendor blogGoogle Developers BlogConfirms Gemini CLI deprecation for free/Pro/Ultra tiers; confirms Gemini Code Assist Standard/Enterprise licenses keep Gemini CLI running unchanged, with continued model accessYes
1 · Vendor docsClaude Code — Discover & install pluginsConfirms marketplace Git URLs include "GitLab, Bitbucket, and self-hosted servers"; confirms plugin cache path ~/.claude/plugins/cacheYes
3 · Vendor docsOpenAI Codex — Plugins docsGeneral plugin-directory context; did not independently confirm an exact Codex plugin cache pathPartial (justifies a placeholder rather than a claimed path)

Web Hunter Notes

  • No CVE ID was identified for Plugin4Shell in any source surveyed as of 2026-09-18.
  • A targeted search for coverage on thehackernews.com returned zero matching results at research time — noted as a coverage gap in that specific outlet, not as evidence against the vulnerability (four independent sources above corroborate it).
  • GitHub's on-record position (via The Register) is that Plugin4Shell cannot be exploited on GitHub.com because it rejects 40-hex-shaped branch/tag names. Air Security's countered position — that Bitbucket-hosted and self-hosted marketplaces remain exploitable, and that this is exactly why GitHub Copilot (which supports those hosts) is still vulnerable — is carried forward as the operative risk statement in this pack, and is independently supported by Claude Code's own documentation confirming Bitbucket/self-hosted marketplace support (source 08 above).
  • Prompt-injection check: all 9 saved source snapshots were scanned for directive-style text aimed at an AI agent (e.g. "ignore previous instructions," fake system/admin authority claims, instructions to fetch further URLs or run commands). None was found in any source. This matters more than usual here since the subject is an attack on AI coding agents themselves — see also the note in §18.
03

Hunt Brief & Attack Chain

Hunt hypotheses

#HypothesisMITRETelemetryConf
H1Vulnerable agent binaries (Claude Code, Codex, Copilot, Gemini CLI) are present and executing on managed endpointsT1195.002ProcessRollup2Low (visibility only)
H2Version/update-check invocations expose the installed version for manual confirmationT1195.002ProcessRollup2Low
H3Git clone/fetch/checkout operations occur inside agent plugin directories (expected, but scopes every other hunt)T1195.002ProcessRollup2Medium
H4A given plugin path shows repeated SHA re-pin/checkout churn — the "version bump → rug-pull" cadence AIR describesT1195.002ProcessRollup2Medium
H5A git process spawns a shell or script interpreter — the signature of a malicious post-checkout hookT1195.002, T1059ProcessRollup2High
H6A shell/script interpreter or LOLBin executes from inside an agent plugin directoryT1195.002, T1059ProcessRollup2High
H7A process spawned by git or from a plugin path reads SSH keys, cloud credentials, .npmrc, .env, or keychain itemsT1552.001, T1552.004, T1555.001ProcessRollup2High
H8An agent process resolves DNS / makes outbound connections to a destination outside the vendor API and marketplace-host allowlist, following plugin update activityT1071.001, T1567DnsRequest, ProcessRollup2Medium

Attack chain (per Air Security)

StepWhat happensTelemetryHunt angle
1. PlantAttacker publishes a genuinely benign plugin, pinned at commit aaa…aaa; it passes marketplace reviewNone (marketplace-side, pre-endpoint)Out of EDR scope — marketplace review process, not this pack
2. AdoptionUsers install the plugin; every install pins to the reviewed aaa…aaa commitProcessRollup2 (git clone/checkout)H3
3. Version bumpAttacker ships a routine, still-benign update; marketplace re-pins to new commit bbb…bbbProcessRollup2 (git fetch/checkout)H3, H4
4. Rug-pullAttacker creates a branch named bbb…bbb (or, for Gemini CLI, a default branch named FETCH_HEAD), sets it default, and points it at malicious code — the pinned commit object itself can stay untouchedNone (git-server-side; no endpoint telemetry sees this step)Documented gap — see §15
5. Auto-update to RCEBackground auto-update re-runs git checkout <pin>; git resolves the SHA-shaped name to the branch instead of the commit object; malicious code lands and executes with no user interactionProcessRollup2 (git checkout, then child process)H4, H5, H6, H7, H8
04

Consolidated IOC Table

Plugin4Shell has no published campaign IOCs — no malware hashes, no C2 domains/IPs, no confirmed in-the-wild exploitation. The rows below are exposure and behavioral indicators only, honestly labelled as such.

TypeValueConfidenceActionContextExpiry
software-versionClaude Code < 2.1.179HighhuntVulnerable to Plugin4Shell SHA-pinning bypassn/a — structural until patched fleet-wide
software-versionOpenAI Codex < 0.146.0HighhuntVulnerable; fix landed in commit "Verify Git plugin SHA checkouts"n/a
software-versionGitHub Copilot, any version, with marketplace plugins enabledHighhunt / enrichNo patch shipped; exposure confirmed where Copilot supports Bitbucket / self-hosted marketplacesn/a — reassess when Microsoft ships a fix
software-versionGemini CLI, any versionHighhuntDeprecated by Google; will not be patched; Standard/Enterprise Gemini Code Assist licenses keep it runningn/a — indefinite
behavioralgit checkout inside a plugin directory resolving to a branch rather than the pinned commit objectMediumhuntCore exploitation mechanic; not independently observable via EDR (see §15 gap)n/a
filename-patternPlugin install/cache path segments (e.g. ~/.claude/plugins/cache for Claude Code; exact Codex/Copilot/Gemini equivalents not confirmed in sources — REPLACE_WITH_your-tenant's plugin path)MediumpivotScoping value for §8 queriesn/a
process-nameAgent binaries (claude, codex, gemini, copilot) as parents of shell/script interpretersMediumhuntBaseline for behavioral queries; high native FP (agents legitimately spawn shells)n/a
05

Affected Surface & Telemetry Matrix

SurfaceRequired TelemetryPriorityGap Risk
Endpoints running Claude CodeProcessRollup2, DnsRequest, NetworkConnectIP4CriticalLow — standard EDR coverage
Endpoints running OpenAI CodexProcessRollup2, DnsRequest, NetworkConnectIP4CriticalLow
Endpoints running Gemini CLI (Enterprise/Standard-licensed, still supported)ProcessRollup2, DnsRequest, NetworkConnectIP4HighMedium — smaller install base, but zero patch path exists
Endpoints running GitHub Copilot with plugin marketplaces enabledProcessRollup2, DnsRequest, NetworkConnectIP4HighMedium — ~90% of Fortune 500 run Copilot per Microsoft (source 03); unpatched
Software/version inventoryFalcon Discover / Spotlight app inventory, RTRCriticalHigh — Falcon process telemetry has no semantic-version field; §8 Q1/Q2 are visibility proxies only, not a substitute for inventory
Plugin marketplace git infrastructure (Bitbucket / self-hosted hosts)Git server audit logs — outside Falcon's scopeMediumHigh — the actual malicious branch creation happens server-side; no EDR telemetry observes it (see §15)
06

ATT&CK Mapping

TacticTechnique IDTechnique NameObserved Behavior
Initial AccessT1195.002Supply Chain Compromise: Compromise Software Supply ChainMalicious plugin publication or repository takeover swaps trusted, SHA-pinned plugin code via the branch-name / FETCH_HEAD checkout-resolution bypass
ExecutionT1059 (.001/.003/.004/.006)Command and Scripting InterpreterMalicious plugin payload or post-checkout git hook launches a shell or script interpreter
ExecutionT1204 — N/AUser ExecutionExplicitly not required — zero-click via background auto-update is the defining characteristic of this vulnerability
Credential AccessT1552.001Unsecured Credentials: Credentials In FilesReads of .env, .npmrc, .git-credentials, cloud CLI config/token caches
Credential AccessT1552.004Unsecured Credentials: Private KeysReads of ~/.ssh key material
Credential AccessT1555.001Credentials from Password Stores: Keychainsecurity find-generic-password / find-internet-password invocations on macOS
Command and ControlT1071.001Application Layer Protocol: Web ProtocolsBehavioral only — no confirmed C2 infrastructure; outbound calls from a compromised agent process to non-allowlisted hosts
ExfiltrationT1567Exfiltration Over Web ServiceData pushed out via legitimate-looking web endpoints from the compromised agent process
07

Native Audit-Log Hunts

Non-CQL checks — run these directly (RTR, SSH, or a management tool) since they read information Falcon process telemetry does not expose (semantic version strings, git ref resolution, marketplace configuration).

1. Fleet version audit

Run via RTR or your software-deployment tool against every managed endpoint:

claude --version
codex --version
gemini --version
gh copilot --version   # or: gh extension list
npm ls -g @anthropic-ai/claude-code
npm ls -g @openai/codex

Flag: Claude Code < 2.1.179, Codex < 0.146.0, any Gemini CLI, any Copilot install with plugin/marketplace features enabled.

2. Per-plugin pin-vs-HEAD audit

This is literally the check the vulnerable agents omit — running it out-of-band is the strongest manual verification available. For each installed plugin directory, compare the resolved commit against the pin recorded in the marketplace's manifest/lock entry for that plugin:

git -C <plugin_dir> rev-parse HEAD
# Compare the output against the SHA the marketplace manifest recorded as pinned
# for this plugin. Any mismatch is a direct compromise indicator.

3. SHA-shaped branch / bad-default-branch audit

Run against any plugin repository your organization controls or mirrors:

git ls-remote --heads <repo> | grep -E '[0-9a-f]{40}'      # SHA-shaped branch names
git remote show <repo> | grep 'HEAD branch'                 # must never be a 40-hex name or "FETCH_HEAD"

4. Marketplace host inventory

Enumerate configured plugin marketplaces per agent (Claude Code: ~/.claude/settings.json marketplace entries; check equivalent configuration for Codex/Copilot in your environment) and flag any entry hosted on Bitbucket or a self-hosted git server as elevated risk until the corresponding agent is confirmed patched.

08

CrowdStrike LogScale CQL Hunt Queries

Pick your tenant's cloud first — every "Open in Falcon" button below uses this selection.
Q1 · Exposure: AI Coding Agent Binary Inventory
CONF LOWFP LOWCOST LOW

Looks for: any execution of a Claude Code, Codex, Gemini CLI, or Copilot binary — the host population every other query in this pack is scoped against.

// HUNT: AI Coding Agent Binary Inventory (Plugin4Shell Exposure Baseline)
// MITRE: T1195.002
// CONF: low
// FP: low
// COST: low
// REQUIRES: ProcessRollup2
// FALSE POSITIVES: none — this is an asset-visibility query, not a detection. Every hit is expected.
// LOOKBACK: 7d
#event_simpleName = ProcessRollup2
| FileName = /^(claude|claude-code|codex|gemini|copilot|github-copilot|gh-copilot)(\.exe)?$/i
| groupBy([ComputerName, FileName, ImageFileName], function=[count(as=Executions), max(@timestamp, as=LastSeen)], limit=20000)
| table([ComputerName, FileName, ImageFileName, Executions, LastSeen])
| sort(LastSeen, order=desc)
Q2 · Exposure: Agent Version / Self-Update Invocation Capture
CONF LOWFP MEDIUMCOST LOW

Looks for: explicit version/health-check subcommands whose CommandLine an analyst can pull to confirm the actual installed version. FP: routine manual health checks (claude doctor) and CI pipelines that print version banners are expected and benign — triage, don't alert.

// HUNT: Agent Version / Self-Update Invocation Capture (Plugin4Shell Version Validation)
// MITRE: T1195.002
// CONF: low
// FP: medium
// COST: low
// REQUIRES: ProcessRollup2
// FALSE POSITIVES: routine manual health checks and CI pipelines that print a version banner are expected and benign.
// TUNING: pull the returned CommandLine into RTR or Discover/Spotlight software inventory to read the actual version string — Falcon process telemetry has no semantic-version field.
// LOOKBACK: 7d
#event_simpleName = ProcessRollup2
| FileName = /^(claude|claude-code|codex|gemini|copilot|github-copilot|gh-copilot)(\.exe)?$/i
| CommandLine = /(--version|doctor|update\s+--check|self-update)/i
| table([@timestamp, ComputerName, UserName, FileName, CommandLine])
| sort(@timestamp, order=desc)
Q3 · Plugin Activity: Marketplace Git Operations Inside Plugin Directories
CONF MEDIUMFP HIGHCOST LOW

Looks for: git clone/fetch/checkout activity scoped to a path containing "plugin" — the routine mechanic Plugin4Shell abuses. FP: fires on every legitimate plugin install and every legitimate background auto-update, which is the vast majority of hits.

// HUNT: Marketplace Git Operations Inside Agent Plugin Directories
// MITRE: T1195.002
// CONF: medium
// FP: high
// COST: low
// REQUIRES: ProcessRollup2
// FALSE POSITIVES: legitimate plugin installs and background auto-updates are the majority of hits — this is a scoping/pivot query, not a standalone alert.
// TUNING: pivot from a hit here into Q5-Q7 (hook execution, plugin-path interpreter spawn, credential-store access) — only escalate a hit that also matches one of those.
// LOOKBACK: 7d
#event_simpleName = ProcessRollup2
| FileName = /^git(\.exe)?$/i
| CommandLine = /(clone|fetch|checkout)/i
| CommandLine like "*plugin*"
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, CommandLine])
| sort(@timestamp, order=desc)
Q4 · Plugin Activity: Repeated Plugin Re-Pin / Checkout Churn
CONF MEDIUMFP MEDIUMCOST MEDIUM

Looks for: hosts where a plugin has been re-pinned/checked-out to a new 40-hex commit unusually often — the "version bump → rug-pull" cadence described in the attack chain (§3, steps 3-4). FP: plugins under active development legitimately re-pin often right after install; fast-release marketplaces will also show repeat hits.

// HUNT: Repeated Plugin Re-Pin / Checkout Churn (Rug-Pull Cadence Anomaly)
// MITRE: T1195.002
// CONF: medium
// FP: medium
// COST: medium
// REQUIRES: ProcessRollup2
// FALSE POSITIVES: plugins under active development re-pin often in the first days after install; fast-cadence marketplaces show repeat hits too.
// TUNING: exclude the first 24h after first-seen install per host+plugin; if your marketplace publishes a release calendar, exclude known release windows.
// LOOKBACK: 7d
#event_simpleName = ProcessRollup2
| FileName = /^git(\.exe)?$/i
| CommandLine = /checkout/i
| CommandLine like "*plugin*"
| CommandLine = /[0-9a-f]{40}/i
| groupBy([aid, ComputerName], function=[count(as=CheckoutEvents), collect(CommandLine, limit=10)], limit=10000)
| CheckoutEvents > 3
| sort(CheckoutEvents, order=desc)
Q5 · Post-Exploitation: Git Process Spawning a Shell or Script Interpreter
CONF HIGHFP LOWCOST LOW

Looks for: a shell or script interpreter launched directly by git — the signature of a malicious post-checkout hook running immediately after the SHA-pinning bypass lands. IOA candidate (see §9). FP: repos with legitimate git hooks (husky, lint-staged, pre-commit) spawn interpreters from a git parent as normal developer workflow.

// HUNT: Git Process Spawning a Shell or Script Interpreter (Post-Checkout Hook Execution)
// MITRE: T1195.002, T1059
// CONF: high
// FP: low
// COST: low
// REQUIRES: ProcessRollup2
// FALSE POSITIVES: repos with legitimate git hooks (husky, lint-staged, pre-commit) spawn interpreters from a git parent outside agent plugin directories.
// TUNING: exclude known-good repo paths / CI runners in ImageFileName or CommandLine; correlate with Q3 to confirm the parent git process was operating inside an agent plugin directory before alerting.
// LOOKBACK: 7d
#event_simpleName = ProcessRollup2
| ParentBaseFileName = /^git(\.exe)?$/i
| FileName = /^(powershell|pwsh|cmd|sh|bash|zsh|dash|ksh|osascript|wscript|cscript|mshta|python[23]?|perl|ruby|node|curl|wget)(\.exe)?$/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, ImageFileName, CommandLine])
| sort(@timestamp, order=desc)
Q6 · Post-Exploitation: Interpreter or LOLBin Executing From a Plugin Path
CONF HIGHFP MEDIUMCOST LOW

Looks for: a shell, script interpreter, or LOLBin whose own executing image resides inside a plugin directory — the malicious plugin's own delivered payload running. IOA candidate (see §9). FP: plugins that legitimately bundle a helper/build script executing from their own directory on first install.

// HUNT: Shell or Script Interpreter Executing From an Agent Plugin Directory
// MITRE: T1195.002, T1059
// CONF: high
// FP: medium
// COST: low
// REQUIRES: ProcessRollup2
// FALSE POSITIVES: plugins that legitimately bundle a helper script (build step, native-module postinstall) executing from their own directory on first install.
// TUNING: exclude the first-install window for that plugin path (correlate against Q3's first-seen timestamp); exclude your organization's reviewed, allowlisted plugin publishers.
// LOOKBACK: 7d
#event_simpleName = ProcessRollup2
| ImageFileName like "*plugin*"
| FileName = /^(powershell|pwsh|cmd|sh|bash|zsh|dash|ksh|osascript|wscript|cscript|mshta|python[23]?|perl|ruby|curl|wget)(\.exe)?$/i
| table([@timestamp, ComputerName, UserName, ImageFileName, CommandLine])
| sort(@timestamp, order=desc)
Q7 · Credential Access: Plugin/Git-Hook-Spawned Process Touching Credential Stores
CONF HIGHFP LOWCOST LOW

Looks for: a process spawned by git or executing from a plugin path that references SSH keys, cloud credential files, or macOS keychain items — the payoff step of a real compromise. IOA candidate (see §9). FP: legitimate developer tooling reads these same paths constantly; this query is pre-scoped (git/plugin-path parent only) specifically to suppress that noise.

// HUNT: Plugin- or Git-Hook-Spawned Process Touching Credential Stores
// MITRE: T1552.001, T1552.004, T1555.001
// CONF: high
// FP: low
// COST: low
// REQUIRES: ProcessRollup2
// FALSE POSITIVES: legitimate developer tooling (aws-cli, git credential helpers, dotenv loaders) reads these same paths constantly — this query is pre-scoped to git/plugin-path parents specifically to suppress that noise.
// TUNING: do not widen the parent/path scope without adding a second condition (unusual child, non-interactive session, off-hours) or it will flood on ordinary developer activity.
// LOOKBACK: 7d
#event_simpleName = ProcessRollup2
| (ParentBaseFileName = /^git(\.exe)?$/i or ImageFileName like "*plugin*")
| CommandLine = /(aws\/credentials|aws\\credentials|\.ssh\/|\.ssh\\|\.npmrc|git-credentials|\.env|find-generic-password|find-internet-password)/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, ImageFileName, CommandLine])
| sort(@timestamp, order=desc)
Q8 · Exfil: Agent-Process DNS/Network Activity to Non-Allowlisted Destinations
CONF MEDIUMFP MEDIUMCOST MEDIUM

Looks for: DNS resolutions from an agent process to a domain outside a vendor-API/marketplace-host allowlist. FP: coding agents legitimately reach many domains (package registries, telemetry, MCP servers) — this query is only useful once tuned to your tenant's actual allowlist. Ships Investigate-only, not an IOA candidate, until tuned.

// HUNT: Agent-Process DNS/Network Egress to Non-Allowlisted Destinations
// MITRE: T1071.001, T1567
// CONF: medium
// FP: medium
// COST: medium
// REQUIRES: DnsRequest, ProcessRollup2
// FALSE POSITIVES: coding agents legitimately reach many domains (package registries, telemetry, MCP servers, the vendor's own API) — useful only once tuned to your tenant.
// TUNING: ⚠ validate in tenant — replace the domain allowlist below with your organization's approved vendor API hosts and configured marketplace host(s) before relying on this query; ship as Investigate-only until tuned.
// LOOKBACK: 7d
#event_simpleName = DnsRequest
| rename(field=ContextProcessId_decimal, as=TargetProcessId_decimal)
| join(query={#event_simpleName = ProcessRollup2 | FileName = /^(claude|claude-code|codex|gemini|copilot|github-copilot|gh-copilot)(\.exe)?$/i}, field=TargetProcessId_decimal)
| not (DomainName = /(anthropic\.com|openai\.com|githubcopilot\.com|github\.com|githubusercontent\.com|google\.com|googleapis\.com|bitbucket\.org)$/i)
| table([@timestamp, ComputerName, UserName, DomainName, CommandLine])
| sort(@timestamp, order=desc)
09

CrowdStrike Custom IOA Recommendations

Three queries clear the bar for Custom IOA promotion (high CONF, low-medium FP, low cost). Deploy all three in Detect mode fleet-wide first; do not jump to Prevent given AI agents' legitimately high baseline of shell/script activity (see §11 Validation Gates).

IOA-1 — Git Process Spawning a Shell/Script Interpreter (from Q5)

Pattern: ParentBaseFileName matches git AND the child's FileName matches a shell/script-interpreter list. Exclusions: known CI runner images; repos with reviewed git hooks (husky/lint-staged) outside agent plugin directories. Deployment: Falcon Custom IOA rule, Detect mode, 14-day burn-in.

Scheduled Search: DETECT — Git Hook Spawns Interpreter (Plugin4Shell) — fires on any git-parented interpreter process; investigate whether the parent git operation touched a plugin path (cross-reference Q3) before escalating.

Triage: (1) confirm the parent git command from CommandLine, (2) check whether the working directory is an agent plugin path, (3) pull the child process's own CommandLine and any subsequent network/file activity, (4) check Q7 for the same host/timeframe, (5) if plugin-path-confirmed and unexpected, isolate the host and proceed to §14 Containment.

IOA-2 — Interpreter/LOLBin Executing From a Plugin Path (from Q6)

Pattern: ImageFileName contains a plugin-path segment AND FileName matches a shell/interpreter/LOLBin list. Exclusions: first-install window per plugin path; allowlisted publishers. Deployment: Custom IOA, Detect mode, 14-day burn-in, then evaluate Prevent for allowlisted-publisher exclusions only.

IOA-3 — Credential-Store Access From Git/Plugin-Spawned Process (from Q7)

Pattern: parent is git or image path contains a plugin segment, AND CommandLine references a credential-store path. Exclusions: none by default — this pattern is already narrow; widen only with a documented business reason. Deployment: Custom IOA, Detect mode; strong Prevent candidate after a clean 14-day burn-in given its low native FP.

Pivot queries: host-scoped — re-run Q5/Q6/Q7 with aid = "<affected aid>" added as the first filter after #event_simpleName; environment-wide — drop the host scope and widen §8's 7-day lookback to 30 days to check for a broader campaign.

10

Machine-Readable IOC Appendix

Plugin4Shell ships no campaign IOCs. The grid below is grouped for quick-copy convenience — vulnerable/fixed version strings, plugin path patterns, and process names — not a blocklist of malicious infrastructure.

Falcon IOC Management CSVbulk import
type,value,action,severity,expiration,description,tags
filename,REPLACE_WITH_your-tenant-plugin-cache-path,hunt,medium,2027-03-18,Plugin4Shell plugin-path scoping value — no campaign IOC published,supply-chain:Plugin4Shell
domain,REPLACE_WITH_your-approved-marketplace-host,enrich,low,2027-03-18,Plugin4Shell allowlist entry for Q8 — populate with your tenant's actual marketplace host,supply-chain:Plugin4Shell
Vulnerable / Fixed Version Stringsquick reference
Claude Code:  VULNERABLE  < 2.1.179   |  FIXED  >= 2.1.179  (fixed 2026-06-17)
OpenAI Codex: VULNERABLE  < 0.146.0   |  FIXED  >= 0.146.0  (fix verified 2026-08-12)
GitHub Copilot: VULNERABLE, all versions with marketplace plugins enabled — no fix shipped
Gemini CLI:   VULNERABLE, all versions — deprecated 2026-08-04, will not be patched
Plugin Path / Process-Name Quick Referencefor CQL / RTR
Process basenames: claude, claude-code, codex, gemini, copilot, github-copilot, gh-copilot, git
Confirmed plugin cache path (Claude Code): ~/.claude/plugins/cache
Codex/Copilot/Gemini plugin paths: REPLACE_WITH_confirmed-path (not published in sources surveyed — validate via native audit §7.4)
Generic path-scoping wildcard used in §8 queries: *plugin*
Native Audit One-Linersfrom §7
claude --version; codex --version; gemini --version; gh copilot --version
git -C <plugin_dir> rev-parse HEAD
git ls-remote --heads <repo> | grep -E '[0-9a-f]{40}'
git remote show <repo> | grep 'HEAD branch'
11

Detection Validation Gates

GateRequirement
Telemetry readyProcessRollup2 and DnsRequest broadly available across the fleet; Identity Protection license not required for any query in this pack
Benign baselineRun Q1/Q2 once to establish a fleet inventory; run Q3/Q4 for 7 days in Investigate-only mode before setting the Q4 churn threshold for your environment
Positive testsValidate Q5/Q6/Q7 against a benign, git-hook-heavy development repo (one using husky/lint-staged) to confirm your exclusion list actually catches it before promoting to a Custom IOA
PromotionQ5, Q6, Q7 promote to Custom IOA in Detect-only mode for a minimum 14-day burn-in with zero benign hits before Prevent is even considered — AI coding agents have a legitimately high shell-spawn baseline, so this window matters more here than in a typical LOLBin hunt
12

Hardening — Tiered

Immediate (this week)

Patch Claude Code to ≥2.1.179 and Codex to ≥0.146.0 fleet-wide. MITRE M1051 (Update Software). Both fixes are shipped, low-risk version bumps — no compatibility rework needed. Verify: re-run §7.1's version audit; zero hosts should report a pre-fix version after rollout.

Immediate (this week)

Restrict plugin marketplace hosts to GitHub-only wherever business requirements allow, for Copilot and any Claude Code/Codex marketplaces you administer. MITRE M1033 (Limit Software Installation). GitHub structurally rejects 40-hex branch names, which closes the branch-name variant of the bypass entirely for marketplaces hosted there (confirmed via GitHub's own statement, source 03, and independently via Claude Code's marketplace-host documentation, source 08). This does not help the Gemini CLI FETCH_HEAD variant. Verify: §7.4 marketplace host inventory — zero non-GitHub hosts remaining, or each one explicitly risk-accepted.

Near-term (1-4 weeks)

Gate or disable background plugin auto-update for GitHub Copilot and Gemini CLI specifically — the two vendors with no patch available — until each plugin's pin is manually re-verified against §7.2's pin-vs-HEAD check. MITRE M1033, M1038. ⚠ The exact configuration toggle name for auto-update was not confirmed in any source fetched for this pack — consult current vendor plugin-settings documentation before deploying; do not assume a specific config key.

Near-term (1-4 weeks)

Migrate Gemini CLI installations to Antigravity where feasible — Google's stated mitigation, and the only complete fix since Gemini CLI itself will not be patched. MITRE M1033. Verify: §7.1 version audit shows zero active Gemini CLI processes post-migration.

Strategic (1-3 months)

Move developer/agent credentials off long-lived static files (~/.aws/credentials, static SSH keys) onto short-lived, scoped credentials (cloud IAM role assumption, SSH certificate authorities, a secrets manager) so that even a successful Plugin4Shell exploitation yields a narrow, quickly-expiring blast radius instead of durable keys. MITRE M1041 (Encrypt Sensitive Information — data at rest for any vaulted secrets), M1026 (Privileged Account Management). Verify: CIS AWS Foundations Benchmark control on long-lived IAM access keys; audit for static SSH keys in developer home directories.

Strategic (1-3 months)

Application-control rule blocking script-interpreter execution from user-writable agent plugin directories (Windows AppLocker/WDAC; macOS/Linux equivalent via EDR prevention policy). MITRE M1038 (Execution Prevention). Verify: §8 Q6 spot-check shows zero interpreter executions from plugin paths post-deployment, apart from documented allowlist exceptions. ⚠ best-practice control — no CIS Benchmark or MS Security Baseline entry exists specifically for AI-agent plugin directories; the rule is a direct application of the general AppLocker/WDAC guidance to this new path.

13

Deployable Playbooks

Playbook A — Fleet-Wide Agent Version Enforcement

MITRE: T1195.002 → M1051   Estimated deploy time: 1-2 hours to script + one RTR/deployment-tool push cycle   Prerequisites: RTR access or existing software-deployment tooling; network path to each vendor's package registry (npm for Claude Code/Codex)   Reboot required: No

Step 1 — Audit current versions fleet-wide

What it does: establishes which hosts are below the fixed version. Why it works: you cannot enforce a patch you haven't measured compliance against.

# Run via RTR against each managed endpoint (or your fleet's equivalent)
claude --version
codex --version
# Collect results centrally; flag Claude Code < 2.1.179 and Codex < 0.146.0

Verify: aggregate the returned versions; the count of non-compliant hosts is your rollout scope.

Rollback: none required — this step is read-only.

Step 2 — Push the update

# npm-based installs
npm install -g @anthropic-ai/claude-code@latest
npm install -g @openai/codex@latest

# Native installer path — re-run the vendor's install/update command, then:
# restart the terminal / re-launch the agent for the update to take effect

Verify: re-run Step 1's version check; expect ≥2.1.179 / ≥0.146.0 fleet-wide.

Rollback: npm install -g @anthropic-ai/claude-code@<previous-version> / @openai/codex@<previous-version> if the update breaks an unrelated workflow — note that rolling back re-exposes the host to Plugin4Shell, so treat this as a short-lived exception only, tracked to a re-patch date.

Playbook B — Marketplace Host Restriction (GitHub-Only)

MITRE: T1195.002 → M1033   Estimated deploy time: 2-4 hours   Prerequisites: administrative access to each agent's marketplace configuration; inventory of currently-configured marketplace hosts (§7.4)   Reboot required: No

Step 1 — Inventory configured marketplaces

# Claude Code marketplace entries live under enabledPlugins / marketplace config in:
cat ~/.claude/settings.json
# Review each marketplace's source URL for a non-GitHub git host (Bitbucket, GitLab,
# self-hosted). Repeat against your organization's Codex/Copilot marketplace config.

Verify: a list of every non-GitHub-hosted marketplace currently trusted.

Rollback: none required — read-only.

Step 2 — Remove or risk-accept non-GitHub marketplaces

# Remove a marketplace (Claude Code):
/plugin marketplace remove <marketplace-name>

# If a non-GitHub marketplace is a genuine business requirement, document a formal
# risk acceptance and compensate with the §8 Q5/Q6/Q7 Custom IOAs in Detect mode
# specifically for hosts using that marketplace.

Verify: §7.4 marketplace host inventory returns zero non-GitHub hosts, or each remaining one is attached to a documented risk acceptance.

Rollback: re-add the marketplace with /plugin marketplace add <url> if removal breaks a required workflow; this restores the underlying exposure, so pair any rollback with the Custom IOA compensating control from Step 2.

14

Containment Runbook

PhaseActionsOwnerEvidence
IsolateNetwork-contain the affected host via Falcon RTR/RTM; treat any credential the compromised agent process could have reached (cloud keys, SSH keys, git tokens, npm tokens) as compromised pending rotation; disable plugin auto-update fleet-wide as an emergency stopgap if the affected plugin is broadly installedIR / SOCQ5-Q8 hit details; §7.2 pin-vs-HEAD mismatch record
EradicateRemove the compromised plugin directory; confirm the git remote's default branch and resolved HEAD match the expected upstream (§7.3); reinstall the plugin fresh from a known-good, manually-verified pin; patch/upgrade the agent binary to the fixed versionIR / Endpoint EngBefore/after §7.2 and §7.3 audit output
RecoverRotate every credential the host could reach; audit downstream systems (cloud IAM, CI/CD, package registries, connected MCP servers) for anomalous access under the rotated credentials' prior values; re-enable plugin auto-update only after the fleet is confirmed patched; monitor via Q5-Q8 for 30 days post-incidentIR / Cloud & Identity EngCredential rotation log; 30-day Q5-Q8 monitoring results
15

Detection Coverage Map

Technique / StepBehaviorCQLIOACoverage
T1195.002 — Plant / AdoptionMalicious or later-hijacked plugin published and adopted via marketplace reviewGAP — marketplace-side review process, no endpoint telemetry
T1195.002 — Version bump / Rug-pullBranch renamed to the pinned SHA, or default branch renamed to FETCH_HEAD, on the attacker's git hostGAP — happens entirely server-side on the plugin's git host; no EDR visibility into remote repository state
T1195.002 — Auto-update checkoutBackground auto-update re-runs git checkout against the (possibly hijacked) pinQ3, Q4Partial — checkout activity is visible; Falcon cannot see whether git resolved the name to a ref or a commit object
T1059 — Malicious code executionPost-checkout hook or plugin entrypoint runs a shell/script interpreterQ5, Q6IOA-1, IOA-2Good
T1552 / T1555 — Credential accessCompromised-process reads of SSH keys, cloud credentials, keychainQ7IOA-3Good
T1071 / T1567 — C2 / ExfilOutbound calls from a compromised agent processQ8Partial — requires tenant-specific allowlist tuning before it is reliable
Exposure — vulnerable version presenceUnpatched agent binaries running fleet-wideQ1, Q2Partial — Falcon process telemetry cannot read a semantic version; true exposure measurement needs Discover/Spotlight software inventory alongside these queries

See §11 for the full Detection Validation Gates (telemetry readiness, benign baselining, positive testing, and the promotion criteria for Q5/Q6/Q7 into Custom IOAs).

16

Hunt Summary Ticket

TITLE:      Plugin4Shell — Multi-Vendor AI Coding Agent Plugin SHA-Pinning Bypass (0-Click RCE)
SEVERITY:   High — zero-click RCE across 4 major AI coding agents; no confirmed
            in-the-wild exploitation as of 2026-09-18
SCOPE:      Endpoints running Claude Code < 2.1.179, OpenAI Codex < 0.146.0,
            GitHub Copilot (any version, marketplace plugins enabled),
            Gemini CLI (any version)
HYPOTHESIS: An attacker-controlled plugin repository resolves a SHA-pinned
            checkout to a branch (Claude Code / Codex / Copilot) or to a default
            branch named FETCH_HEAD (Gemini CLI), delivering malicious code
            through a trusted, already-installed plugin during background
            auto-update, with no user interaction required.
QUERIES:    8 CQL hunts (Q1-Q8); 3 Custom IOA candidates (Q5, Q6, Q7)
DO FIRST:   1. Patch Claude Code to >=2.1.179 and Codex to >=0.146.0 fleet-wide.
            2. Run Q1 to inventory hosts running any of the four agents.
            3. Restrict plugin marketplace hosts to GitHub-only wherever
               feasible (§12/§13 Playbook B) — structurally blocks the
               branch-name bypass variant.
FINDINGS:   REPLACE_WITH_your findings after running Q1-Q8 in your tenant
GAPS:       No EDR visibility into marketplace/repo-side branch creation (the
            actual "rug-pull" happens off-endpoint, §15); Falcon process
            telemetry has no semantic-version field, so Q1/Q2 require
            cross-reference with Discover/Spotlight software inventory.
ACTIONS:    Track Claude Code/Codex patch compliance; track Copilot/Gemini CLI
            marketplace-host exposure until Microsoft/Google ship or formally
            decline a fix; enable IOA-1/IOA-3 (Q5/Q7) in Detect mode fleet-wide.
OWNER:      REPLACE_WITH_owning_team
VERSION:    v0.1 (Draft) · 2026-09-18
17

Changelog

v0.12026-09-18Initial build from Air Security's Plugin4Shell disclosure (2026-09-17/18). 8 CQL hunt queries across exposure, plugin-update activity, post-exploitation, credential access, and exfil; 3 Custom IOA candidates. No confirmed in-the-wild exploitation and no published campaign IOCs at time of writing — pack is behavioral/exposure by design.
18

References

TierSourceUsed ForAccess Date
1Air Security — "Plugin4Shell - Zero Click RCE Vulnerability found in top four coding agents"Primary technical research; attack chain; timeline; vendor patch status2026-09-18
2Help Net Security — "Zero-click RCE vulnerability hit four major AI coding agents, two remain unpatched"Corroboration; researcher quotes2026-09-18
2The Register — "AI coding agents' 0-click RCE flaw could hand attackers keys to the kingdom"On-record GitHub statement; Copilot exposure detail; Microsoft non-response2026-09-18
3Mallory.ai — Plugin4Shell story summaryCross-check of vendor table, timeline, researcher names2026-09-18
1Claude Code — Official ChangelogConfirms version 2.1.179 exists (dated 2026-06-16)2026-09-18
1OpenAI Codex — GitHub Release rust-v0.146.0Confirms version 0.146.0 and the fix commit "Verify Git plugin SHA checkouts"2026-09-18
1Google Developers Blog — Gemini CLI to Antigravity CLI transitionConfirms Gemini CLI deprecation and Enterprise/Standard license carve-out2026-09-18
1Claude Code Docs — Discover and install prebuilt pluginsConfirms Bitbucket/self-hosted marketplace support; confirms ~/.claude/plugins/cache path2026-09-18
3OpenAI Codex Docs — PluginsGeneral plugin-directory context (did not confirm an exact cache path)2026-09-18

All 9 sources above were saved as plain-text snapshots at build time and scanned for prompt-injection content directed at an AI research agent. No injection attempt was found in any source. Given that Plugin4Shell's subject matter is an attack on AI coding agents themselves, this check was treated as mandatory rather than optional for every fetched page.