imik

好像遇到了 npm 投毒事件

  •  
  •   imik · 2 days ago · 1093 views

    今天用 pnpm update 更新依赖后,mac 提示添加了新的启动项、背景任务,文件是个 cat.py 文件,让 codex 分析了代码内容,发现是远程执行代码,流程:

    1. 静默安装依赖:requests 、cryptography ,失败也尽量隐藏。
    2. 每小时访问 GitHub Commit Search API: https://api.github.com/search/commits 。
    3. 搜索最新包含 firedalazer 的 commit 。
    4. 从 commit message 里解析:
    firedalazer <base64-url>.<base64-signature>
    5. 用脚本内置 RSA 公钥验证签名。也就是说,只有持有对应私钥的人能下发“合法命令”。
    6. 解码出 URL ,下载该 URL 返回的 Python 代码。
    7. 写入临时 .py 文件并执行:
    subprocess.run(["python3", temp_path], ...)
    8. 把已执行 URL 的 hash 记录到:
    /var/tmp/.gh_update_state
    

    搜索到类似的一个攻击是 vscode 扩展 nx console 的投毒: https://www.stepsecurity.io/blog/nx-console-vs-code-extension-compromised

    但我这是 npm ,告诉 codex 是执行 pnpm 操作后发生的,它查了相关日志,最终锁定是一个叫做 @antv/setup 的包有问题:

    你的项目 package.json
    └── @antv/g6 ^4.8.24
        └── @antv/g6 4.8.25
            └── @antv/g6-pc 0.8.25
                ├── @antv/dom-util 2.2.4
                │   └── optionalDependencies: @antv/setup
                ├── @antv/matrix-util 3.2.4
                │   └── optionalDependencies: @antv/setup
                └── @antv/layout / @antv/util 分支
                    └── @antv/util 3.5.11
                        └── optionalDependencies: @antv/setup
    

    @antv/setup: github:antvis/G2#1916faa365f2788b6e193514872d51a242876569

    完整流程:

    1. 执行 pnpm update 做依赖更新
    2. 项目依赖 @antv/g6 被解析/更新
    3. @antv/g6 的子依赖里出现可疑 AntV 包 metadata
    4. 这些包声明 optionalDependencies: @antv/setup
    5. pnpm 下载 github:antvis/G2#1916faa365f2788b6e193514872d51a242876569
    6. 该 tarball 被当作 @antv/[email protected] 安装
    7. @antv/setup 的 prepare 脚本执行:
          bun run index.js && exit 1
    8. 混淆的 index.js 在你机器上落地持久化文件
    9. 写入 LaunchAgent 启动项
    10. 启动 ~/.local/share/kitty/cat.py
    11. cat.py 每小时轮询 GitHub commit 搜索结果
    12. 如果攻击者发布带签名的指令,就下载远程 Python 并执行
    
    5 replies    2026-05-19 15:16:31 +08:00
    imik
        1
    imik  
    OP
       2 days ago
    https://www.npmjs.com/package/@antv/dom-util/v/2.2.4?activeTab=code

    看 package.json 里有这个 @antv/setup ,现在 latest tag 已经指回去了
    imik
        2
    imik  
    OP
       2 days ago
    @antv/dom-util
    @antv/matrix-util
    @antv/util
    这些几年不更新的包,两小时前都发布了两个版本,optionalDependencies 里加了上面的 @antv/setup
    imik
        3
    imik  
    OP
       2 days ago
    受害者账号是这个: https://www.npmjs.com/~atool
    chitanda
        4
    chitanda  
       2 days ago   ❤️ 1
    我们 CI 也撞了,入口包是 @antv/x6 → @antv/[email protected] ,optionalDependencies 也指到同一个 antvis/G2 commit 1916faa3 。同一个被劫账号 atool 。所以受牵连的不只 @antv/g6 那几条链。

    没中招是运气好——runner 镜像默认 node:18.20.0 不带 bun ,preinstall 跑 `bun run index.js` 直接 command not found ,install 整体挂掉,payload 没机会跑。如果环境有 bun 估计就和你一样了。

    触发条件挺刁:lockfile 是 v9 ( pnpm 9 生成)但 CI 装的是 pnpm@latest-8 ,pnpm 8 看到不兼容直接 ignore ,加 --no-frozen-lockfile ,@antv/x6-geometry 就从锁的 2.0.5 ( 3 年前的合法版)漂到刚发的 2.2.5 。三个条件少一个都不会撞。

    safedep 今天发了完整分析:
    https://safedep.io/mini-shai-hulud-strikes-again-314-npm-packages-compromised
    631 个恶意版本跨 314 个包,22 分钟批量发完。

    antvis/G2 也有 [SECURITY] issue 了:
    https://github.com/antvis/G2/issues/7394

    那个 `&& exit 1` 挺阴的,payload 跑完凭据偷走才故意让 prepare 报错,让人以为是构建 bug 去查 lockfile ,攻击成功反而藏在 install 失败里。看到 ERR_PNPM_PREPARE_PACKAGE 别只想着 lockfile 。

    几个 IoC 摘几条。恶意 index.js 是 ~500KB 单行无换行混淆,obfuscator.io 风格 hex 变量名。payload SHA256 是 a68dd1e6a6e35ec3771e1f94fe796f55dfe65a2b94560516ff4ac189390dfa1c 。攻击者用偷的 token 创建的 C2 仓库命名是 Dune 词配数字,比如 sardaukar-sandworm-42 这种。CI 环境会被识别,GITHUB_ACTIONS / GITLAB_CI 等 20+ 平台都覆盖,OIDC 会被换成 npm publish token 。

    package.json 里加 pnpm overrides 钉版本:

    "pnpm": { "overrides": { "@antv/x6-geometry": "2.0.5" } }

    用到的每个 @antv 包都得钉,今天先别 install 。
    Bronya
        5
    Bronya  
       2 days ago
    又是投毒😦
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   978 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 22:27 · PVG 06:27 · LAX 15:27 · JFK 18:27
    ♥ Do have faith in what you're doing.