AIコーディングエージェント4製品に「Plugin4Shell」 固定したはずのプラグインが、確認されないまま差し替わる
9月17日、セキュリティ企業Air Securityが、Claude Code・OpenAI Codex・GitHub Copilot・Gemini CLIの4製品に共通する脆弱性「Plugin4Shell」を公開しました。マーケットプレイスがプラグインを特定のコミットに固定(SHAピン留め)しても、エージェントは「本当にそのコミットに着地したか」を確認していない。攻撃者がSHAと同じ名前のブランチを既定にすると、固定の表示はそのままに別のコードが入り、自動更新が既定のため利用者の操作なしで実行される、と。Airによれば、Claude Codeは6月、Codexは8月に修正済み。Copilotは未修正、Gemini CLIは非推奨で修正されない。当サイトの芯——宣言と挙動は別——が、今度はプラグインの配布経路で起きた話です。
まず時系列で(誰が何をしたか)
- 1. 2026年5月 — Air Securityの研究チームが脆弱性を発見。4製品すべてで動く概念実証(PoC)を作成。
- 2. 6月 — Airが4社(Anthropic・OpenAI・Microsoft・Google)に協調的開示で通知。
- 3. 6月17日 — AnthropicがClaude Code 2.1.179で修正を確認(Airの時系列による)。
- 4. 8月4日 — Googleが「Gemini CLIは非推奨のため修正しない。Antigravityへ移行を」と回答(同)。
- 5. 8月12日 — OpenAIのCodex 0.146.0で修正を検証(同)。
- 6. 9月17日 — Airが公開。Microsoft(GitHub Copilot)は修正を出していない、とAirは書いています。
つまり、見つけたのは外部の研究者、直したのは2社、直していないのが1社、直さないと決めたのが1社。公開の3か月前から、修正済みの製品では更新すれば守られる状態でした。
3行で捉える
- 何が起きた: プラグインの「このコミットに固定する」という宣言が、4製品とも着地の確認なしで運用されていた。攻撃者がSHAと同名のブランチを既定にすれば、固定表示のまま別のコードが入る。
- どう読む: 自動更新が既定(Claude Code・Codex)なのでゼロクリック。しかもマーケットプレイス側では塞げない。固定を解決するのはエージェントの内側だから。修正は「着地したHEADが固定値と一致するか確かめる」一行です。
- 次に見る: Copilotの修正と、Gemini CLI利用者の移行。そして、自分のエージェントの版数。Claude Codeは2.1.179以上、Codexは0.146.0以上か。
所属テーマ
何が壊れていたのか——固定は書かれるが、確認されない
コーディングエージェントは、マーケットプレイスからプラグイン(スキルや拡張)を取り込みます。このとき安全のために使われるのがSHAピン留めです。プラグインの元になるgitリポジトリの特定のコミット(40桁のハッシュ)をマーケットが記録し、「審査したのはこの版で、入るのもこの版」と保証する。あとで元のリポジトリが書き換えられても、固定した版しか入らない——はずの仕組みです。
Airが見つけたのは、その保証が最後の一歩で抜けていることでした。Claude Code・Codex・Copilotは、リポジトリを取得したあと、固定されたハッシュを指定してcheckoutする。ところがgitは、同じ名前のブランチとコミットがあると、ブランチを優先します(警告は出るが止まらない)。攻撃者がリポジトリを掌握し、固定ハッシュと同じ40桁の名前のブランチを作って既定にすると、checkoutはそのブランチに着地する。エージェントは「固定したコミットで入れました」と報告しながら、実際にはブランチの中身、つまり攻撃者のコードが動く。固定したコミットそのものは、手つかずのままでかまいません。
Gemini CLIは手順が違いますが、同じ穴です。固定したコミットをfetchしてからFETCH_HEADをcheckoutするのですが、リポジトリの既定ブランチを「FETCH_HEAD」という名前にしておくと、取得したコミットは捨てられ、ブランチの中身が入る。
どちらも、「固定した」と書くところまではやっていて、「固定どおりに着地したか」を確かめていない。Airが示す修正は一行です。checkoutのあと、作業ツリーの実際のHEADを解決し、固定値と一致しなければ中止する。要求したものではなく、着地したものを確かめる——これがGemini版をすり抜けさせない要点だ、と。
なぜ「ゼロクリック」なのか——自動更新が既定だから
この穴だけなら、「新しいプラグインを入れさせる」手間が要ります。それを不要にするのが自動更新です。Claude CodeとCodexは、既定で、入れたプラグインを背景で更新する。だから攻撃の筋は、こうなります。
まず本当に無害なプラグインを、信頼されたマーケットに登録し、審査を通す。使われる。次に、やはり無害な更新版を出し、マーケットの固定を新しいコミットに書き換えてもらう(これも審査を通る)。そのうえで、新しい固定ハッシュと同じ名前のブランチを作り、既定にして、中身を悪意あるコードに向ける。固定が変わったので、各利用者のエージェントが背景で更新を走らせる。checkoutはブランチに着地する。利用者は何もしていません。入れる操作も、確認も、気づく場面もない。
もう一つの筋は、他人の正規のプラグインのリポジトリを乗っ取ることです。Airは、以前の研究(SkillJacking)で削除・改名されたアカウント名を再登録してリポジトリを乗っ取る手口を実際に示しており、それとPlugin4Shellをつなげば、乗っ取りから全利用者への配布までが一本の線になる、と書いています。
そして重要なのは、マーケットプレイス側では、この穴を完全には塞げないことです。固定の解決はエージェントの内側で起きるので、保証をうたっているマーケットが、その保証を守る手段を持っていない。直せるのは、エージェントを作った会社だけです。
誰が直し、誰が直していないか
Airの記述によれば、対応は割れています。
Anthropic(Claude Code)は6月17日に2.1.179で修正を確認。OpenAI(Codex)は8月12日に0.146.0で修正を検証。この2製品は、公開の3か月前・1か月前に、更新すれば守られる状態になっていました。
Microsoft(GitHub Copilot)は、同じ欠陥を通知されたが修正を出していない、とAirは書いています。利用者に当てるパッチがない状態です。
Google(Gemini CLI)は、製品自体を非推奨にしており、修正しない。利用者はAntigravityへ移行を、と。Airは、Antigravityにはマーケットのプラグイン固定がそもそもないので、この攻撃は届かない、としています。
当サイトが追ってきた流れで言えば、これは「同じ穴を、全社が作っていた」話です。一社の実装ミスではなく、業界共通の設計の抜け。そして直すかどうかは、各社の判断に委ねられ、実際に割れた。
割り引いて読むところ
技術的な指摘は具体的で、修正の一行まで示されています。そのうえで、冷静に見る点を並べます。
1. 発表元は、商業ベンダーです。Air Securityは、エージェント向けの安全製品を売る会社で、公開文には自社のAir MarketplaceとAir Filterを使う企業は影響を受けなかった、と自社製品の宣伝が入っています。「数百万のエージェントが影響」という規模感も、Airの見積もりです。指摘の中身は検証可能な技術情報ですが、規模の数字と製品の売り込みは、分けて読むのが安全です。
2. 前提条件があります。攻撃者がプラグインのリポジトリを掌握していること、そしてブランチ変種では、リポジトリのホストがハッシュと同じ名前のブランチを許すこと。Air自身が、GitHubは40桁のブランチ名を拒否すると書いています。許すのはBitbucketや自前のgitサーバー。つまり、プラグインの元リポジトリがGitHubにあるなら、ブランチ変種の対象外です(Gemini CLI変種は別)。「全利用者が等しく危険」ではありません。
3. 実被害の主張はありません。公開文が示しているのは、研究チームの概念実証と、以前の研究での乗っ取りの実演です。この穴が実際の攻撃に使われた、とは書かれていません。
4. 各社の対応状況は、Airの記述です。Copilotが未修正、Gemini CLIが修正しない、という部分は、当サイトがMicrosoftとGoogleの公式発表で確かめたものではありません。Airの時系列に基づく記述として読んでください。
読者への影響
ここは、今日の時点で直接の影響があります。コーディングエージェントにマーケットのプラグインを入れているなら、今日確かめる価値があります。
Claude Codeなら、2.1.179以上か。Codexなら、0.146.0以上か。更新していれば、Airの記述どおりなら守られています。GitHub Copilotは、Airによればパッチがないので、マーケットからのプラグインを絞る・自動更新を止める・GitHub外のホストからは入れない、といった運用側の手当てが当面の防御です。Gemini CLIは、Googleが修正しないとされているので、移行を検討する。
そして、この話の芯は、版数より一段上にあります。「固定した」という表示と、「固定どおりに入った」という事実は、別のものです。当サイトはこの数週間、宣言と挙動は別と書いてきました(行動規範の話、引き継ぎ要約の話)。今回は、それがモデルではなく配布の仕組みで起きた。社内でプラグインやスキルを配るとき、「審査した版を固定した」で終わらせず、「入った版が固定と一致するか」を、入った側で確かめる。エージェントの権限設計(ガイド)と、外から仕込まれた指示への備え(プロンプトインジェクションとは)と並ぶ、三つ目の入口です(サプライチェーン攻撃とは)。
次に見ること
第一に、MicrosoftとGoogleの公式の反応。Copilotに修正が出るか。Gemini CLIの利用者への案内が公式に出るか。
第二に、マーケットプレイス側の対応。Airは「マーケットでは完全には塞げない」としつつ、ハッシュ名のブランチを拒むホストに限る、という部分的な緩和にも触れています。各マーケットが何をするか。
第三に、同型の穴が、スキルやMCP(解説)にもあるか。Airは今回を、AIエージェントのエコシステムで最初のサプライチェーン脆弱性であり、配布の層を攻めるもの、と位置づけています。最初、ということは、次がある前提です。
前後の流れ
サプライチェーン攻撃とは / ツールポイズニングとは / プロンプトインジェクションとは / MCPとは / Claude Codeとは / AIエージェントの権限設計 / 週次: 検算する人を、雇いはじめた週