{"schema_version":"1.0","service":"Publicasta","type":"article","id":290,"slug":"chaindrop_shai_hulud_npm_install_secrets_2026_08_09","title":"当 npm install 变成入口：冷静看待 ChainDrop","excerpt":"冷静梳理 Shai-Hulud npm 事件：发生了什么，provenance 的边界在哪里，以及团队如何检查 CI secrets 而不把下载量误当受害者数量。","language":"zh","default_language":"en","canonical_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=zh","image":{"url":"https://publicasta.com/storage/projects/9/pages/290/2026/08/97750d89-bcf8-4d9f-8916-37c6bd3565a3.webp","alt":"依赖关系图中的警告节点、CI runner 和受保护的密钥"},"publisher":{"id":9,"slug":"cybersecurity","name":"Cybersecurity Without Panic","url":"https://publicasta.com/cybersecurity"},"author":{"name":"Anton R"},"published_at":"2026-08-09T18:00:40+00:00","updated_at":"2026-08-09T18:00:40+00:00","content_markdown":"依赖安装本来应该很无聊。ChainDrop 这一轮围绕 Shai-Hulud 的 npm 供应链事件中，危险恰好出现在这个日常步骤：CI runner 或开发者电脑解析到被污染的 npm 包，包在安装阶段执行 lifecycle script，而这些环境里通常放着发布令牌、云访问权限和构建密钥。\n\n ![依赖关系图中的警告节点、CI runner 和受保护的密钥](https://publicasta.com/storage/projects/9/pages/290/2026/08/97750d89-bcf8-4d9f-8916-37c6bd3565a3.webp)\n\n ## 8 月 4 日到 9 日发生了什么\n\n Aikido、Socket、SafeDep、JFrog、Unit 42、Wiz、Endor Labs 等团队都发布了分析，指出这是一场与 Keyv 和 Cacheable 包族有关的 npm 供应链攻击。Aikido 报告称，最早可见的集群从 `keyv@6.0.0` 的发布路径被滥用开始，并牵涉 `flat-cache`、`file-entry-cache`、`cacheable-request`、`cacheable`、`@cacheable/memory`、`cache-manager` 等包。The Hacker News 后来把这一周概括为具有蠕虫式扩散特征的活动，影响范围已超出最初命名空间。\n\n 不同来源给出的数量不完全一致，这是因为研究人员发布文章时事件仍在变化。JFrog 提到 400 多个受影响包，SafeDep 和 Unit 42 在不同时间给出更高的包或版本计数，Endor Labs 强调某些依赖路径每周下载量巨大。这些数字不能相加，也不能直接当作受害者数量。它们描述的是包、版本或下载规模，不等于每次下载都执行了恶意代码。\n\n ## 为什么它不是普通恶意包事件\n\n 很多 npm 恶意事件来自拼写相似的假包或几乎没人用的小包。ChainDrop 更麻烦，因为入口包含许多团队会间接获得的 transitive dependencies。开发者可能从未主动选择 `keyv`，却通过框架、缓存层、linter、构建工具或服务端库把它带进项目。此时 lockfile 比人的记忆更可靠：危险版本可能藏在你以为自己安装的包下面好几层。\n\n 这次活动还击中了常见的信任信号。研究人员称，一些恶意版本通过看似合法的 release workflow 发布，并可能显示有效 provenance。Provenance 仍然有价值，但它回答的是窄问题：哪个 workflow、以哪个身份、在什么仓库上下文中生成了包。它不能证明 maintainer 账号没有被控制，不能证明 release commit 经过真实审查，也不能证明安装脚本适合在你的 runner 上执行。\n\n ## 安装阶段的攻击链\n\n 公开报告描述的链条并不复杂。被污染的版本加入 `preinstall` 之类的生命周期命令，启动 `node setup.mjs`。随后脚本加载混淆后的 JavaScript，研究人员提到过 `Math_Symbol.js`、`math_init.js` 等文件名，并在部分流程中使用 Bun 作为运行时。Bun 本身不是被攻破的组件，只是 payload 使用的工具。\n\n 恶意代码进入 CI 或开发机后，会寻找 npm 和 GitHub tokens、云凭据、Vault 和 Kubernetes 材料、SSH keys、`.env`、Terraform state、Docker 与 Helm 配置，以及 GitHub Actions runner 上短暂出现的 secrets。构建环境特别敏感，因为短生命周期凭据和 OIDC 派生 token 可能正好在 job 期间出现在环境变量或内存中。\n\n 蠕虫式扩散来自发布权限。如果 payload 拿到 npm publishing tokens，就可能发布受害者维护的其他包的感染版本；如果拿到 GitHub access，报告中还描述了仓库改动和持久化表面，例如 VS Code tasks 与 Claude Code settings 相关文件。并非每个文件都会自动执行，但它们说明攻击者想把开发自动化变成下一步入口。\n\n ## 如何判断自己是否暴露\n\n 先看证据，而不是看口号。按照 Aikido、SafeDep、Socket、JFrog、Unit 42 等来源列出的精确包名和版本，检查 `package-lock.json`、`npm-shrinkwrap.json`、`pnpm-lock.yaml`、`yarn.lock`、Bun lockfile、内部镜像和依赖扫描记录。不要只看直接依赖；这次问题的核心就是传递依赖。\n\n 然后确认相关时间窗口内是否真的执行过 install。CI 日志、构建时间、package-manager cache 创建时间、容器层历史和开发机 shell history，可以区分“lockfile 里出现过”和“代码已经运行过”。如果受影响版本只停留在 lockfile，处理可能限于 pin、更新和记录；如果它在有 secrets 的环境里运行过，就应把该环境视为已暴露。\n\n 不要用“升级到 latest”结束处理。升级只能避免未来安装已知坏版本，不能拿回已经复制走的 token。应隔离 runner 或工作站，保留必要日志，重建临时 runner，检查缓存、环境变量、开发工具和仓库改动。撤销 npm 与 GitHub tokens，检查 maintainers、2FA 和权限，再轮换云密钥、Vault、Kubernetes、SSH 与部署 secrets。\n\n 长期做法是把安装脚本当成特权代码执行。能用 `--ignore-scripts` 的地方就用；确实需要 lifecycle scripts 的包要显式批准；测试 npm 12 相关控制以及 pnpm、Yarn、Bun 的对应策略；为自动安装设置最小发布年龄；保持 runner 可重建；把 install、test、publish 分离。ChainDrop 不是开源失败的证明，而是提醒我们：`npm install` 不是下载，它常常是在钥匙旁边执行代码。","available_translations":[{"language":"ar","title":"عندما يصبح npm install مدخلًا للاختراق: ChainDrop بلا ذعر","html_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=ar","markdown_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.md?lang=ar","json_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.json?lang=ar","api_url":"https://publicasta.com/api/public/v1/channels/cybersecurity/articles/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=ar"},{"language":"de","title":"Wenn npm install zur Lücke wird: ChainDrop ohne Panik","html_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=de","markdown_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.md?lang=de","json_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.json?lang=de","api_url":"https://publicasta.com/api/public/v1/channels/cybersecurity/articles/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=de"},{"language":"en","title":"When npm install Became the Breach: ChainDrop Without Panic","html_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=en","markdown_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.md?lang=en","json_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.json?lang=en","api_url":"https://publicasta.com/api/public/v1/channels/cybersecurity/articles/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=en"},{"language":"es","title":"Cuando npm install se convirtió en la brecha: ChainDrop sin pánico","html_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=es","markdown_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.md?lang=es","json_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.json?lang=es","api_url":"https://publicasta.com/api/public/v1/channels/cybersecurity/articles/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=es"},{"language":"fr","title":"Quand npm install devient la brèche: ChainDrop sans panique","html_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=fr","markdown_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.md?lang=fr","json_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.json?lang=fr","api_url":"https://publicasta.com/api/public/v1/channels/cybersecurity/articles/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=fr"},{"language":"pl","title":"Gdy npm install staje się wejściem: ChainDrop bez paniki","html_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=pl","markdown_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.md?lang=pl","json_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.json?lang=pl","api_url":"https://publicasta.com/api/public/v1/channels/cybersecurity/articles/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=pl"},{"language":"ru","title":"Когда npm install стал точкой взлома: ChainDrop без паники","html_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=ru","markdown_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.md?lang=ru","json_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.json?lang=ru","api_url":"https://publicasta.com/api/public/v1/channels/cybersecurity/articles/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=ru"},{"language":"zh","title":"当 npm install 变成入口：冷静看待 ChainDrop","html_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=zh","markdown_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.md?lang=zh","json_url":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.json?lang=zh","api_url":"https://publicasta.com/api/public/v1/channels/cybersecurity/articles/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=zh"}],"_links":{"self":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.json?lang=zh","api":"https://publicasta.com/api/public/v1/channels/cybersecurity/articles/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=zh","html":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=zh","canonical":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09?lang=zh","markdown":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.md?lang=zh","json":"https://publicasta.com/cybersecurity/chaindrop_shai_hulud_npm_install_secrets_2026_08_09.json?lang=zh","channel":"https://publicasta.com/api/public/v1/channels/cybersecurity","channel_articles":"https://publicasta.com/api/public/v1/channels/cybersecurity/articles","search":"https://publicasta.com/api/public/v1/search","documentation":"https://publicasta.com/api-docs#reading-publicasta","openapi":"https://publicasta.com/api-docs/openapi.json","llms":"https://publicasta.com/llms.txt"}}