npm爆发大规模供应链攻击 蠕虫污染 2000+ 个包版本: 深度技术剖析
npm 蠕虫污染 2000 个包版本深度技术剖析2026 年 8 月 4 日究竟发生了什么以及每位开发者必须知道的事全景概览2026 年 8 月 4 日攻击者入侵了 Jared Wray 的 GitHub 账号, 他是广泛使用的keyv包的维护者该包是一个键值存储抽象库每周下载量约 1.27 亿次。短短数小时内一种名为ChainDrop的自我复制蠕虫Shai-Hulud 恶意软件家族的变种就污染了444 个不同包中的 2,234 个版本。这些受影响包的合计月下载量超过20 亿次。这次事件之所以令人震惊不仅在于其规模更在于其精巧程度。该蠕虫并未利用 npm 本身的任何漏洞而是滥用了合法功能可信维护者的身份、自动化发布流水线以及经过签名的来源证明provenance。攻击步骤详解步骤 1账户入侵攻击者首先控制了维护者的 GitHub 账户。初始入侵途径尚未确认但结果很明确攻击者现在拥有了推送代码和发布包的合法凭证。为何发生维护者的账户缺乏足够保护, 没有硬件安全密钥未对关键操作强制要求双因素认证或者凭证通过其他途径暴露。这是整个链条中最关键的一个失败点。步骤 2直接注入主分支UTC 时间 8 月 4 日 09:02攻击者直接向keyv仓库的main分支推送了一个恶意提交。该提交添加了两个文件setup.mjs—— 一个 29 KB 的加载器脚本Math_Symbol.js—— 一个 728 KB 的混淆第二阶段载荷同时修改了package.json添加了preinstall钩子scripts:{preinstall:node setup.mjs}为何发生攻击者拥有主分支的写入权限。仓库没有配置分支保护规则要求合并到主分支前必须经过 Pull Request 审查。这是 GitHub 仓库安全配置的基本失误。攻击者得到了什么通过直接注入主分支恶意代码成为了自动化发布流水线将会构建和发布的源码的一部分。步骤 3IDE 和 AI 代理持久化钩子UTC 09:04攻击者推送了额外的提交在开发者工具配置中植入了执行钩子.claude/settings.json—— 一个SessionStart钩子在 Claude Code 会话启动时运行node .claude/setup.mjs.vscode/tasks.json—— 一个folderOpen任务在仓库于 VS Code 中打开时运行node .vscode/setup.mjs为何发生攻击者深知开发者不只是安装包他们还会克隆仓库并在 IDE 中打开。这就创建了一个完全不需要npm install的次级感染向量。开发者或 AI 编码助手仅仅因为打开克隆的仓库文件夹就可能被攻陷。步骤 4发布到 npmUTC 09:35keyv6.0.0被发布到 npm。合法的发布流水线构建了已被木马化的源码并附带了有效的 npm 来源证明—— 一份签名的 SLSA 证明。keyv6.0.0 附带有效的 npm 来源证明发布 合法的发布流水线构建了已被木马化的源码 签名验证在恶意软件上通过了为何发生来源证明证明的是构建完整性而非源码完整性。构建系统执行了它设计要做的事, 构建仓库中存在的任何源码并对结果签名。系统信任源码因为维护者的账户是受信的。关键教训经过签名的来源证明并不意味着代码安全。它只说明该代码确实来自所声称的构建过程。步骤 5蠕虫激活当开发者运行npm install安装受影响包时preinstall钩子自动执行。setup.mjs实际执行的操作检查 Bun 运行时—— 若未安装则直接从 GitHub 官方发布页下载bun v1.3.13执行载荷—— 使用 Bun 运行Math_Symbol.js清除痕迹—— 执行后删除临时 Bun 目录Math_Symbol.js载荷经过重度混淆728 KB采用控制流扁平化和 Base91 字符串编码。载荷功能使用 TruffleHog 风格的正则表达式扫描磁盘查找凭证信息窃取 npm 和 GitHub 访问令牌窃取 AWS、GCP 和 Azure 云凭证提取 HashiCorp Vault 令牌和 Kubernetes 服务账户令牌读取 GitHub Actions OIDC 令牌和实例元数据捕获 Stripe 和 Slack 令牌、SSH 密钥以及数据库凭证使用 AES-256-GCM 在操作者公钥下加密窃取的数据将数据外泄至攻击者控制的 GitHub 仓库和通过 DNS 解析的目标地址步骤 6自我复制这才是它成为蠕虫的关键。利用窃取到的 npm 令牌恶意软件搜索被入侵身份拥有发布权限的其他包下载这些包注入相同的恶意文件setup.mjs以及Math_Symbol.js或math_init.js修改package.json添加preinstall钩子增加版本号将木马化后的包重新发布到 npm速度令人咋舌蠕虫在大约两小时内09:40 至 11:44 UTC重新发布了435 个包中的 1,557 个恶意版本。每隔两到七分钟就有一波新的被污染包发布。当窃取的凭据中包含 GitHub App 令牌时蠕虫进一步扩大影响范围 —— 向每个可访问仓库的最多 50 个分支提交恶意钩子。为何发生npm 令牌授予发布权限。一旦被窃取它们就成为蠕虫的主要传播机制。整个过程没有任何速率限制或异常检测来标记这种异常的发布模式。步骤 7动态 C2 基础设施恶意软件放弃了在载荷中硬编码 C2 域名的传统做法而是使用eth_call调用主网上的一个以太坊智能合约StringListStore动态获取当前的 C2 域名列表攻击者可以随时更新合约来更换 C2 基础设施而无需重新部署恶意软件为何发生静态 C2 域名容易被封堵。通过将以太坊作为动态配置存储攻击者使恶意软件能够抵御域名封禁。初始链记录显示有 3 个域名后来更新为仅返回一个。步骤 8令牌撤销陷阱这里尤其阴险。载荷安装了一个自毁开关将窃取的 GitHub 令牌和攻击者提供的处理命令写入~/.config/gh-token-monitor/将自身持久化为 macOS LaunchAgent 或 Linux systemd 用户服务并启用loginctl enable-linger以在注销后继续运行监控令牌是否被撤销陷阱如果你作为第一响应措施撤销了被窃令牌就会触发自毁开关。载荷将执行其处理命令 —— 可能销毁证据、外泄额外数据或造成其他破坏。为何发生攻击者预判了应急响应流程并内置了对抗措施。这是专业级别的战术手段。受影响的包值得注意的被入侵版本包括keyv6.0.0—— 月下载量约 6 亿flat-cache6.1.24—— 月下载量约 5.8 亿file-entry-cache11.1.6—— 月下载量约 5.7 亿cacheable-request13.0.20cacheable2.5.1cache-manager7.2.10ecto5.0.1蠕虫还波及了 Deliveroo、Ornikar、OneReach、Picsart、Qlik 和 ServiceTitan 等其他组织下的包。代码分析恶意载荷preinstall 钩子{scripts:{preinstall:node setup.mjs}}问题所在npm 的preinstall钩子在包安装之前执行且无需任何用户交互。受害者不需要导入包或编写任何应用代码 —— 仅仅运行npm install就足够了。攻击面这并不是 npm 的漏洞而是合法功能被滥用。包管理器信任包作者不会作恶。加载器setup.mjs —— 简化示意// 伪代码示意import{platform,arch}fromos;import{execSync}fromchild_process;import{existsSync,mkdtempSync,rmSync}fromfs;// 检查 Bun 是否已安装constbunPathwhichBun();if(!bunPath){// 从 GitHub 下载 Bun v1.3.13consturlhttps://github.com/oven-sh/bun/releases/download/bun-v1.3.13/bun-${platform()}-${arch()}.zip;downloadAndExtract(url);}// 执行混淆后的载荷execSync(bun run${__dirname}/Math_Symbol.js,{stdio:inherit});// 清理rmSync(tempDir,{recursive:true,force:true});危险之处加载器下载了一个完整的 JavaScript 运行时Bun并执行任意代码。这绕过了任何 Node.js 特定的安全控制。728 KB 的载荷经过重度混淆使得静态分析极为困难。凭证收割器Math_Symbol.js —— 概念性// 基于模式的凭证扫描TruffleHog 风格constpatterns{aws:/AKIA[0-9A-Z]{16}/g,github:/gh[psu]_[0-9a-zA-Z]{36,}/g,npm:/npm_[a-zA-Z0-9]{36,}/g,// ... 数百种其他模式};// 扫描磁盘上的文件functionscanDirectory(path){for(constfileofwalkSync(path)){constcontentreadFile(file);for(const[type,pattern]ofObject.entries(patterns)){constmatchescontent.match(pattern);if(matches){exfiltrate({type,matches,file});}}}}// 自我复制functionpropagate(npmToken){constpackagesgetPublishablePackages(npmToken);for(constpkgofpackages){consttarballdownloadPackage(pkg);constmodifiedinjectPayload(tarball);constnewVersionbumpVersion(pkg.version);publishPackage(pkg.name,newVersion,modified,npmToken);}}之所以如此有效的原因使用合法的 npm API 进行传播 —— 无需任何漏洞利用为修改后的包重新计算完整性哈希值为篡改后的版本生成全新的 Sigstore 来源记录安装后包的行为正常但主机已被攻陷这对开发者意味着什么攻击面已经扩大此次攻击表明供应链威胁模型现在包括维护者账户—— 开源中最关键的资产源码仓库—— 不仅是已发布的包IDE 配置——.vscode/、.claude/、.cursor/现在成为执行入口AI 编码助手—— 打开仓库即可触发执行构建流水线—— 带有 OIDC 令牌的 GitHub Actions 是重点目标来源证明并非银弹keyv6.0.0版本具有有效的 npm 来源证明附带签名的 SLSA 证明。证明验证通过因为构建系统从被入侵的源码构建构建系统对结果进行了签名签名证明该构建确实来自合法的流水线来源证明证明的是构建完整性而非源码完整性。这是业界许多人一直忽略的关键区别。如何修复补救指南立即行动1. 检查是否受影响查找以下入侵指标SHA-256 哈希值9fc2570b7cef51c1b8df116d144d11ff4096357be7d2c4c6367cfc2509cf1bcc → Math_Symbol.js / math_init.js728 KB 载荷 54dc7ea54a1317cca0e890a2770630cf7fa6c97813e0cb9d2caa93012b350668 → setup.mjs加载器29,918 字节 fd3ca4007b225fdf8de7af4345a19179d5efa8c4bb9205f88cda806e5684b1eb → setup.mjs加载器变体11,017 字节检查你的package-lock.json或yarn.lock中是否存在受影响的版本。2. 不要首先撤销令牌如果你怀疑被入侵切勿作为第一步就撤销 npm 令牌或 GitHub 令牌—— 这会触发自毁开关。正确做法首先识别并终止持久化机制删除 systemd 服务或 LaunchAgent删除~/.config/gh-token-monitor/然后轮换凭证3. 识别并移除受影响版本# 检查锁文件中是否存在受影响版本grep-Ekeyv: 6\.0\.0package-lock.jsongrep-Eflat-cache: 6\.1\.24package-lock.jsongrep-Efile-entry-cache: 11\.1\.6package-lock.json移除受影响版本改用已知良好版本。4. 将受影响系统视为已被入侵任何安装了受影响包或打开了受感染仓库的系统都应被视为可能已被入侵。从干净镜像重建这些系统。5. 轮换所有暴露的凭证在移除持久化机制后轮换npm 令牌GitHub 令牌和 PAT云服务商凭证AWS、GCP、AzureHashiCorp Vault 令牌Kubernetes 服务账户令牌SSH 密钥数据库凭证Stripe 和 Slack 令牌长期预防对于维护者启用分支保护—— 要求合并到主分支前必须经过 Pull Request 审查禁止直接推送。使用硬件安全密钥—— 对所有关键操作强制使用 WebAuthn 双因素认证。审计发布权限—— 定期审查谁和什么可以发布包。监控异常活动—— 留意意外提交尤其是对主分支的提交。使用独立账户—— 维护者账户用于编写代码使用单独且权限受限的服务账户进行自动化发布。对于组织在 CI 中阻止安装脚本—— 在 CI/CD 流水线中尽可能使用npm install --ignore-scripts。扫描依赖—— 使用能够检测恶意 preinstall 钩子和混淆代码的工具。锁定依赖版本—— 使用精确版本号而非^或~范围以避免意外的补丁升级。审计锁文件—— 定期审查package-lock.json是否有意外更改。将仓库视为执行面—— 在隔离环境中克隆和打开仓库尤其是在调查安全事件时。对于生态npm 应考虑对多年未使用preinstall钩子却突然添加该钩子的包进行额外验证。GitHub 应考虑标记那些通常使用 PR 流程却突然直接向主分支提交的账户。Sigstore 来源证明应包含源码完整性验证而不仅仅是构建完整性。真正的问题没有验证的信任此次事件从根本上说并非 npm、GitHub 或任何特定技术的漏洞而是关于我们如何将整个软件供应链建立在隐式信任之上。我们信任了维护者账户是安全的仓库中的源码是维护者所意图的来源签名意味着代码是安全的包管理器在安装期间只执行安全代码这些假设没有一项成立。攻击链之所以优雅并非因为它利用了一个零日漏洞而是因为它利用了信任—— 我们对维护者、构建系统、包注册表以及日常工具的信任。结语2026 年 8 月的 npm 蠕虫攻击是软件供应链安全的一个分水岭。它表明账户入侵已成为新的零日漏洞—— 最关键的漏洞不在代码中而在身份中来源证明不等于安全—— 一个已签名的包仍然可能是恶意的你的 IDE 现在是攻击向量—— 打开仓库与运行未知代码同样危险AI 编码助手是攻击目标—— 它们会在无人审查的情况下执行配置钩子应急响应必须进化—— 旧的行动手册先撤销后提问可能会适得其反维护者是受害者。npm 和 Sigstore 流水线完全按照设计运行。系统按设计工作 —— 而这正是问题所在。我们需要构建不依赖隐式信任的系统。每一步都需要验证。我们必须认识到在开源世界中维护者的笔记本电脑现在已成为攻击面的一部分。

相关新闻

声音导演诞生:960秒AI对话音频的魔法之旅

声音导演诞生:960秒AI对话音频的魔法之旅

声音导演诞生:960秒AI对话音频的魔法之旅 【免费下载链接】MOSS-TTSD-v0.5 项目地址: https://ai.gitcode.com/OpenMOSS/MOSS-TTSD-v0.5 🎯 痛点直击:当声音创作遇到三重障碍 想象一下,你正在创作一部有声小说&#xff0…

2026/10/17 12:24:49 阅读更多 →
ComfyUI-WanVideoWrapper:AI视频生成工作流的终极指南

ComfyUI-WanVideoWrapper:AI视频生成工作流的终极指南

ComfyUI-WanVideoWrapper:AI视频生成工作流的终极指南 【免费下载链接】ComfyUI-WanVideoWrapper 项目地址: https://gitcode.com/GitHub_Trending/co/ComfyUI-WanVideoWrapper 你是否曾梦想将静态图片变成生动的视频?或者用文字描述直接生成电影…

2026/10/16 11:42:56 阅读更多 →
技术解析:ArduPilot任务规划系统在多无人机协同作业中的应用与优化

技术解析:ArduPilot任务规划系统在多无人机协同作业中的应用与优化

技术解析:ArduPilot任务规划系统在多无人机协同作业中的应用与优化 【免费下载链接】ardupilot ArduPlane, ArduCopter, ArduRover, ArduSub source 项目地址: https://gitcode.com/GitHub_Trending/ar/ardupilot 在复杂的无人机应用场景中,如何高…

2026/10/18 17:22:35 阅读更多 →

最新新闻

Flutter for OpenHarmony幸运大转盘数据统计模块实现

Flutter for OpenHarmony幸运大转盘数据统计模块实现

幸运大转盘系列写到这里,前面九篇已经把页面结构、转盘动画、抽奖算法、奖品库存、历史记录都串起来了。说实话,我自己把整个流程跑通的时候,第一反应是“终于像个完整 App 了”,但紧接着就会发现一个被忽略的问题:到底…

2026/10/19 14:43:16 阅读更多 →
LabVIEW连接泰克示波器:VISA与SCPI编程实战指南

LabVIEW连接泰克示波器:VISA与SCPI编程实战指南

简介:这份 LabVIEW 连接泰克示波器范例,面向从事电子测试与信号分析、希望用 LabVIEW 远程控制示波器并实现自动化测量的工程师,适用于从基础功能连接到批量自动化测试的进阶场景。压缩包共包含166个文件,以153个 vi 程序文件为核…

2026/10/19 14:43:16 阅读更多 →
GSWOA优化Elman网络:多输入单输出预测的精度与稳定性提升

GSWOA优化Elman网络:多输入单输出预测的精度与稳定性提升

前几天帮一位做设备状态监测的同事看了组数据:一堆传感器读数、环境变量在前面排着,后面只有一列要预测的目标值。他试过线性回归,效果惨不忍睹;又试了BP神经网络,好了一些,但每次换随机种子结果就飘得厉害…

2026/10/19 14:43:16 阅读更多 →
Artcraft:手工艺数字化的三层翻译方法论

Artcraft:手工艺数字化的三层翻译方法论

1. “Artcraft”不是新词,而是被长期误读的设计实践范式“Artcraft”这个词最近突然在设计类社区、创意工作坊和高校课程大纲里高频出现,但翻遍主流设计史文献、权威术语词典甚至近十年的国际设计期刊索引,都找不到它作为独立概念的明确定义。…

2026/10/19 14:43:16 阅读更多 →
基于MySQL的人脸识别考勤系统设计与关键实现

基于MySQL的人脸识别考勤系统设计与关键实现

1. 为什么要自己动手做一套人脸识别考勤系统 先说个真实的痛点。某小型团队之前用的是那种指纹打卡机,一到冬天干燥季节,手指脱皮、静电干扰,一堆人打不上卡;后来换成刷卡,又有人忘带卡、代刷,月底对考勤记…

2026/10/19 14:43:16 阅读更多 →
国产卫星定标系数与光谱响应函数:从DN值到辐亮度的关键处理

国产卫星定标系数与光谱响应函数:从DN值到辐亮度的关键处理

简介:面向遥感数据处理、地理信息系统与地球观测应用开发者,这份数据包系统整理了高分系列(GF-1、GF-2、GF-4、GF-6)与资源系列(ZY-3、ZY-1 02C)等国产卫星的辐射定标系数和光谱响应函数,并提供…

2026/10/19 14:42:10 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →