一个 40 位的分支名,让四款最火的 AI 编程助手在没人点击任何东西的情况下,执行了攻击者的代码
一、先说最反直觉的一点:这次你不需要点任何东西
2026 年 5 月,安全公司 AIR Security 的研究员在实验室里做了一件听起来很无聊的事:他们建了一个 git 分支,分支名是一串 40 位的十六进制字符。
然后,市面上最主流的四款 AI 编程助手——Anthropic 的 Claude Code、OpenAI 的 Codex、GitHub 的 Copilot、Google 的 Gemini CLI——全部在他们面前执行了任意代码。
没有弹窗,没有确认框,没有任何一次点击。
这个漏洞在 9 月 17 日被公开,代号Plugin4Shell。AIR Security 给它的定性是:AI agent 生态系统的第一个供应链漏洞。
注意这个措辞。过去两年,围绕 AI 安全的讨论基本都在两个层面打转:要么研究模型本身(提示注入、越狱、对齐失败),要么研究 agent 本身(它会不会自己乱来)。Plugin4Shell 走的是第三条路——它攻击的是 agent 底下那层分发管道:插件市场。
而这条管道,是通向数百万台机器的。
二、先讲清楚"插件"为什么危险
要理解这个漏洞的分量,得先理解 AI 编程助手现在是怎么工作的。
今天的 coding agent 早就不只是一个聊天框了。它可以装插件、装 skill、装扩展,这些扩展通常来自社区市场。装上之后,它们继承开发者本人的权限——本地源码、云凭证、SSH 密钥、内部仓库、生产系统、各种密钥。
换句话说:你给 agent 装一个插件,本质上是在自己的机器上、用自己的身份,跑了一段别人写的代码。
这本来不是新鲜事,npm、PyPI、VS Code 插件市场都是这个逻辑。行业对此的标准答案是SHA pinning(提交哈希锁定):
市场在审核完一个插件之后,把它锁死到某一个具体的 git commit 哈希上。以后 agent 安装时,只装这个哈希对应的代码,而不是"最新版"或"被改过的版本"。审一次,永远只跑那一份。
这套机制的设计初衷非常明确:防止"rug-pull"(先伪装、后投毒)。你先审一个干净版本,等大家装完了,再偷偷把仓库换成恶意代码——SHA pinning 就是专门堵这条路的。
Plugin4Shell 干的事,就是让这套机制表面上完全正常地失效。
三、一个分支名,为什么能骗过 git
漏洞的根因说出来简单到有点荒唐:
这些 agent 会让 git 去 checkout 那个被锁定的 commit,但从来不检查最后落到工作区里的到底是不是它。
用命令表示,agent 干的是这件事:
git clone <插件仓库> ./git checkout aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
第二行的aaaa...就是市场锁定的那个 40 位哈希。看起来没问题。
但 git 有一个很多人不知道的行为:当一个名字既是一个合法的引用(ref),又是一个对象 ID 时,git 优先选择引用,只在旁边打印一句refname is ambiguous的警告,然后继续。
于是攻击者只要做两件事:
- 在自己控制的插件仓库里,建一个名字正好等于那 40 位哈希的分支
- 把这个分支设为仓库的默认分支,让它指向恶意代码
之后那句git checkout aaaa...就会解析到这个分支上,而不是那个 commit。被锁定的 commit 本身甚至可以完全不动、干干净净地留在仓库里——它只是不再被使用而已。
而且git clone会把默认分支作为本地分支拉下来,所以攻击者连"让受害者主动 fetch"都不需要。
两个前提条件都不难满足:
- 分支名可以是 40 位十六进制。git 自己的
git check-ref-format是接受这种名字的。GitHub 明确拒绝形如哈希的分支名,但Bitbucket 和任何自建 git 服务器都允许——而 Anthropic 自己的文档里,就把 Bitbucket 和自建 git 列为合法的插件市场后端。 - 这个分支必须是仓库的默认分支。如果不是默认分支,它只会被当作远端跟踪引用拉下来,checkout 会老老实实回退到 commit 上。
所以准确地说:这不是"某个市场的配置失误",而是 git 的默认行为和 agent 缺失的那一次校验,正好撞在了一起。
四、四款产品,犯的是同一个错
AIR Security 强调了一点:这不是某一家的实现失误。
同一个设计错误,出现在每一个受影响的 agent 里。不是某个产品写错了代码,而是一个错误在整个行业里被重复了四遍。
这种"大家都不约而同漏掉同一件事"的情况,在软件史上通常意味着两件事:一是这个错误足够隐蔽,二是它造成的暴露面足够大。四款 agent 覆盖的是当前 AI 编程工具市场的绝大部分份额,潜在受影响的 agent 实例以百万计。
五、Gemini CLI 的另一种死法
Claude Code、Codex、Copilot 走的是上面那条"分支名冒充哈希"的路径。Gemini CLI 的问题更隐蔽一点。
它的安装流程是三段:
git clone --depth 1 <插件仓库> ./git fetch origin 41d0bc0a4aeb2fbf797dacea39e876d98c95024bgit checkout FETCH_HEAD
第二行确实把正确的 commit 拉下来了,也记进了.git/FETCH_HEAD。看起来比前三个还严谨。
但第三行git checkout FETCH_HEAD并不一定要读那个文件。如果仓库的默认分支本身就叫FETCH_HEAD,checkout 会解析到这个分支上——刚刚 fetch 下来的那个正确 commit 被静默丢弃,工作区里留下的是攻击者默认分支里的内容。
同一个错误,换了一件衣服。
六、真正让它是"零点击"的,是自动更新
如果漏洞只发生在安装那一刻,危害还能控制——你不装新的就没事。
但 Plugin4Shell 之所以被定性为零点击,是因为插件会自动更新。
Claude Code 和 Codex 默认在后台自动更新已安装的插件。这意味着攻击链的最后一环根本不需要受害者参与:
- 投种:攻击者往可信市场提交一个货真价实的良性插件,通过审核,锁定在
aaa...aaa。 - 铺开:用户安装,每一次安装都锁在
aaa...aaa这个经过审核的版本上。 - 版本更新:攻击者推送一个例行更新——依然是良性的,市场把锁重新指向
bbb...bbb。 - 掉包:攻击者建一个名叫
bbb...bbb的分支,设为默认分支,指向恶意代码。被锁的那个 commit 本身纹丝不动。 - 自动更新到 RCE:锁变了,触发所有 agent 的后台自动更新。checkout 把
bbb...bbb解析成分支,恶意代码执行。
没有提示,没有点击,没有"要不要更新"的询问。
攻击者不需要说服任何人装新东西。他们只需要那个良性插件已经在你的机器上。
七、最刺人的一句话:你什么都没做错
这是整件事里最值得停下来想一下的地方。
你可能会想:这跟我有什么关系?我又不乱装插件。
但按 AIR Security 的说法,受害者不需要"乱装插件"。他们只需要满足一个条件:
装过一个来自可信市场的插件,而且这个插件经过了审核、并且按照安全模型的要求被正确地 pin 到了某个 commit。
也就是说,你把所有该做的都做对了,你依然在风险里。
对那些比社区市场更谨慎的组织来说,这一点尤其难堪。很多企业的做法是:不让员工随便用社区插件,而是自己审一遍、pin 到某个 review 过的 commit,再放行。
Plugin4Shell 让这一整套流程直接作废——审核通过,pin 写下了,但装上去的是另一份代码。所有建立在 pinning 之上的下游校验流程,一起继承了这次失败。
这也解释了为什么 AIR Security 在报告里写了一句挺重的话:
市场无法完全关掉这个洞。因为 pin 是在 agent 内部解析的,只有 agent 侧的修复才能恢复这个保证。
换句话说:这是客户端的问题,市场再努力也补不上。市场能做的只有一件事——把"名字长得像哈希的分支"这条路堵死,而那等于只允许 GitHub 一家托管(因为 GitHub 会直接拒绝 40 位十六进制分支名),顺带把 agent 官方支持的其他托管方式一起禁掉,而且对 Gemini CLI 那个变体毫无作用。
八、修了吗?两家修了,一家没修,一家弃疗
这是本次披露里最不好看的一段。
- Claude Code:Anthropic 修复,版本2.1.179
- OpenAI Codex:OpenAI 修复,版本0.146.0
- GitHub Copilot:AIR 把同样的缺陷报给了微软,截至披露时微软没有发布修复
- Gemini CLI:Google 表示 Gemini CLI已弃用,不会打补丁,建议用户迁移到 Antigravity
关于 Copilot,GitHub 的回应是:他们的平台会拦截"形如 SHA 的分支名和标签名"。
但 AIR Security 并不接受这个说法。他们的反驳是:市场可以托管在 Bitbucket 这类服务上,也可以是自建的 git 服务器——这些地方并没有这种拦截,所以仍然可以被利用。而前面说过,这些托管方式是被官方文档认可的正规配置。
至于 Gemini CLI,处境更尴尬:它不会再有修复了。每一个已经装了它的环境,就永久留在风险里。Google 给出的出路是迁到 Antigravity——Antigravity 没有插件 SHA pinning 这套东西,所以这个攻击够不到它。
顺便说一下,这个漏洞其实不是 9 月才发现的。完整时间线是这样的:
- 2026 年 5 月:AIR 研究实验室发现,并对四款 agent 都做出了可用的 PoC
- 2026 年 6 月:按协调披露流程告知四家厂商
- 2026 年 6 月 17 日:Anthropic 确认 Claude Code 2.1.179 已修复
- 2026 年 8 月 4 日:Google 确认不修,建议迁移
- 2026 年 8 月 12 日:验证 Codex 0.146.0 已修复
- 2026 年 9 月 17 日:公开披露
从发现到公开,四个月。两家修了,一家没修,一家决定让它就这么烂下去。
九、这不是孤例:这条管道已经被攻破过两次
Plugin4Shell 是 AIR Security 同一系列研究的第三篇。前两篇讲的是同一件事的不同阶段,而且都是实战验证过的:
- 《The Story of Skills》:他们造了一个恶意 skill 放进市场,看着它传播开,最终控制了超过 26,000 个 agent。结论是:把一个恶意插件塞进一个被信任的市场,根本不是最难的部分。
- 《SkillJacking》:连"塞进去"都不需要。925 个已经在被使用的 skill,被通过接管其背后的仓库而劫持,影响了134,000 个 agent。
再加上第三篇的 Plugin4Shell,这条链就完整了:
恶意插件可以轻易进入市场 → 已有插件可以被接管 → 而本该兜底的 pinning 机制可以被绕过。
三件事凑齐,就不是巧合了,而是这个生态的结构性问题。
十、同一个九月,还有这些事
Plugin4Shell 是九月网络安全新闻里最扎眼的一条,但不是唯一一条。把它放回这个月的背景下看,会更有意思。
Brevo 供应链攻击:10 万个网站被注入
9 月 14 日,邮件营销平台 Brevo(原 Sendinblue)被攻破。攻击者先窃取了一个长期有效的 Cloudflare API key,用它在 Cloudflare 上部署了一个恶意 Worker,然后通过它往这些地方注入脚本:brevo.com、sibforms.com,以及客户嵌在自己网站上的 3 个 JavaScript 文件。
注入的脚本会向特定访客弹出伪造的 Cloudflare “verify you are human” 页面,诱导访客复制粘贴并运行恶意命令。在装了 Brevo widget 的 WordPress 站点上,攻击者还尝试给已经登录的管理员安装恶意插件,直接种后门。
安全公司 Sansec 估算受影响的网站超过 10 万个,恶意 Worker 活跃了大约4 到 5.5 小时。
在这之前,9 月 10 日,同一批攻击者利用一个 SAML SSO 缺陷访问了138 个账户。加密钱包厂商Trezor是最初被攻陷的账户之一。
思科 ISE 零日:CVSS 满分 10.0
CVE-2026-76460,思科身份服务引擎(ISE)的 API 认证绕过漏洞,CVSS 评分 10.0。未认证的远程攻击者可以完全控制设备。
CISA 在 9 月 16 日把它加入了已知被利用漏洞目录(KEV),并且没有临时缓解措施。这是两天之内第二个被主动利用的思科零日——前一个是 Secure Email Gateway 的 CVE-2026-76461。
WeaselBiscuit:13 个恶意 npm 包
一个叫 WeaselBiscuit 的窃密木马,通过13 个恶意 npm 包传播,包括@biz44/*系列,以及engin1、id79-client、process-lhpm、process-mite、process-tailwind。
它的载荷从 Npoint 死投点拉取并在内存中执行,专门窃取Chrome 扩展的本地存储(Local Extension Settings 的 LevelDB 目录),Windows、macOS、Linux 三端通吃。在 Windows 上还能在 C2 指令控制下记录剪贴板和键盘。C2 地址是103.170.217.184:8787。
它的功能和朝鲜 DPRK “Contagious Interview” 组织的工具(BeaverTail、OtterCookie)高度重叠,不过目前没有确切的归因证据。
用 AI 造出的漏洞利用,打穿了 OpenAI 内部
这条最讽刺。
安全公司 Hacktron 的研究员用 Claude,为libheif库(被 ImageMagick 使用)的一个未修复漏洞开发出了可靠的利用代码。这个漏洞上游其实一年前就修了,但因为它从来没被标记为安全问题,所以没有分配 CVE,也就错过了正常的补丁流程。
利用路径是通过 Discourse 的 HEIC/HEIF 图片上传实现远程代码执行。再结合 OpenAI 侧一个登录 token 权限过大的缺陷——该 token 能对关联的 ChatGPT 和 Codex 账户获得完整的 API 访问权——研究人员最终接管了一名员工账户。而这名员工恰好把 Codex 接入了 OpenAI GitHub 组织的权限。
研究者在内部仓库开了一个 PR,然后就停手了。OpenAI 支付了漏洞赏金,并把图像处理的问题归给了第三方 Discourse,把 token 权限问题算作自己的。
西班牙:首例"代理式 AI"数据泄露
西班牙数据保护机构 AEPD 报告了该国第一例由代理式 AI 驱动的个人数据泄露。
AEPD 主席 Francisco Pérez Bes 描述的经过是:一个使用已知语言模型的 agent 扫描通用文件,成功登录,然后自主搜索应用漏洞;进入之后修改了个人数据、访问了发票。
不过 AEPD 的定性很克制:这是"把 AI 当作工具,串联攻击的不同阶段",背后有人类操作者指挥,而不是一个完全失控的自主系统。即便如此,它还是被称作一个"分水岭时刻"。
十一、那现在该怎么办
把上面这些事放在一起,能看出一个共同的形状:攻击面正在从"你写的代码"转移到"你依赖的东西"。
从 npm 包,到 CI/CD 流水线,到 Cloudflare Worker,到邮件营销平台的 JS widget,现在再到 AI 编程助手的插件市场。你写的代码可能一行问题都没有,但你的构建链上任意一环被换掉,结果都一样。
具体到 Plugin4Shell,能做的事情不多但很明确:
- 升级 Claude Code 到 2.1.179 及以上,Codex 到 0.146.0 及以上。这是唯一完整的缓解手段。
- 如果你在用 GitHub Copilot,目前没有补丁。这意味着你要么暂时控制插件来源,要么接受这个风险敞口。
- 如果你在用 Gemini CLI,它不会修了。该考虑迁移了。
- 盘点你的插件。你到底装了哪些?它们从哪来?背后是谁的仓库?这些仓库最近有没有换过所有者、改过默认分支?——注意,最后一问正是 SkillJacking 和 RepoJacking 的作案特征。
- 重新想一想"自动更新"这件事。这次漏洞能被定性为零点击,靠的就是它。自动更新买到的是省事,付出的是"你不再控制什么时候发生变化"。对持有生产凭证的 agent 来说,这笔账未必划算。
还有一句更本质的话值得记住。
过去我们习惯的安全模型是:审核一次,锁定版本,之后就可以信任。Plugin4Shell 打掉的正是"之后就可以信任"这半句——审核通过了,版本也锁了,但跑起来的是别的东西。
对正在把 AI agent 接进自己工作流的每一个团队来说,这大概是九月最需要消化的一课:当你把一个能读你源码、拿你密钥、连你生产环境的 agent 请进门,你实际上是把信任交给了一整条你根本看不见的供应链。
关于本文
本文事实依据来自:AIR Security 的原始披露《Plugin4Shell — Zero Click RCE Vulnerability found in top 4 most popular coding agents》(air.security)、Cyber Security News 的报道(cybersecuritynews.com)、Cyber Recaps 2026 年 9 月 18 日安全日报(cyberrecaps.com),以及其中引用的 SecurityWeek、Help Net Security、CyberScoop、The Hacker News、Infosecurity Magazine 等媒体报道。
漏洞时间线与版本号以 AIR Security 原始披露为准。截至本文发布,微软尚未就 GitHub Copilot 发布修复,Google 已确认 Gemini CLI 不会收到补丁。文中涉及的安全事件细节仍在持续演进,后续如有新的官方披露,以官方为准。
如果你也在用 AI 处理日常工作和资料整理,WorkBuddy 是我自己在用的一个选择——它把文档处理、数据分析和多步任务编排放在同一个对话里完成,省掉了很多在工具之间来回切换的时间。