AI 编程工具会反复 hallucinate 出相同的虚假包名,攻击者据此注册同名 npm/PyPI 包进行供应链攻击,概率高达 85%。
AI 编辑器会编造根本不存在的包名,而攻击者则会在 npm 和 PyPI 上注册这些确切的名称。
你的依赖扫描器报告零发现,因为三个月前发布的包没有 CVE 历史可以匹配。
修复方法是在安装前检查包是否有历史,而不是安装后再扫描。
上个月我向 Cursor 要了一个 codemod 工具。它给了一个自信的安装命令和一个五行使用示例。包名看起来没问题,听起来也像是真实存在的。
它确实存在。这就是问题所在。
有人注册了这个名字,因为他们知道模型会不断编造它。去年七月,研究人员发表论文后,这种攻击有了一个名字:特拉维夫大学 Ben Nassi 团队的 Aya Spira 和同事们,与 Technion 的 Stav Cohen 以及 Intuit 的 Ron Bitton 一起,将其称为 HalluSquatting。大多数开发者称之为 slopsquatting。他们的发现是,助手不会随机产生幻觉。同一个问题问足够多次,相同的错误名称会在高达 85% 的仓库请求中返回。这不是噪音。这是一个稳定的、可预测的目标,攻击者可以注册一次然后坐等。
Aikido 的 Charlie Eriksen 在一月已经在野外发现了一个:react-codeshift,这个包最初是幻觉产生的,最终被 237 个代码项目引用。
漏洞不在 AI 写的代码里。它在安装命令里,看起来完全正常。
# Cursor suggested this. It runs without a single warning.
npm install react-codeshift
{
"dependencies": {
"react-codeshift": "^1.0.0"
}
}
这里没有任何东西会触发 linter、类型检查器或代码审查。npm install 在你读完一行之前就运行了包的安装脚本。等你注意到 package.json 里的依赖时,它已经在你机器上执行过了。
模型生成包名的方式和生成其他内容一样:通过预测合理的 token,而不是检查注册表。像 react-codeshift 这样的名字正是真实包会用的名字,这也是模型生成它的原因,也是代码审查时没人眨眼的原因。
第二部分是人们忽略的部分。幻觉是一致的。同样的提示会从同一个模型中反复拉出相同的编造名称,所以攻击者不需要猜测。他们查询助手几十次,收集它不断编造的名字,然后注册。模型免费为他们做了目标定位。
而 agent 循环则缩小了差距。开发者过去必须复制名字、搜索、然后决定。具有终端访问权限的 agent 会读取建议并直接运行。没有任何时刻有真人查看这个字符串。
在安装前检查包是否有历史。五秒钟的注册表元数据胜过安装后运行的任何扫描。
# Before installing anything an AI suggested
npm view react-codeshift time.created
# Errors out? The package does not exist. That is the good outcome.
# Created last month, 40 weekly downloads? That is the attack.
关闭安装脚本,这样错误是可以恢复的而不是即时发生:
npm config set ignore-scripts true
npm ci --ignore-scripts
Python 有一个更强的版本,因为 pip 可以拒绝任何你没有预先确认过哈希的包:
# requirements.txt
requests==2.32.3 \
--hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6
pip install --require-hashes -r requirements.txt
一个幻觉出来的包无法进入哈希锁定的文件,因为你必须自己记录它的哈希。
一件人们高估其作用的事:lockfile。Lockfile 忠实地记录你第一次安装的任何东西,包括恶意的东西。它阻止漂移,但不阻止初始安装。
Q: lockfile 能保护我免受 slopsquatting 攻击吗?A: 只能在事后。它锁定你已经安装的东西,所以防止版本 later 变化,但首次安装一个幻觉名称才是让你被入侵的原因,而 lockfile 会忠实地记录它。
Q: 为什么我的依赖扫描器报告这个包是干净的?A: 因为 CVE 数据库是向后看的。一个三周前注册用来捕获幻觉的包没有 CVE、没有 advisory、没有报告的恶意软件,所以针对已知漏洞匹配的扫描不会返回任何东西。
Q: 我如何区分幻觉包和真实包?A: 在安装前检查它的创建日期和下载历史。你的 AI 推荐的真正依赖会有数年的发布历史和真实的下载量。Slopsquat 只会有几周。
我想在这里直说工具的事,包括我自己的。我在 Cursor 和 Claude Code 里把 SafeWeave 作为 MCP server 运行,它的依赖扫描器和其他人一样是 CVE 匹配器。它不会标记上周才注册的包,因为目前还一无所知。它能捕获的是 agent 在同一会话中留下的其他东西——硬编码的密钥、未参数化的查询、缺失的 auth 检查。对于 slopsquatting 特定的控制,上面说的注册表年龄检查才是有效的。在安装前运行,而不是安装后。