NPM 作为 JavaScript 生态的核心包管理器,其 typosquatting(错别字劫持)攻击已成为供应链安全的隐形杀手。攻击者通过注册与热门 scoped packages(如 @scope/pkg)高度相似的包名,诱导开发者误装,并在 package.json 中注入恶意 postinstall 或 preinstall 脚本。这些脚本在 npm install 时自动执行,常伪装成无害工具安装(如 Bun runtime),实则加载 obfuscated payload,窃取凭证、扫描文件系统并在 CI/CD 管道中横向传播。GitLab Vulnerability Research 团队最近发现的 Shai-Hulud v2 变种,正是此类攻击的典型:感染包的 preinstall 脚本执行 setup_bun.js,进而运行 10MB 的 bun_environment.js 负载,导致 GitHub/npm/AWS 等凭证外泄与蠕虫式传播。
攻击的核心在于 postinstall/preinstall 脚本的隐蔽执行机制。这些脚本在 npm install 阶段运行,绕过常规代码审查,尤其在 CI/CD 环境中,devDependencies 常被忽略安装,导致生产镜像 compromised。Shai-Hulud v2 的初始向量虽未明确 typosquatting,但其 propagation 阶段使用窃取的 npm token 自动感染维护者其他包,并增补版本号 republish,放大 scoped packages 的风险——开发者常省略 @scope 前缀,如误装 core-tracing 而非 @azure/core-tracing。负载执行后,立即枚举环境变量(ghp_/gho_ 开头的 GitHub token)、~/.npmrc 文件及云 SDK 配置,同时下载 Trufflehog 扫描 home 目录秘密,exfil 到标记为“Sha1-Hulud: The Second Coming”的 GitHub repos。更危险的是 dead man's switch:若同时失连 GitHub/npm,触发数据销毁(Windows: del /F /Q /S %USERPROFILE%* + cipher /W;Unix: shred -uvz -n1)。
检测此类攻击需从静态审计入手。首先,强制审查 package.json 中的 scripts 字段:禁止或 sandbox 执行 curl -fsSL https://bun.sh/install | bash 或 powershell -c "irm bun.sh/install.ps1|iex" 等命令,这些是 Shai-Hulud 的典型 loader。参数阈值:postinstall 脚本长度 >5KB 或含 eval/atob 等动态执行,标记高危;使用 Levenshtein 距离计算包名相似度,若 <3 与热门包(如 lodash)匹配,触发警报。工具集成:npm audit + Snyk 扫描 transitive deps,结合 GitLab Dependency Scanning 检查 lockfile 中的感染包。
在 CI/CD 管道中,实施零信任安装策略。使用 npm ci --production --ignore-scripts --no-audit 跳过 scripts 执行,仅安装 prod deps;对于 scoped packages,配置 .npmrc 中的 scope=registry.npmjs.org/@scope 并 audit 前缀完整性。清单如下:
- Lockfile 固定:commit package-lock.json,CI 中 npm ci --strict-peer-deps,若 resolved URL 变异或 integrity sha512 不匹配,回滚。
- 脚本禁用:.npmrc 设置 ignore-scripts=true;postinstall 需手动 approve,超时 30s 杀掉进程。
- IoC 扫描:grep -r "bun_environment.js|.truffler-cache|Sha1-Hulud" node_modules/;监控进程如 shred 或 cipher /W。
- 动态沙箱:Docker --security-opt no-new-privileges --read-only --tmpfs /tmp:/tmp,限制网络出站至白名单。
- 签名验证:集成 Sigstore/npm-provenance,验证 tarball sig;阈值:无 sig 或 issuer 非 npmjs,reject。
零日响应强调速度与最小破坏。发现异常后,立即隔离机器:kill npm/yarn 进程,rm -rf node_modules;扫描全盘 IoC(如 .truffler-cache/trufflehog),rotate 所有 creds(GitHub PAT、npm token、云 keys)。监控 GitHub search "Sha1-Hulud: The Second Coming" repos,若现身 fork/delete 并报告 CISA。参数:响应 SLA <1h,凭证轮换覆盖 90 天内 install 的包;回滚策略:pin deps 到事件前版本,如 "pkg": "^1.2.3" 而非 "*"。
进一步强化,部署持续监控:Dependabot alerts on new postinstall;自定义 CodeQL 查询检测 env 检查 + exec(如 process.env.NODE_ENV === 'production' 后 spawn)。对于 scoped packages,建立内部镜像 + 白名单,Levenshtein 阈值 2 内包需手动 review。风险量化:CI 中 dev deps install 概率 70%,postinstall 执行率 40%,结合传播链可 compromise 整个 org。
实战案例验证:在 GitLab CI,使用 Security Analyst Agent 查询“Are any dependencies affected by Shai-Hulud?”,结合 Duo Chat 快速 triage。最终,防范不止工具,需文化:install 前 npm view pkg dist-tags --json 检查最新发布者/日期异常。
资料来源:GitLab 博客(2025/11/22),CISA Shai-Hulud Alert(2025/09/23),OSSF NPM Best Practices。