在 Red Hat Cloud Services 中检测到恶意 npm 包
事件范围
- 恶意 npm 包被推送到了 Red Hat Cloud Services 的 JavaScript 客户端仓库,似乎是通过被攻陷的 CI/CD 管道(GitHub Actions + OIDC)完成的,而不是通过被盗的静态凭据。
- 受影响的包是编译进某些 Red Hat 容器镜像的前端库;影响看起来主要落在这些镜像的使用者身上,而不是直接的 npm 用户。
- 多项分析(在线程中有链接)列出了共享的管道,并将此归类为更广泛的“mini‑Shai-Hulud”/TrapDoor 风格 npm 蠕虫的一部分。
这是 npm 的问题,还是整个生态系统的问题?
- 许多人认为,所有现代语言的包管理器(npm、PyPI、crates.io、Composer、NuGet、RubyGems 等)都共享同样的核心风险:任何人都可以发布,代码以较大的权限运行,而且维护者往往是个人。
- 另一些人认为 npm 更糟,原因包括:
- 生命周期/postinstall 脚本在安装时默认运行任意代码。
- 巨大、深度嵌套的依赖图,以及大量微小包的文化。
- “始终更新到最新版本”的快速演进规范。
- 反方观点:生命周期钩子和类似特性在许多系统中都存在(dpkg/rpm、RubyGems、Pip、NuGet),因此有些人认为把责任只归咎于 npm 是不公平或带有偏见的。
提出的缓解措施
- 依赖冷却期(1–7 天),避免安装新发布的版本,依赖扫描器和维护者在这段时间内发现恶意代码。pnpm、Yarn 4、npm 11、pip、uv,以及第三方工具都支持这一做法。
- 支持者:成本低,在近期那些在数小时/数天内被发现的攻击中很有效。
- 怀疑者:如果所有人都延迟,攻击者可以加入定时炸弹;同时仍需要处理紧急 CVE。
- 加固 CI/CD:
- 将“构建/测试”和“签名/发布”作业分离,这样蠕虫就不能自动重新发布。
- 使用可信发布者、MFA、分阶段发布;但如果 CI 本身被攻陷,这些措施也帮不上忙。
- 缩小爆炸半径:
- 在容器、沙箱或低权限环境中运行安装/测试。
- 避免使用同时持有敏感密钥或钱包的开发机器。
- 治理与打包模型:
- 有人呼吁借鉴 Linux 发行版:受审查的维护者、多层审核、较慢的渠道(testing/unstable)。
- 也有人建议 vendoring 依赖、固定精确版本、避免不必要的库,并优先选择依赖图更扁平、更小的生态系统。
文化批评
- 多条评论把责任归咎于 JavaScript/Web 文化:小包泛滥、快速变化、深层传递依赖,以及对自动更新的高度依赖。
- 另一些人强调,用户在出问题之前更看重便利而非安全;安全被视为一种隐形需求,往往在后期才被补上。