8月4日,npm生态爆发一起重大供应链安全事故。攻击者入侵了极流行的键值存储库keyv的维护者GitHub账户,并借此在其名下所有软件包中投递了凭据窃取恶意代码。keyv自身的每周下载量约为1.27亿次,而同一维护者还掌管着cacheable、flat-cache、file-entry-cache、cache-manager、cacheable-request等一系列高下载量缓存工具包,全部受到波及。据安全公司Aikido向Cybersecuritynews独家提供的研究资料,恶意的预安装脚本在数小时内便如蠕虫般扩散至数百个原本无关的软件包,截至当日中欧夏令时13:20,已有868个包的1381个版本被确认遭到篡改,数字还在持续攀升。
攻击的源头是维护者GitHub账户凭据失陷。攻击者没有采用传统的窃取维护者npm令牌方式,而是直接获得了仓库的写权限。随后,他们在每个受影响仓库的主分支直接提交恶意文件,并紧接着发布新版本。这些新版本通过GitHub Actions生成的有效来源签名(provenance signatures)被推送至npm注册表,使任何审计供应链完整性的工具都将其视作合法发布。一个持有正常构建签名的恶意包,对依赖方几乎防不胜防。
每个被篡改的包都被植入了两个新文件:setup.mjs和Math_Symbol.js,同时在package.json中静默添加了一个“preinstall”钩子。只要开发者执行npm install,preinstall脚本就会自动触发,启动setup.mjs。这一文件是一个高度混淆的植入器,它会从GitHub的发布地址悄悄下载Bun JavaScript运行时,并在完全无提示的情况下使用该运行时执行真正的载荷——Math_Symbol.js。整个过程对开发者不可见,既没有弹出的命令行窗口,也不需要任何额外操作。
载荷Math_Symbol.js内置了一套凭证提取器,专门针对开发机与CI运行环境中常见的密钥存储位置。它会读取.npmrc文件中的npm注册表认证令牌、GitHub CLI配置里的经典个人访问令牌、会话令牌以及OIDC令牌;同时直接从~/.aws/credentials文件窃取AWS访问密钥与会话令牌。此外,恶意代码还尝试获取HashiCorp Vault客户端令牌,优先检查VAULT_TOKEN环境变量,若该变量不存在,则通过HTTP回退尝试获取令牌。这些凭据是开发者用来发布软件包、访问代码仓库以及控制云资源的核心密钥。一旦失窃,攻击者相当于拿到了通往整个软件交付链路的钥匙。
该恶意软件被命名为Shai-Hulud战役的一部分,其自传播设计是造成大规模扩散的关键。当某个使用被投毒包的CI环境或开发者机器被感染后,窃取的npm访问令牌和GitHub凭据就可以被攻击者用来发布更多携带同样恶意代码的新版本,或者直接污染其他未受影响的仓库。Deliveroo、Qlik、Picsart等知名组织的相关软件包版本中均已发现受感染的情况,表明恶意代码已经成功跳出原始维护者的包群,波及第三方项目。
这一事件暴露出当前软件供应链防线中的两处薄弱环节。其一,账户失陷后的自动化发布流程仍能照常生成有效签名,使得本应作为可信验证的来源签名形同虚设。其二,npm生态对preinstall脚本的默认执行机制使恶意代码能在安装瞬间启动,开发者几乎没有任何事前拦截的手段。而受影响包的范围覆盖了从底层缓存工具到高层封装的各种库,意味着许多间接依赖这些包的应用程序都可能面临凭据泄露的风险,排查与修复的难度不容低估。
截至Aikido最新统计,已确认被污染的包包括keyv、cacheable、flat-cache、file-entry-cache、cache-manager、cacheable-request以及@cacheable范围内的多个scoped包,其中flat-cache月下载量高达5.65亿次,file-entry-cache月下载量达5.57亿次,cacheable月下载量也达到2900万次。所有使用这些包的个人开发者、团队和企业都应立即检查自己的环境下是否有setup.mjs或Math_Symbol.js文件,并回滚到可信版本。同时,建议轮换所有可能暴露的凭据,尤其是npm令牌、GitHub令牌和AWS密钥。
热门跟贴