axios 被投毒了!每周一亿次下载的 npm 巨包沦陷,安装即植入「远控木马」,全球开发者紧急停工排查
【导读】npm 生态核弹级事件:axios 维护者账号被劫持,恶意版本 1.14.1 和 0.30.4 被直接推送到 npm 仓库。攻击者没改一行 axios 代码——只悄悄塞进一个「幽灵依赖」,安装瞬间自动下载跨平台远控木马(RAT),执行完还会自毁灭迹。每周超过 1 亿次下载,窗口期虽然只有约 3 小时,但足以让无数 CI/CD 流水线和开发机中招。
凌晨突袭:一个从未存在过的依赖,悄悄出现在 axios 的 package.json 里
北京时间 3 月 31 日清晨,全球 JavaScript 开发者的噩梦开始了。
安全公司 Socket 的创始人 Feross 在推特上紧急发帖,六个字母全部大写:CRITICAL。
"CRITICAL: Active supply chain attack on axios -- one of npm's most depended-on packages. The latest axios@1.14.1 now pulls in plain-crypto-js@4.2.1, a package that did not exist before today. This is a live compromise."
「高危:axios 正在遭受供应链攻击——这是 npm 上被依赖最多的包之一。最新的 axios@1.14.1 引入了 plain-crypto-js@4.2.1,这个包今天之前根本不存在。这是一次正在发生的入侵。」

▲ Socket 创始人 Feross 发出高危警报,超过 200 万人看到这条推文,6000+ 点赞
这条推文像一颗信号弹,瞬间引爆了整个开发者社区。
知名 JavaScript 教育者 Wes Bos 紧接着发出了更直白的警告:
"Do not npm install or deploy anything right now. Supply chain attack on axios 1.14.1 - even if you don't use axios it may be a nested dep."
「现在不要运行 npm install,不要部署任何东西。即使你没直接用 axios,它也可能是你某个依赖的依赖。」

▲ Wes Bos 呼吁全球开发者立即停止安装和部署,84 万次浏览,6200+ 点赞
你没看错——一个 HTTP 请求库,让全球开发者被要求「停止一切操作」。
教科书级的攻击链:不改一行代码,安装即沦陷
到底发生了什么?
据安全公司 StepSecurity 的完整技术分析,这次攻击的精密程度令人脊背发凉。
攻击者根本没有修改 axios 的源代码。他们做的事情简单到可怕:在 package.json 里加了一行依赖——`"plain-crypto-js": "^4.2.1"`。
这个包从来没有在 axios 的任何一行代码里被 import 或 require 过。它唯一的使命就是:在你运行 `npm install` 的那一刻,通过 postinstall 脚本自动执行恶意代码。
整条攻击链如下:
1. `npm install axios@1.14.1` 2. npm 自动安装依赖 `plain-crypto-js@4.2.1` 3. 触发 postinstall → 执行混淆过的 `setup.js` 4. 检测操作系统(macOS / Windows / Linux) 5. 从 C2 服务器下载对应平台的二阶段木马 6.执行完毕后自毁——删除 setup.js,用干净文件覆盖 package.json
最后一步才是最阴险的。执行完就擦干净所有痕迹,你事后去翻 `node_modules`,什么异常都看不到。
StepSecurity 在报告中写道:
"If you have installed axios@1.14.1 or axios@0.30.4, assume your system is compromised."
「如果你安装过 axios@1.14.1 或 0.30.4,请直接假设你的系统已经被攻陷。」
精心策划的 18 小时:攻击者甚至提前「养号」
这次攻击并非仓促之举。
根据 StepSecurity 与 npm Registry 的时间戳记录,攻击者至少提前18 小时进行了布局:
- 3 月 30 日 05:57 UTC
:发布 `plain-crypto-js@4.2.0`——一个完全干净的版本,里面是正常的 crypto-js 源码。目的?建立发布历史,骗过安全扫描器的「全新包」检测规则。 - 3 月 30 日 23:59 UTC
:发布 `plain-crypto-js@4.2.1`——真正的恶意版本,加入了 postinstall 和混淆 dropper。 - 3 月 31 日 00:21 UTC
:发布 `axios@1.14.1`——注入幽灵依赖。 - 3 月 31 日 01:00 UTC
:发布 `axios@0.30.4`——对旧版本线也下了毒。 - 约 3 月 31 日 03:15 UTC
:npm 团队介入,下架恶意版本。
从投毒到处置,窗口期大约3 小时。
三个小时够干什么?够让全球无数条 CI/CD 流水线执行一次 `npm install`。够让无数开发者的笔记本在后台静默安装一个远控木马。
维护者账号被劫持:绕过了所有正规发布流程
一个关键问题:攻击者是怎么把恶意版本推上 npm 的?
答案是:劫持了 axios 核心维护者 jasonsaayman 的 npm 账号。
Socket 和 StepSecurity 的分析都指出了决定性证据——
正常的 axios 1.x 发布走的是GitHub Actions + OIDC Trusted Publisher流程,发布记录里会有 `trustedPublisher`、`gitHead` 等元数据。而 1.14.1 的发布元数据显示:手动通过 npm CLI 发布,没有对应的 GitHub commit、tag 或 release。
"The affected Axios version does not appear in the project's official GitHub tags."
「受影响的 axios 版本并未出现在项目的官方 GitHub tag 中。」
攻击者还把注册邮箱改成了匿名的 ProtonMail 地址(`ifstap@proton.me`)。这意味着即便其他维护者发现异常,也很难通过常规渠道夺回账号控制权。

▲ Socket 官方确认:AI 分析将其标记为恶意混淆投放器,正在持续调查中
事实上,在 GitHub issue #10604 的讨论中,axios 的另一位协作者 DigitalBrainJS 就提到了这个困境:他们无法自行撤销更高权限账号的访问令牌,必须等 npm 管理员介入。
开源世界的残酷现实:发现快,但修复的权限链条很长。
跨平台远控木马:macOS、Windows、Linux 一个不放过
这个恶意依赖到底会做什么?
Socket 的技术分析揭示了完整的执行链路——`setup.js` 经过两层反混淆(字符串反转 + Base64 + 自定义 XOR),检测当前操作系统后,向 C2 服务器 `sfrclak[.]com:8000` 发送请求,并用伪装成 npm 域名的字符串来区分平台:
macOS → POST body 包含 `packages.npm.org/product0` Windows → `packages.npm.org/product1` Linux → `packages.npm.org/product2`
Socket 特别解释了一个"容易踩坑的点":`npm.org`并不是真正的 npm registry(真正的是 `registry.npmjs.org`),攻击者把 POST body 伪装成类似 npm 的字符串,可能是为了在网络日志和告警系统里"看起来像正常的 npm 流量"。
macOS 上,木马会通过 AppleScript 下载 C++ 编写的 Mach-O 二进制文件,伪装成 Apple 系统守护进程,每 60 秒向 C2 回传一次系统指纹(主机名、用户名、运行进程等)。
Windows 上,木马把 PowerShell 复制到 `%PROGRAMDATA%\wt.exe`(伪装成 Windows Terminal),通过隐藏的 VBScript 以 `-WindowStyle Hidden -ExecutionPolicy Bypass` 执行下载的 payload。
Linux 上,用 `curl` 下载 Python 脚本,`nohup` 后台执行,脱离终端也不会中断。
这些木马支持的指令包括:代码注入(peinject)、远程脚本执行(runscript)、目录遍历、自杀删除——一个标准的远程访问木马(RAT)工具集。
全球开发者社区的「地震级」反应
消息传开后,推特上掀起了一场罕见的全球性开发者紧急动员。
安全专家 Matt Johansen 的反应很能代表当时的气氛:
"Massive. Like stop what you're doing and go check if you're impacted moment. Axios package hacked and is pushing malware."
「影响巨大。就是那种需要你立刻停下手头所有事情、去检查自己是否受影响的时刻。Axios 被黑了,正在推送恶意软件。」

▲ 安全专家 Matt Johansen:这是一个「放下一切去排查」的时刻
日本安全研究者 YONEUCHI Takashi 在社区同步发出了日文告警,说明这个事件的冲击波已经跨越了语言和时区:

▲ 日本安全研究者发布详细时间线,Takumi Guard 在事发 2 小时内就开始拦截
开发者 Aiden Bai 的一声惊呼代表了千千万万人的第一反应:
"holy shit axios is compromised right now"
「我的天,axios 现在被入侵了」

▲ 开发者 Aiden Bai 附带 npm 页面和 GitHub issue 截图,近 20 万人围观
受影响的项目方也在第一时间做出响应。ByteRover CLI 的开发者 andy nguyen 发布了详细的安全公告,将 axios 锁定到安全版本 1.14.0:

▲ 下游项目紧急发布安全公告:假设受影响的机器已被攻陷,轮换所有凭据和密钥
你现在该怎么办?一份紧急排查清单
如果你的项目用了 axios,现在就做以下检查:
第一步:确认是否中招``` npm ls axios npm ls plain-crypto-js ``` 如果看到 `1.14.1`、`0.30.4` 或 `plain-crypto-js`,立即进入应急响应模式。
第二步:锁定安全版本把 package.json 里的 axios 改为精确版本:`"axios": "1.14.0"`(注意:去掉 `^` 和 `~`)。
第三步:清理并重新安装删除 `node_modules` 和 lockfile,重新 `npm install`。
第四步:如果确认中招
- 假设机器已被攻陷
轮换该机器上所有可访问的凭据、API 密钥 审计正在运行的进程,终止可疑项 检查系统临时目录和 ProgramData 目录
有推特用户分享了一个实用的防御配置:
"npm config set min-release-age 3. Do it now."
「设置 npm 最小发布年龄为 3 天。现在就做。」

▲ 社区分享的缓解措施:设置 min-release-age 让新版本有冷却期,避免「零日投毒」
这个配置会让 npm 在安装时自动跳过发布时间不足 3 天的版本——虽然会牺牲一点"尝鲜"的便利,但能有效防止这类闪电式投毒。
一亿次下载背后的脆弱:开源供应链的系统性危机
axios,一个被几乎所有 JavaScript 项目直接或间接依赖的 HTTP 客户端库——每周超过 1 亿次下载——它的安全竟然取决于一个维护者的 npm 令牌有没有泄漏。
这才是这次事件最令人后怕的地方。
攻击者不需要找到 axios 代码里的漏洞,不需要绕过任何代码审查,甚至不需要往源码里塞一行可疑代码。他们只需要拿到一个账号的访问令牌,就能在全球 CI/CD 流水线里静默植入木马。
更可怕的是,大量项目的 package.json 里写的是 `"axios": "^1.14.0"`——这个caret 范围符号(^)意味着 npm 会自动安装满足语义化版本的最新版本。当 1.14.1 被恶意发布时,任何执行 `npm install` 的环境都可能自动拉取到毒版本,而开发者完全不知情。
在 AI Agent 和自动化编程工具越来越流行的今天,大量代码生成和依赖安装发生在无人值守的流水线中。一次 3 小时的投毒窗口,已经足以造成难以估量的连锁反应。
值得庆幸的是,Socket 的自动化恶意软件扫描在 plain-crypto-js@4.2.1 发布后6 分钟内就将其标记为恶意软件。社区的响应速度同样惊人——从 Feross 发出第一条警报,到 npm 团队下架恶意版本,全程不到 3 小时。
但这也提出了一个无法回避的问题:如果下一次攻击者更耐心一点,如果被投毒的包不是 axios 这样的明星项目,如果安全扫描器没有在 6 分钟内捕获异常——会发生什么?
开源生态养活了整个互联网,但守护它的人,往往只是几个手握长期令牌的志愿者。
这个问题,远比一次 axios 投毒事件严重得多。
— END —
夜雨聆风