发生了什么、你是否受影响以及如何防范 —— axios 供应链攻击

MMaximilian Schwarzmüller
Computing/SoftwareBusiness NewsInternet Technology

Transcript

00:00:00这事真的很严重,不是开玩笑,过去的几个小时非常艰难,因为发生了一场
00:00:06针对 Axios 的大规模供应链攻击,没错,就是那个每周有超过 8000 万次
00:00:14下载量的 Axios。
00:00:15现在,首先要做的是。
00:00:18为了让大家检查自己是否受到影响,我附上了一篇文章链接,并且
00:00:23我稍后会分享更多细节,但这一点很重要,为了检查你
00:00:27是否受到了影响,请点击下方的链接并运行你看到的针对
00:00:32你操作系统的命令,Mac OS、Linux、Windows 全都受到了影响。
00:00:37如果你受到影响,你需要运行这些命令。
00:00:40特别是如果这些步骤显示你已经被入侵,你将需要
00:00:49轮换你的密钥,更改密码,将你系统上的凭据、API 密钥,
00:00:55以及系统上的一切内容,都视为已被窃取。
00:01:00将你的密码视为已被窃取,全部更改,禁用 API 密钥,这非常重要。
00:01:07那么,到底发生了什么?
00:01:09Axios 显然是非常流行的 JavaScript 库,一个可用于发送 HTTP 请求的库,
00:01:17例如从 React 应用发送到后端 API。
00:01:22如你所见,它的使用非常广泛,而一些恶意代码被注入到了
00:01:28这个库中。
00:01:29现在,这并不意味着使用该库的网站受到了影响。
00:01:36相反,这意味着你安装该库的系统,你的 MacBook、你的
00:01:41电脑,或者你构建网站的 VPS,这些系统已经被入侵了。
00:01:50如果你在过去的几个小时内运行了 npm install、bun install、npm update、bun update 等命令,
00:01:57那么你很有可能已经受到了影响。
00:02:00再次强调,我分享了你应该运行的检查步骤,以确认你是否受到影响。
00:02:05那么,这一切到底是怎么发生的,什么是供应链攻击?
00:02:10顺便说一下,我还会分享未来如何防御此类攻击。
00:02:15但首先,让我们了解到底发生了什么以及什么是供应链攻击。
00:02:20供应链攻击简单来说就是一种不直接针对你的应用代码的攻击。
00:02:24攻击者并不试图直接渗透你的系统或代码库。
00:02:31相反,他们利用了你的应用代码通常有依赖项,而这些依赖项本身
00:02:37也有依赖项的事实。
00:02:38所以你拥有这条依赖链,而攻击的目标正是这条依赖链。
00:02:45因此,攻击发生在你的代码的上游。
00:02:48由于某种恶意代码被注入其中,这些依赖项之一受到了攻击,
00:02:54这并不是因为维护者想要攻击你。
00:02:58相反,例如在此次案例中,维护者的账户被盗用,
00:03:03攻击者利用该账户向某个库或某个包注入恶意代码,
00:03:10而另一个包可能会使用它,你的代码则可能正在使用那个使用了
00:03:16恶意包的包,或者你的应用代码直接引入了恶意的依赖项。
00:03:23无论哪种方式,你的其中一个依赖项现在突然带有了恶意代码。
00:03:28当你运行 npm install 之类的命令或更新时,
00:03:36那个恶意的、受影响的包就会下载到你的系统上,然后它可以执行
00:03:41你系统上的恶意代码,通常是借助安装后脚本(post install scripts)。
00:03:47所以,如果你不知道的话,npm 有这种脚本机制。
00:03:56我们都在项目中使用它们,例如启动开发服务器、构建项目、
00:04:01运行测试等等。
00:04:04其中特别有安装后脚本,当你构建 React 应用时可能不会用到,
00:04:11但库经常使用,或者说可能会使用,
00:04:17以便在安装库后在你的系统上运行一些代码,通常不是为了
00:04:23做任何恶意或坏事,而是为了编译一些代码,创建一个可能
00:04:31被该库需要的二进制文件,以任何形式准备你的系统,以便它能够真正
00:04:36使用你刚刚下载的库。
00:04:40这就是安装后脚本背后的理念。
00:04:42它允许包定义一些在通过例如 npm install 安装后
00:04:49应该执行的代码,而这正是这些供应链攻击中通常会被利用的地方。
00:04:55攻击者向包中注入恶意代码,其本质上是一个安装后脚本,
00:04:57一旦安装了受感染的包,该脚本就会自动执行。
00:05:10通常这些代码经过混淆,以便不易被读取。
00:05:14它可能是 base64 编码的,这样扫描恶意代码的扫描器可能
00:05:20检测不到它,或者恶意代码可能会被下载。
00:05:24因此,像这次 Axios 攻击的情况,安装后脚本实际上并不直接
00:05:30包含恶意代码。
00:05:32相反,它会联系服务器并从那里下载代码。
00:05:36这就是这里发生的事情。
00:05:37我们有一份关于那次攻击期间具体发生了什么的详细报告。
00:05:41如果你想阅读所有细节,可以在附件中找到,但在报告中我们基本上
00:05:45了解到 Axios 包的两个版本,1.14.1 和 0.30.4 受到了影响,并最终被入侵,
00:05:57这是由攻击者获取了其中一名 Axios 包维护者的账户权限而完成的,
00:06:02他们利用该账户发布了一个新版本的 Axios 包,
00:06:08其中包含一个依赖项,而该依赖项反过来包含了那个安装后脚本。
00:06:14所以,甚至不是 Axios 包本身包含了安装后脚本,
00:06:19而是另一个包,plaincryptojs 包,它是由攻击者创建的,
00:06:25其唯一目的是拥有一个下载并运行恶意代码的安装后脚本。
00:06:32所以 Axios 包是通过将 plaincryptojs 作为依赖项添加到 Axios 中而被入侵的。
00:06:39这是一个恶意包。
00:06:40除了下载恶意代码外,它没有其他用途,而仅仅通过将这个
00:06:46依赖项添加到 Axios,攻击基本上就完成了。
00:06:52这个包没有被导入到 Axios 源代码的任何地方。
00:06:56它只是带有这个安装后脚本,仅此而已。
00:06:59正如提到的,它随后能够从 Windows 和 Linux 下载并运行代码,
00:07:05然后去做什么呢?
00:07:06嗯,偷一大堆东西。
00:07:08所以,如果你的系统受到影响,正如我最初提到的,凭据、API 密钥、加密代币,
00:07:14所有这些有趣的东西都会被下载该安装后脚本的木马收集并外泄。
00:07:22这就是那次攻击的工作原理。
00:07:24过去类似的攻击也是这样运作的。
00:07:29现在有点意思的是,哦,顺便说一下,这次攻击大约从午夜开始,
00:07:36确切地说是今天 UTC 时间午夜之后,就在几小时前。
00:07:40它持续了几个小时,Axios 的 1.14.1 和 0.30.4 两个版本都在
00:07:5040 分钟内,准确地说是 39 分钟内受到了影响。
00:07:53所以这是一次非常有组织、有计划的攻击。
00:07:56显然,这个额外包的创建时间我记得是在攻击开始前的
00:08:0318 个小时。
00:08:04这是非常有组织且经过计划的。
00:08:06现在这里有点奇怪的是,NPM 有一种叫做“可信发布”(trusted publishing)的机制,
00:08:14可以由包维护者使用。
00:08:17这里的想法是将新版本包的发布过程限制在一个清晰
00:08:26定义的流程中,具体来说,你必须通过支持的 CI/CD 提供商之一,
00:08:32配合一定的设置来构建和发布新版本。
00:08:38其理念是,即使你的 NPM 账户凭据被盗,理论上,
00:08:46攻击者也无法从他们的机器发布新版本的包,因为他们
00:08:51必须通过那个流程。
00:08:52现在你可以争辩说,如果维护者的 GitHub 账户被盗,那么也许
00:08:59一个恶意版本可以被推送到 GitHub,触发这里的部署工作流,因此
00:09:06恶意代码通过那个可信发布流程被发布了。
00:09:11但根据这里的安全报告,那并不是这里发生的事情。
00:09:16因为 Axios 团队在 1.x 分支上使用了这个可信发布流程,
00:09:21虽然 0.30 分支没有用,但 1.x 分支用了。
00:09:26但根据这份报告,Axios 的 GitHub 仓库中没有任何提交或攻击迹象。
00:09:33所以并没有向 GitHub 推送那个被入侵的 Axios 版本。
00:09:40因此,可信发布流程本不应该被触发。
00:09:44相反,这份报告指出,攻击者一定获取了一个长期的经典 NPM
00:09:50访问令牌来发布这个恶意或被入侵的 Axios 版本,因为
00:09:56该版本仅存在于 NPM 上,而不在 GitHub 上。
00:10:01也许这是错的。
00:10:02也许攻击是通过 GitHub 进行的。
00:10:05但如果是正确的,我不清楚它是如何运作的,因为理论上,
00:10:11当开启可信发布时,这种发布方式应该是行不通的。
00:10:15不确定这是某种安全漏洞还是 NPM 这边的问题。
00:10:20即即使开启了可信发布,某些现有的长期令牌仍然可以使用。
00:10:27这是我没能弄清楚具体是怎么回事的地方。
00:10:32在 Axios 库的 GitHub Issue 中有一个帖子,记录了这次攻击的
00:10:39报告过程。
00:10:40顺便说一下,更多的此类 Issue 被创建了,但它们被那个被盗账户的
00:10:45维护者删除了。
00:10:48这个帖子存活了下来,攻击最终被阻止了。
00:10:52受影响的维护者重新获得了账户权限。
00:10:56在那个帖子中,维护者发布消息说他们使用了可信
00:11:03发布,目前还不清楚具体是怎么回事。
00:11:07这里分享了一个理论。
00:11:09但我的理解是,这个理论仍然需要将一个新的恶意或被入侵的版本
00:11:16推送到 GitHub,但同样,这都不清楚。
00:11:20清楚的是,被入侵的版本已经被发布并最终出现在 NPM 上,
00:11:25因此可能被下载到系统并窃取在那里的东西。
00:11:29当然,由于每周有超过 8000 万次的下载量,短短几个小时内就会造成巨大的破坏。
00:11:37显然,全天每小时的下载量并不是均匀分布的,但这个数字
00:11:44绝对是巨大的,我们可以假设有成千上万、甚至数万个系统
00:11:51在短短几个小时内受到了影响。
00:11:55当然,这并不是第一次供应链攻击。
00:11:59在过去的几个月里,我们已经看到了多次攻击。
00:12:01去年年底发生了一次大规模攻击,即 shy hulu 攻击,当时有多个包在
00:12:08NPM 上被执行,那次攻击也有类似的模式,恶意代码被注入并在
00:12:16下载了那些受损包的系统上执行,然后凭据等东西被
00:12:21窃取。
00:12:22那是一次重大的攻击。
00:12:25仅仅几天前,Python 生态系统中也发生了类似的事件。
00:12:31所以这并不局限于 JavaScript,lightllm 包也受到了影响。
00:12:37这是一个非常流行的包,它最终使得通过一个方便的接口使用
00:12:43多个 AI 提供商变得更容易,它也遭受了类似的攻击并受到影响。
00:12:49因此,这当然不仅仅发生在 JavaScript。
00:12:52我认为有几个原因导致我们看到更多此类攻击发生。
00:12:57因为理论上,这类攻击在过去可能也发生过,
00:13:03但显然现在变得更加频繁了,我认为这里有几个
00:13:08原因。
00:13:11当然,一个主要原因是,我们正处于一个代码产出比以往任何时候
00:13:17都多、且生成量巨大的时代。
00:13:19你可以看看各种指标。
00:13:22例如,我最近看到一张图表显示,新创建的 GitHub 仓库数量
00:13:27正处于历史最高水平,当然,这是因为 AI。
00:13:31人们在做项目,在生成代码。
00:13:35我们的代码产出量比以往任何时候都大,这当然意味着随着编写的程序
00:13:42和生成的代码越来越多,攻击面也就大得多。目标也更多了。
00:13:48有更多的人在构建或编写代码并安装包。
00:13:52所以它比以往任何时候都更有吸引力。
00:13:54并不是说它过去没有吸引力,但现在有比以往任何时候都多的人
00:13:59可以被攻击。
00:14:00所以这当然是一个重要的原因。
00:14:03发起这些攻击变得更有利可图,但这并不是唯一的原因。
00:14:07我认为另一个原因当然也与 AI 有关,首先,借助 AI 发起像这样
00:14:15的攻击可能变得更容易了,因为恶意代码当然也可以
00:14:21在 AI 的帮助下生成和编写,因此我认为发起这类攻击所需的
00:14:28技术门槛比过去更低,尽管你也可以在
00:14:33暗网买到像这样的脚本或木马,但它对普通人来说可能变得更易获取。
00:14:40AI 不仅仅有让更多人能构建软件、将想法转化为业务等好的一面,
00:14:46它也有坏的一面。
00:14:50多亏了 AI,更多人可以做与代码相关的坏事,所以这是一个原因。
00:14:55你也可以辩称,包维护者、库维护者被
00:15:01Pull Request 淹没了。
00:15:02这是我们目前的另一个大问题,如果你是一个开源维护者,
00:15:07现在的 Pull Request 比以往任何时候都多,所以你可能不会非常仔细地检查
00:15:13你合并的内容。
00:15:14需要明确的是,这并不是这里的问题。
00:15:16在这次 Axios 攻击中,显然是一个账户被盗了,但理论上
00:15:22你可以辩称,维护者有可能将恶意代码或安装恶意依赖项的代码
00:15:29合并到他们的库中,因为他们忽略了它,或者
00:15:34因为他们使用的是未能捕捉到它的全自动代码审查流程。
00:15:38他们只是在依赖 AI。
00:15:40虽然这次不是这种情况,但你可以预见未来这可能会被攻击者利用,
00:15:45他们向代码库注入恶意代码,因为人们根本不去看。
00:15:51此外,当你使用 Cursor、OpenCursor 或任何类似工具在系统上做各类工作时,
00:15:56不仅是帮你开发软件,可能还包括管理你的整个系统,
00:16:01当然,对于某些任务,OpenCursor、Cursor、Codeium 之类的工具可能会决定
00:16:09编写一些脚本并运行一些代码来完成你要求它们做的特定任务,
00:16:15而它们生成的代码可能也依赖于像 Axios 这样的依赖项。
00:16:20所以攻击面再次扩大了,这是我的第一个论点,但
00:16:24已经超出了传统的软件开发范畴,因为所有这些原因以及许多其他原因,
00:16:30这些攻击正变得更有利可图、更容易实施、也更有趣,
00:16:37这就是为什么我确信未来我们会看到更多这类攻击。
00:16:43那么,你能做些什么来防止此类攻击,保护自己呢?
00:16:47一个重大的安全提升步骤是,在你所有的
00:16:55应用开发项目中,当你使用像 pnpm 而不是 npm 来管理
00:17:02依赖项时,你可以在 pnpm-workspace.yaml 文件中添加最小发布时长(minimum release age)设置。
00:17:09Bun 也有类似的功能,如果你使用 Bun 作为包管理器,可以添加一个 bunfig.toml 文件,
00:17:15该文件中也可以添加最小发布时长设置。这有什么作用呢?
00:17:21它只是确保无论以何种方式安装包,它只安装那些
00:17:27至少已经发布了这么久的包或版本。所以如果一个包在
00:17:345 小时前被入侵了,但你有一个规则只安装发布至少
00:17:393 天以上的版本,那你应该是安全的。这就是其核心理念。不幸的是,npm 本身
00:17:46目前还没有这个功能。
00:17:51为了明确这一点,我们讨论的仍然是托管在 npm 上的包。npm 仓库本身没有问题,
00:17:56我这里谈论的是包管理器工具。你当然可以使用 Bun 或 pnpm 从 npm 下载那些包,
00:18:03如果你使用它们而不是只用 npm 命令行工具,那么你就可以利用这类设置,
00:18:08它们能为你提供额外的安全层。因为通常在过去,这些攻击
00:18:14在几个小时内就会被发现。所以如果你有一个比如 3 天的阈值,
00:18:20大多数此类攻击到那时就已经被发现了并且结束了。当然这不是 100%
00:18:25安全的,攻击可能会持续更长时间,但它给了你明显的优势,
00:18:32这绝对是值得去做的事情。现在为了更安全,你可以而且应该考虑使用
00:18:39像 Doppler 这样的解决方案,这不是赞助,这只是一个例子,还有其他替代方案。
00:18:44实际上我自己也构建了一个我自己正在使用的替代方案,这些服务或工具
00:18:49可以管理你的密钥。比如你的 OpenAI API 密钥,你可以把它放在一个 .env
00:18:55文件中,但更好的做法是将其加密存储在像 Doppler 这样的服务上,或者
00:19:02托管在你自己的 VPS 上,然后在需要时将其注入到应用程序的环境变量中,
00:19:08让应用能够感知并使用它。这样,如果你系统上有一个
00:19:13木马程序,它可能会抓取你所有的 .env 文件并从中提取信息,
00:19:20但它在里面找不到任何密钥。这就是其核心思想。将这些密钥
00:19:25存储在加密的其他地方,而不是系统上的文本文件中(.env 文件归根结底只是个文本文件),
00:19:32这绝对也是你应该考虑做的事情。
00:19:36再说一次,这里有不同的解决方案,但这是你应该考虑的。
00:19:40为了更加安全,你当然可以外包你的开发环境,
00:19:45不要把它放在你的 MacBook 或你常用的机器上,而是放在一个 VPS 或一台 Mac Mini 上,
00:19:50通过 SSH 之类的方式连接,或者放在 Docker 容器里,这样
00:19:56如果那里执行了某些恶意代码,它只会影响那个 Docker 容器或
00:20:02那个 VPS,而不会波及你的整个系统。所以它无法收集你所有的系统密码
00:20:07之类的东西。相反,它是隔离的,爆炸半径更小。因为这些攻击
00:20:13显然会继续发生。我很确定我们将会有越来越好的机制
00:20:21来保障包的发布安全等,但永远无法 100% 保证
00:20:27此类攻击不会发生。因此,作为此类包的使用者,你必须保护
00:20:33你的系统,并建立多层防御,从而降低你下载到
00:20:39被入侵包版本的概率,即使下载了,也能让爆炸半径更小。
00:20:45我会在未来的视频中分享更多相关内容,也会在我的另一个频道 Academy 频道分享。
00:20:50总之,请保持警惕,检查你是否受到了这次攻击的影响,
00:20:55正如我所说,过去的几个小时真的很艰难。

Key Takeaway

Axios 供应链攻击利用受损维护者账户注入带恶意 postinstall 脚本的依赖包,开发者需通过设置包管理器最小发布时长限制和加密密钥管理来防御此类日益频繁的自动化攻击。

Highlights

Axios 的 1.14.1 和 0.30.4 版本在 2026 年 3 月 31 日 UTC 时间午夜后的 39 分钟内遭到恶意代码注入。

攻击者通过盗用维护者账户,将名为 plaincryptojs 的恶意包作为依赖项引入 Axios,利用其 postinstall 脚本在受害者系统执行代码。

每周下载量超过 8000 万次的 Axios 遭到攻击,意味着数以万计的 macOS、Linux 和 Windows 开发环境可能泄露了凭据和 API 密钥。

通过在 pnpm-workspace.yaml 或 bunfig.toml 中设置最小发布时长(minimum release age)可以过滤掉发布不足 3 天的新包以规避此类风险。

将 .env 文件中的明文密钥迁移到 Doppler 等加密管理服务,可防止本地运行的木马程序直接抓取敏感环境变量。

使用 Docker 容器或远程 VPS 隔离开发环境,能将供应链攻击的“爆炸半径”限制在虚拟机内,保护宿主机系统的密码和数据。

Timeline

Axios 供应链攻击的现状与紧急应对

  • Axios 1.14.1 和 0.30.4 版本已被确认包含恶意注入代码。
  • 在过去几小时内运行过 npm install 或 update 的系统均面临凭据窃取风险。
  • 受影响的用户必须立即轮换所有 API 密钥、更改系统密码并禁用现有凭据。

这场针对每周 8000 万次下载量库的大规模攻击影响了所有主流操作系统。攻击的目标并非最终网站的访问者,而是运行安装命令的开发者机器或构建服务器。受害者需要假设系统上的所有敏感信息已被外泄,并执行彻底的安全清理。

供应链攻击的运作机制与技术细节

  • 攻击者利用依赖链的上游环节,通过 postinstall 脚本在包安装后自动执行恶意指令。
  • 恶意包 plaincryptojs 伪装成依赖项被引入 Axios,其唯一功能是联系服务器并下载执行木马程序。
  • 攻击代码通常使用 base64 编码或动态下载方式来绕过静态代码扫描器的检测。

供应链攻击通过操纵应用所依赖的第三方库来实现渗透。即使 Axios 本身没有恶意逻辑,只要其依赖项中包含恶意脚本,开发者在安装时就会触发攻击。在这种案例中,postinstall 脚本被滥用,从远程服务器获取专门用于收集 Windows 和 Linux 系统凭据的木马。

NPM 可信发布机制失效之谜

  • 虽然 Axios 在 1.x 分支启用了可信发布(Trusted Publishing)流程,但恶意版本依然出现在 NPM 镜像中。
  • GitHub 仓库中未发现任何恶意提交记录,表明攻击者可能绕过了 CI/CD 流程直接发布。
  • 攻击者利用获取到的长期经典 NPM 访问令牌发布了被篡改的包版本。

可信发布旨在将发布权限限制在特定的 CI/CD 流程中,防止账户被盗导致的非法发布。然而,此次攻击中 GitHub 记录保持干净,意味着攻击者可能利用了 NPM 系统的某种安全漏洞或残留的长期令牌。这种有计划的行动在 plaincryptojs 包创建 18 小时后便精准发动。

攻击频率上升的原因与 AI 的影响

  • AI 生成代码的普及导致 GitHub 仓库数量激增,显著扩大了潜在的攻击面。
  • 利用 AI 生成恶意脚本降低了发起复杂供应链攻击的技术门槛。
  • 开源维护者面临海量 PR 压力,可能导致对恶意依赖项或代码注入的审查疏漏。

随着代码产出量达到历史最高水平,黑客拥有了更多的攻击目标。AI 不仅帮助开发者提高效率,也让攻击者能更轻易地编写混淆代码。此外,过度依赖 AI 进行自动化审计而缺乏人工检查,为恶意代码混入主流库提供了可乘之机。

多层防御体系与安全实践建议

  • 使用 pnpm 或 Bun 代替原生 npm,并配置最小发布时长规则以拦截刚发布的新版本。
  • 采用 Doppler 等服务管理加密密钥,避免在 .env 文本文件中明文存储敏感信息。
  • 通过 Docker 容器或远程开发环境(如 Mac Mini/VPS)实现开发环境的物理隔离。

由于供应链攻击通常在发布后数小时内被发现,设置 3 天左右的下载阈值可以过滤掉绝大多数受损包。加密存储密钥能确保即使系统被入侵,攻击者也无法直接读取环境变量。将开发活动限制在隔离的容器内,可以有效控制恶意脚本的执行范围,保护宿主机核心数据的安全。

Community Posts

View all posts