資安公司 Air 週四揭露一項漏洞,攻擊者可在使用 AI 程式助理的開發者機器上取得遠端程式碼執行權限,而且完全不需要使用者操作。這項漏洞在該公司的研究報告中被命名為 Plugin4Shell,影響 Anthropic 的 Claude Code、OpenAI 的 Codex、GitHub Copilot 與 Google 的 Gemini CLI。
四家業者中只有兩家推出修補。Anthropic 在 Claude Code 2.1.179 修正,OpenAI 則在 Codex 0.146.0 修正;Microsoft 尚未為 Copilot 釋出任何更新,Google 則表示不會為已停止維護的 Gemini CLI 修補。
整個攻擊完全沒有碰到模型,也沒有碰到代理的推理流程。它躲在下一層,也就是把附加元件送進工作筆電的市集管線裡,而外掛程式會以操作代理的工程師所擁有的權限運行。
重點摘要
- Air 研究員 Or Nevo、Dor Granat 與 Niv Hoffman 在 Claude Code、Codex、GitHub Copilot 與 Gemini CLI 中,發現同一個被略過的驗證步驟。
- Anthropic 已於 Claude Code 2.1.179 修正,OpenAI 於 Codex 0.146.0 修正;Microsoft 未為 Copilot 釋出更新,Google 也不會修補已停止維護的 Gemini CLI。
- Claude Code 與 Codex 預設開啟的背景外掛自動更新,讓這場攻擊連「點一下」的條件都不需要。
SHA 釘選本該終結這個問題
釘選之所以出現,是因為替代做法早已公開失守。大部分證據來自 Air 自己先前的研究:該公司刻意發布到可信市集的惡意技能,觸及超過 2 萬 6000 個代理;後續研究更劫持了 925 個已在使用中的技能,影響 13 萬 4000 個代理。業界的回應是不再信任名稱——分支或版本標籤可以移動,40 字元的提交雜湊則不行。
這個推論本身沒有問題,而失守的正是這個推論。釘選只有在有人檢查結果時才提供保證,但負責安裝的用戶端程式碼檢查的卻是「請求」而非「結果」。走得最遠的企業反而承受了最完整的風險:那些審查外掛原始碼、釘選已審核提交、把雜湊視為稽核紀錄的組織,整套控制措施恰恰全都押在被略過的那一步上。
驗證是在哪裡消失的
git 對於分支可以叫什麼名字異常寬鬆。它自己的參照格式驗證器會接受由 40 個十六進位字元組成的名稱;當一個字串同時是有效參照又像是合理的物件 ID 時,git 會選擇參照,並把這個衝突降級成沒人會看的警告。因此,掌握外掛儲存庫的攻擊者只要建立一個名稱與釘選雜湊逐字相同的分支,把它提升為儲存庫預設分支,就能在代理回報「已成功取得預期提交」的同時,讓自己挑選的內容順利安裝。Claude Code、Codex 與 GitHub Copilot 都栽在這個變體上。
Gemini CLI 則是從另一道接縫裂開。它正確抓取了釘選的物件並寫入儲存庫的 FETCH_HEAD 檔案,接著卻以名稱的方式對 FETCH_HEAD 執行 checkout,而惡意儲存庫大可把這個名稱宣告成自己的預設分支,那一刻正確抓取到的提交就被直接丟棄。
要堵住這兩種變體,只需要一道判斷:在 checkout 完成後解析 HEAD,與原本請求的雜湊比對,不一致就中止。關鍵差別在於檢查「解析後的結果」而非「所請求的參照」,而 Gemini 的變體閃避的正是這一點。
自動更新這個放大器
只發生在安裝當下的漏洞已經夠嚴重,這次更糟,因為代理會按自己的排程重新執行同一段 checkout。Claude Code 與 Codex 預設會在背景更新已安裝的外掛,因此上游把雜湊換掉後,不需要安裝動作、不會跳出提示、也沒有任何可見事件就完成擴散。���擊者根本不必說服任何人安裝什麼——他需要的外掛早已躺在目標機器上,而且早已被信任。
由此衍生兩條入侵路徑,兩者都不需要攻破市集。攻擊者可以發布一個真的好用的東西,通過審查後再更換內容;也可以接管別人所寫外掛背後的儲存庫,而這正是釘選機制當初要防堵的情境。這兩半都已分別被驗證過,也因此整條攻擊鏈是可信的,而非紙上談兵。
兩家修了,兩家沒修
Air 在 6 月依協同揭露程序通知四家業者,回應卻大不相同。Anthropic 與 OpenAI 推出修補。Google 拒絕處理,告訴研究人員 Gemini CLI 已停止維護,並引導使用者改用 Antigravity 環境——該環境根本沒有可供破解的市集外掛釘選機制。研究人員表示,Microsoft 自始至終沒有回應。
GitHub 則否認自身受影響。發言人告訴 The Register,平台會阻擋形似提交雜湊的分支與標籤名稱,因此該手法在其平台上行不通。Air 的回應是,代理使用的市集並不限於託管在 GitHub 上:Anthropic 的文件就把 Bitbucket 與自架 git 列為支援的後端,而這些平台會照常接受雜湊形狀的分支名稱。考量 Microsoft 宣稱 Copilot 在財星 500 大企業的採用率約九成,未修補的受攻擊面並不小。
這對外掛治理意味著什麼
令人不安的結構性重點是:沒有任何市集能替使用者修好這個問題。釘選是在用戶端評估的,因此市集所宣稱的保證,最終是在它沒有任何程式碼在執行的地方被執行。這推翻了當前許多企業採購的前提——把通過核准的市集當成控制邊界。供應商中立的 Agent Plugins 標準這類努力或許能有所幫助,因為它讓驗證行為成為可規範的規格,而不是各家自行決定。就目前而言,實務建議很明確:更新 Claude Code 與 Codex;至於 Copilot 與 Gemini CLI,先盤點裝了什麼、託管在哪裡。關注過帶著有效簽章汙染 444 個 npm 套件的 ChainDrop 蠕蟲的人,會認出同樣的模式——完整性機制確實存在,而「存在」被誤當成了「有在執行」。
常見問題
我的 AI 程式代理會受 Plugin4Shell 影響嗎?
如果你使用 Claude Code、OpenAI Codex、GitHub Copilot 或 Gemini CLI,並安裝了來自市集的外掛,就處於曝險狀態。Claude Code 2.1.179 與 Codex 0.146.0 已含修正,更新即可堵住這兩者;Copilot 與 Gemini CLI 目前沒有可用的修補。
只使用託管在 GitHub 上的外掛就安全嗎?
只安全一部分。GitHub 會拒絕形似提交雜湊的分支與標籤名稱,能在該平台上擋下主要變體。但 Air 研究人員指出,代理同樣支援 Bitbucket 與自架 git 伺服器上的市集,在那裡這套手法依然有效;而且 GitHub 的規則對另一個獨立的 Gemini CLI 變體毫無作用。
市集有辦法自行解決嗎?
沒有。被釘選的提交是在代理執行 checkout 時、於用戶端機器上完成解析,因此只有代理端的驗證步驟才能保證釘選確實生效。市集可以限制允許哪些 git 主機,但那只是縮小支援的組態範圍,並未堵住底層缺陷。






