每周1亿次下载的axios被投毒了,源码一行没动
今天上午我看到一条消息:axios 被投毒了。
我的第一反应和你们一样——不可能。axios 每周 1 亿次下载,npm 榜前十,谁敢动它?
然后我去翻了 GitHub issue,翻了安全公司的分析报告。越看越不对劲。
axios 的源码里,一行恶意代码都没有。
你盯着 GitHub 上的代码看,看一万遍,什么都发现不了。
问题根本不在源码里。
发生了什么
有人盗了 axios 维护者的 npm 账号,绕过 GitHub,直接往 npm registry 发了两版"官方" axios。
代码本身没动。只是在 package.json 依赖里偷偷加了一个包:plain-crypto-js。
你 npm install 的瞬间,这个包的 postinstall 脚本自动跑起来:
1. 检测你的操作系统
2. 下载远控木马
3. 连上攻击者服务器
4. 自我删除,把 package.json 替换成干净版本
你事后翻 node_modules,什么痕迹都没有。
这就好比你从五金店买了一把锁——品牌对、包装对、外观对,但到手之前就被人掉包了。普通漏洞是锁有缺陷,换一把就行。这次是锁在到你手里之前就被换了。
攻击时间线:精密得像一场手术
我把时间线拉出来,你们感受一下这帮人的手法:
T-18小时:攻击者先用小号发布了 plain-crypto-js@4.2.0。
注意,这个版本是干净的,内容就是正常 crypto-js 的复制品,零恶意代码。
为什么要先发一个干净版本?——建立发布历史。一个零历史的新包突然被大包依赖,会触发安全告警。先"养号",18 小时后再动手。
T-30分钟:发布 plain-crypto-js@4.2.1,注入恶意 postinstall 脚本。
T=0:用被盗的维护者账号,发布 axios@1.14.1。
T+39分钟:紧接着发布 axios@0.30.4。1.x 和 0.x 两条版本线,一次全覆盖。
T+3小时:npm 下架恶意版本,攻击窗口关闭。
18 小时预埋,39 分钟全覆盖两条线,3 小时后自动消失、痕迹自毁。
安全公司 StepSecurity 的评价是:"针对 npm Top 10 包有记录以来最精密的供应链攻击之一。"
还有个细节让你后背发凉:恶意载荷在 npm install 开始后 2 秒内就开始向攻击者服务器回传数据。比 npm 解析完其他依赖还快。你根本来不及按 Ctrl+C。
为什么 GitHub 上看不出问题
这里有个关键认知:npm registry 和 GitHub 是两个完全独立的系统。
你在 GitHub 上看到的代码,和你 npm install 装到的东西,可以完全不是同一个东西。
有维护者的 npm token,就能绕过 GitHub 的代码审查、CI/CD、所有你能看到的流程,直接往 registry 发包。
更讽刺的是:axios 所有合法的 1.x 版本都通过 GitHub Actions 的 OIDC Trusted Publisher 机制发布,有密码学签名,和 GitHub 工作流绑定。而这次中招的 1.14.1 是纯手动发布,没有 OIDC 绑定,没有 gitHead 可校验。
这个差异写在 npm registry 元数据里。但你平时装包的时候,查过 registry 元数据吗?
我也没查过。
你的项目中招了吗?三步自查
用了 axios 的项目,花 5 分钟跑一遍,不亏。
第一步:查 lockfile
打开 package-lock.json、pnpm-lock.yaml 或 yarn.lock,搜这三个关键词:
• axios@1.14.1
• axios@0.30.4
• plain-crypto-js
三个都没有?大概率安全,后面两步也建议做。
第二步:清缓存
Bash
npmcacheclean--force
踩坑预警:CI 环境也要清。 GitHub Actions、GitLab CI 的 node_modules 缓存和 npm 缓存里如果残留了恶意 tarball,下次构建还会命中。本地、CI,一个别漏。
第三步:锁死版本
JSON
"axios": "1.14.0"
注意是 1.14.0(固定版本),不是 "^1.14.0"(允许小版本升级)。
^ 意味着自动升级到最新兼容版本——这次恰恰是这个机制让恶意版本被装上的。恶意版本虽然已经下架,但显式锁定版本是好习惯,建议所有核心依赖都这么做。
这次攻击的真正可怕之处
过去我们聊供应链安全,关注的是:依赖的包有没有漏洞?有没有恶意代码?
这次给所有人提了个醒:你依赖的包本身可能没问题,但包的发布渠道可以被劫持。
源码是干净的,GitHub 是干净的,但你装到电脑里的东西是另一回事。
npm 生态的信任模型建立在我们对维护者的信任上,但维护者的账号安全,从来都不是我们能控制的。
这件事没有银弹。但有几个务实的建议:
1. 生产环境 lockfile 必须提交,CI 用 --frozen-lockfile / --immutable
2. 核心依赖固定版本,不要用 ^ 自动升级
3. 有条件的团队,考虑用 npm audit 或 Snyk 做依赖扫描
4. 关注 npm registry 元数据,安装前扫一眼 npm view axios@1.14.1 的 gitHead 是否和 GitHub tag 对得上
希望你们都没中招。也希望这是最后一次听到这种事。
声明:本文参考了掘金社区作者 左右用AI 的文章「每周1亿次下载的axios被投毒了,但是源码里没有一行恶意代码!」,在原文基础上进行了重新创作与整理。感谢原作者的分享,推荐阅读原文获取更多细节。
夜雨聆风