ARTICLE · 1104404
速查!你的 AI 编程插件可能正在执行恶意代码,Codex、Claude Code 等无一幸免

现在写代码,人人都应该装了 Claude Code、Codex 等等这类AI辅助开发工具,本身工具就已经很好用了,加上支持装各种插件 skill;一个小功能包,丢进工具里就能扩展能力,像什么代码审查和部署脚本、UI 布局美化等等,只要你需要的,插件市场都能找的到。插件从市场装;市场也有一套安全机制,代码审核通过后锁定版本,理论上你装的永远是审核过的那份。
但前段时间安全公司 Air Security 披露的 Plugin4Shell 漏洞证明,当下 skill 的这套机制是能被绕过的;你装好的哪些插件,可以在你不知情的情况下被换成恶意代码,这个过程,不需要点击,也不需要授权,静默运行。Claude Code、Codex、GitHub Copilot、Gemini CLI 这几个常用的工具全中招,刚好这些又是大家常用的工具。
不装插件是不是就没事? 是,如果你没装过插件,那可以关掉文章了,这个漏洞和你们啥关系。
插件会自动偷偷安装吗? 不会。装永远是你主动的操作的,不存在静默安装插件的情况。
那危险在哪? 在"自动更新"。Claude Code 和 Codex 默认在后台静默更新已装好的插件;如果插件背后的仓库被攻击者控制、利用,那么恶意版本就会趁更新被拉到你机器上。没有弹窗,没有提示,一切都是静悄悄的发生。
◇ 怎么判断你的插件有没有风险
不是任何插件都会中招。中招要同时满足两个条件:
1. 插件的源仓库被攻击者控制了。 要么作者本来就是坏人,先发干净的攒用户,然后悄咪咪的再动手脚;要么仓库被劫持。安全公司实测纰漏,925 个插件被劫持,影响 13 万个客户端。
2. 仓库托管在 GitHub 之外。 漏洞利用的是 Git 分支名可以伪装成版本号的特性;GitHub 直接禁止这种分支名,所以仓库在 GitHub 上的插件是安全的。风险主要是在一些自建 Git 服务器托管的插件。这个也是安全团队实测核查过:官方默认市场里的插件仓库全部在 GitHub 上,如果你是在 GitHub 下载安装的插件,那是没有问题的。
文章末尾给了一段自检代码,可以自行排查一下你当前的环境;
◇ 如何入侵的
其实这个过程说起来一点也不麻烦,市场锁定插件版本用的是 commit 哈希;工具下载时执行 git checkout <哈希>,但只是校验了这个这个值,但是并没有验落盘的代码是不是就是这个哈希。
攻击者在自己控制的仓库里,建一个名字恰好等于锁定哈希的分支,指向恶意代码并设为默认。Git 解析时优先匹配分支名,拉下来的就是恶意代码;工具还报告"锁定校验通过"。再叠加后台自动更新,整条攻击链零点击完成。
恶意代码到你本地之后,就可以以你的权限运行;文件、SSH 密钥、云凭证,在内网系统下,几乎就如梭不能了。
◇ 解决方式
目前 Claude Code、CodeX 已经修复了相关问题,能升级的马上升级,没修复的,需要在可靠的仓库去安装可靠的插件。
按你用的工具对号入座:
claude --version 查一下 | ||
再补三个动作:
清点插件。 看看自己和团队装了哪些,仓库托管在哪;非 GitHub 托管的重点排查一下,可疑的、不常用的,先卸载掉。
下面是一段 python 的自检代码,可以根据自己实际的使用情况和使用版本,自查一下
Python#!/usr/bin/env python3# check_plugin_pins.py —— Plugin4Shell 自愈式自查import subprocess, json, os, sys# 你的插件根目录(Claude Code 常见路径示例,按实际改,其他工具,就制定成对应的路径)PLUGIN_ROOT = os.path.expanduser("~/.claude/plugins")# 期望的 pin 映射:插件名 -> 期望 SHA(从市场记录里自己搬过来)EXPECTED_PINS = {"my-audit-skill": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2",}defactual_head(repo: str) -> str:try:return subprocess.check_output( ["git", "-C", repo, "rev-parse", "HEAD"], stderr=subprocess.DEVNULL, ).decode().strip()except Exception:return"<unknown>"defmain(): bad = []for name, pinned in EXPECTED_PINS.items(): repo = os.path.join(PLUGIN_ROOT, name)ifnot os.path.isdir(repo):print(f"[skip] {name} 未安装")continue head = actual_head(repo) ok = head == pinned flag = "OK "if ok else"BAD"ifnot ok: bad.append((name, head))print(f"[{flag}] {name}: pinned={pinned[:10]}... head={head[:10]}...")if bad:print(f"\n发现 {len(bad)} 个插件 HEAD 与 pin 不符,疑似被静默替换!") sys.exit(1)print("\n全部插件 HEAD 与 pin 一致。")if __name__ == "__main__": main()团队环境关掉插件静默更新。 个人用户升级到修复版后无所谓;管团队的话,建议给插件更新加一道审批。
收紧凭证。 插件继承你的权限,那就把权限收紧;SSH 私钥、云凭证别裸放开发机。就算哪天被换,损失也有边界。
◇ 最后
技术上这不是什么高深漏洞,也不陌生,但信号很明确;AI 插件生态正在重演 npm 链路攻击的这类老剧本。N年前我们学会看好依赖,现在轮到看好 AI 的插件了。