你今天早上肯定又敲了那行命令。npm install。然后顺手去倒了杯咖啡,回来继续写代码。但就在那几十秒里,你的机器已经执行了几十个陌生人写的脚本——他们可能是正经维护者,也可能是刚被钓鱼邮件骗走账号的受害者。
过去八个月,黑客们终于盯上了这块肥肉。一个叫"Shai-Hulud"的蠕虫家族已经攻陷了数百个npm包,创建了数万个恶意GitHub仓库,偷走上千条开发者密钥。2025年11月那一波尤其疯狂:48小时内,700多个包、2.7万个恶意仓库、约1.4万条暴露的密钥,波及487个组织。
![]()
我受够了等npm官方修这个问题,于是做了np-audit——一个零依赖的CLI工具,能在npm执行安装脚本之前,静态分析这些脚本到底想干什么。
攻击为什么一直奏效
每个Shai-Hulud变种都靠同样的三行代码:
{
"scripts": {
"preinstall": "node setup.mjs"
}
}
就这些。npm install解析到被攻陷的版本时,setup.mjs会在你的代码之前、测试之前、任何人眼检查之前运行。用的是你的用户权限、你的环境变量、你的网络访问。
载荷永远是同一套配方换个皮:
1. 下载第二个运行时(现在流行用Bun,能绕过Node特征检测)
2. 运行混淆过的收割机,扫描GitHub token、npm凭证、AWS/Azure/GCP密钥、Kubernetes服务账号token、Vault凭证、浏览器保存的密码、CI runner密钥
3. 加密后通过GitHub GraphQL API推送到公开仓库——从外面看就像正常的git活动
4. 用偷来的GitHub PAT往受害者能写的其他仓库里注入恶意工作流。一个开发者变成整个组织的零号病人
Mini Shai-Hulud还有个贴心的小设计:
if (locale.startsWith('ru') || lang.startsWith('ru')) {
process.exit(0); // do nothing
}
这个俄语地区保护开关,现在已经被归到TeamPCP名下的三个独立行动里出现了。
这不是漏洞,是功能
这里没有CVE可以打补丁。npm preinstall、install、postinstall脚本自动运行是设计如此——包要靠这个编译原生插件、拉平台二进制、配置构建工具。文档写着呢,故意的,也有用。
但这也是地球上每个Node项目里上了膛的枪,而且2018年以来一直在走火:event-stream、ua-parser-js、node-ipc、colors、faker,还有今年四月的Bitwarden CLI。攻击者不需要变得更 sophisticated,他们不需要。
官方建议是--ignore-scripts。但这会让bcrypt、node-sass、puppeteer、sharp和半个工具链挂掉。没人真在CI里开这个。
所以我们要么继续顶着枪过日子,要么先看看这些脚本到底要干什么再让它们跑。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.