每周1亿次下载的axios被投毒了,但是源码里没有一行恶意代码!

今天上午,有个哥们在群里发了一句话:

"axios 被投毒了。"

我第一反应是不可能。axios 每周 1 亿次下载,npm 上 Top 10 的包,谁敢动它?

然后我去翻了 GitHub issue,翻了安全公司的分析报告。越看越不对劲。

axios 的 GitHub 仓库里,一行恶意代码都没有。你盯着源码看一万遍,什么都发现不了。

问题根本不在源码里。


到底发生了什么

有人偷了 axios 维护者的 npm 账号,绕过 GitHub,直接往 npm registry 发了两个"官方版本"。

axios 代码本身没改。只是在 package.json 的依赖里加了一个你从没见过的包:plain-crypto-js

npm install 的瞬间,这个包的 postinstall 脚本自动跑起来:检测操作系统,下载远控木马,连上攻击者服务器。然后自我删除,把 package.json 替换成干净版本。

你事后翻 node_modules,什么痕迹都没有。

就好像你去五金店买了一把锁,品牌对、包装对、外观对,但里面被人换成了带后门的。你装上了,用着正常,别人随时能开你家门。普通漏洞是锁有缺陷,换一把就行。这次是锁在到你手里之前就被掉包了。


攻击时间线

我把时间线拉出来:

T-18小时 :攻击者用一次性账号发布了 plain-crypto-js@4.2.0

注意,这个版本是干净的。内容就是合法 crypto-js 的复制品,零恶意代码。

为什么要发一个干净版本?在 npm 上建立发布历史。一个零历史的新包突然被大包依赖,会触发安全警报。先"养号",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.jsonpnpm-lock.yamlyarn.lock,搜这三个关键词:

  • axios@1.14.1
  • axios@0.30.4
  • plain-crypto-js

三个都没有?大概率安全。后面几步也值得做。

第二步:清缓存

bash 复制代码
npm cache clean --force

踩坑预警:CI 环境也要清。 GitHub Actions、GitLab CI 的 node_modules 缓存和 npm 缓存里如果残留了恶意 tarball,下次构建还会命中。别只清本地。

第三步:锁死版本

json 复制代码
"axios": "1.14.0"

注意是 "1.14.0",不是 "^1.14.0"^ 意味着自动升级到最新兼容版本,这次恰恰是这个机制让恶意版本被装上的。恶意版本虽然已经下架,但显式锁定是个好习惯。

第四步:审计 install 脚本

bash 复制代码
grep -r '"postinstall"' node_modules/*/package.json

这次的载体就是 postinstall。顺手看看你其他依赖有没有可疑的 install 脚本。

激进做法:.npmrc 里加 ignore-scripts=true,全局禁止。但 esbuild、sharp 这些包也靠 postinstall 下载二进制,全禁可能影响构建,自己权衡。

第五步:确认中招了?当作机器已经失控处理

不是"可能要换密码"。是现在就轮换所有凭证:

  • npm token
  • GitHub token
  • SSH key
  • 数据库密码
  • 云服务 AK/SK

CI 机器中招的话,检查 CI secrets 是否泄露。

查异常进程和网络连接,关注 sfrclak.com:8000 这个地址。

RAT 跑起来之后,你机器上的一切对攻击者都是透明的。别侥幸。


大包不等于安全

很多开发者的直觉是:axios 每周 1 亿下载,总不会出事吧。反过来想,越热门的包,攻击者的投入产出比越高。投毒一个每周 100 下载的包没人在乎,投毒一个每周 1 亿下载的包,3 小时窗口就够覆盖成千上万个项目。

这次 axios 的源码没有任何问题。

问题出在发布链上。你默认信任的那条从代码到 registry 的链路,才是该被审计的东西。lockfile 锁版本,审计 install 脚本,监控依赖变更,关注 registry 元数据的发布者签名。不是有空再搞的事。


你的项目查了吗?评论区报个平安。身边有用 axios 的朋友还不知道这事的,转给他看一眼。

相关推荐
还有你Y1 天前
Shell 脚本语法
前端·语法·sh
踩着两条虫1 天前
如何评价VTJ.PRO?
前端·架构·ai编程
GetcharZp1 天前
告别 jq 噩梦!这款 JSON 神器 fx 让你在终端体验“丝滑”的数据操作
后端
Mh1 天前
鼠标跟随倾斜动效
前端·css·vue.js
小码哥_常1 天前
告别臃肿!Elasticsearch平替Manticore登场
后端
小码哥_常1 天前
Kotlin类型魔法:Any、Unit、Nothing 深度探秘
前端
苍何1 天前
万字保姆级教程:Hermes+Kimi K2.6 打造7x24h Agent军团
后端
我叫黑大帅1 天前
为什么map查找时间复杂度是O(1)?
后端·算法·面试
Web极客码1 天前
深入了解WordPress网站访客意图
服务器·前端·wordpress
幺风1 天前
Claude Code 源码分析 — Tool/MCP/Skill 可扩展工具系统
前端·javascript·ai编程