axios 供应链攻击:维护者账号遭劫持,恶意版本植入远程控制木马

攻击概述

2026 年 3 月 31 日,安全机构 StepSecurity 发现 JavaScript 生态中下载量最大的 HTTP 客户端库 axios 遭遇供应链攻击。攻击者劫持了 axios 首席维护者的 npm 账号(jasonsaayman),手动发布了两个恶意版本——[email protected][email protected]——分别投放到 1.x 和 0.x 两条 release 分支。

这两个版本绕过了项目正常使用的 GitHub Actions CI/CD 流程,也未绑定 npm 的 OIDC Trusted Publisher 机制。npm registry 上的发布记录显示,发布者邮箱被改为一个 ProtonMail 地址([email protected]),且没有对应的 git commit 或 tag。合法的 axios 发布始终通过 GitHub Actions + OIDC 完成发布签名绑定,这次恶意发布打破了所有已知的发布流程指纹。

cover

攻击手法

恶意版本本身没有在 axios 源码中注入任何恶意代码。攻击者采用了更隐蔽的方式:在 axios 的依赖中添加了一个此前从未出现过的虚假依赖 [email protected]

这个包伪装成 crypto-js 的变体,使用了相同的描述、作者署名和仓库地址,但其唯一目的是执行 postinstall 脚本——在 npm install 时自动运行一个跨平台的远程控制木马(RAT)投放器。木马针对 Windows、macOS 和 Linux 分别预编译了三个独立载荷,连接到一个活跃的 C2 服务器接收指令。

更值得关注的是恶意软件的自毁机制:木马执行完成后会自动删除所有恶意脚本文件,并将自身的 package.json 替换为一个干净的版本(plain-crypto-js 4.2.0 的 manifest),确保开发者在事后检查 node_modules 目录时看不到任何异常痕迹。

攻击时间线

整个攻击经过精心策划,分为多个阶段:

  • 3 月 30 日 05:57 UTC — 攻击者使用一次性账号([email protected])发布 [email protected],这是一个干净的诱饵包,包含完整合法的 crypto-js 源码,没有 postinstall 钩子。其目的是为后续的恶意版本建立 npm 发布历史,避免被安全扫描标记为"零历史新包"。

  • 3 月 30 日 23:59 UTC — 同一账号发布 [email protected],加入 postinstall 钩子和混淆的投放器代码。

  • 3 月 31 日 00:21 UTC[email protected] 通过被劫持的 jasonsaayman 账号发布,注入 [email protected] 作为运行时依赖,针对 1.x 用户群。

  • 3 月 31 日 01:00 UTC[email protected] 通过同一账号发布,对 0.x 分支实施相同注入。两条分支在 39 分钟内先后被投毒。

从恶意依赖预置到最终两个 axios 版本发布,整个链条跨越约 18 小时,三个平台载荷预先构建完成。

影响范围

axios 是 JavaScript 生态中使用最广泛的 HTTP 客户端库,周下载量超过 3 亿次。几乎所有使用 Node.js 或浏览器发起 HTTP 请求的应用都可能依赖 axios——从 React 前端到 CI/CD 工具链,再到服务端 API。

任何在 3 月 31 日 UTC 00:21 至漏洞被发现期间运行过 npm installnpm update 并安装了受影响版本的开发环境,都应当被视为已 compromised。恶意软件具备完整的远程控制能力,攻击者可以在受感染机器上执行任意操作。

应对建议

  1. 立即排查依赖版本:检查项目中 axios 版本是否为 1.14.1 或 0.30.4。
  2. 降级到安全版本:将 axios 降级到 1.14.0(1.x 分支)或 0.30.3(0.x 分支)。
  3. 更换所有凭据:如果已安装受影响版本,默认系统已被攻破,应立即更换该机器上的所有 SSH 密钥、API token、数据库密码和其他敏感凭据。
  4. 隔离受影响环境:将可能受感染的机器从网络中隔离,进行全面的恶意软件扫描。

这次攻击的精密程度在 npm 供应链攻击记录中相当罕见。恶意依赖的提前预置、多平台载荷的预先构建、自毁机制的设计,都表明这不是一次 opportunistic 攻击,而是经过长期策划的行动。