Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
npm-incident-response — 用于检测 keyv/cacheable 供应链攻击的扫描器:可发现受感染的 npm 包、验证 payload 哈希,并在仓库(repo)与主机(host)两种模式下查找持久化植入。 | Kitploit
工具/GitHubGitHub/securest8/npm-incident-response
漏洞扫描器持久化机制恶意软件分析数字取证供应链安全事件响应
GitHubsecurest8/npm-incident-response

npm-incident-response

用于检测 keyv/cacheable 供应链攻击的扫描器:可发现受感染的 npm 包、验证 payload 哈希,并在仓库(repo)与主机(host)两种模式下查找持久化植入。

查看仓库
2151个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

npm-incident-response

English | Português

针对 keyv/cacheable 供应链事件(“Shai-Hulud: Here We Go Again”,2026 年 8 月 4 日) 的独立扫描器——该事件中 440+ 个 npm 软件包遭一种自我传播的蠕虫入侵,它窃取云/CI 凭据,并植入带有**死手开关(dead-man's switch)**的持久化。

无需安装任何东西,几分钟内即可检测:

  • package-lock.json、npm-shrinkwrap.json、yarn.lock(v1 和 Berry)、pnpm-lock.yaml 与 bun.lock 中的受损软件包——包括传递依赖,并带完整链路(例如 eslint → file-entry-cache → flat-cache → [email protected]);
  • node_modules 中已安装的载荷(已知构件的名称 + SHA-256 哈希);
  • 尚未列入 IOC 清单的变种(启发式:可疑的生命周期脚本、带蠕虫名称的文件)——始终标记为 SUSPECT,没有哈希绝不确认;
  • 主机持久化植入物:LaunchAgent(macOS)、systemd 用户服务 + linger(Linux)、.claude/settings.json 与 .vscode/tasks.json 中的钩子、临时构件(bun-dl-*);
  • 死手开关:植入物监视 GitHub 令牌,当吊销返回 4xx 时执行远程命令。在清理主机之前轮换凭据会触发陷阱——报告会提醒你,下面的响应顺序可以避免这个错误。
  • 理解这次攻击

    1. 维护者账户:keyv/cacheable 系列的维护者账户被攻破;攻击者发布了带有 "preinstall": "node setup.mjs" 钩子的新版本——该代码在软件包安装之前运行,并拥有执行 npm install 者的权限。
    2. setup.mjs 从 GitHub 下载 Bun 运行时并在其中运行载荷——以此规避仅监控 node 进程的工具。
    3. Math_Symbol.js(约 728 KB,经过混淆)窃取凭据:AWS 实例元数据、AWS/GCP/Azure 密钥、Vault 令牌、Kubernetes 服务账户、GitHub Actions 机密、npm 令牌,外加对磁盘上私钥和 bearer 令牌的通用正则扫描。
    4. 它是一种蠕虫:借助窃取的 npm 令牌,它将相同的钩子注入该身份可发布的其他软件包,重新计算完整性哈希并重新发布。这就是它如何从约 10 个软件包扩散到数百个。
    5. 它无需固定 C2 即可外传数据(即时创建的 GitHub 仓库、DNS),并且留下一个陷阱——见下文。

    两条攻击途径(第二条更隐蔽)

    • **途径 A——安装:**自 2026-08-04 09:35 UTC 起,任何在启用生命周期脚本的情况下运行过 npm install/npm ci 的人。使用 --ignore-scripts 时,钩子不会运行。
    • **途径 B——克隆:**源仓库收到了 .claude/settings.json(SessionStart)和 .vscode/tasks.json(folderOpen)中的自动启动钩子,当克隆的文件夹被打开时就会运行加载器——无需 npm install,不需安装任何东西。这包括为调查事件而克隆仓库的人,以及打开过该目录的 AI 编程代理——这是 AI 代理钩子(.claude/)被用作供应链攻击途径的首批公开案例之一。

    陷阱(死手开关)

    植入物会安装一个“监视器”(gh-token-monitor),由 LaunchAgent(macOS)或 systemd 用户服务 + loginctl enable-linger(Linux)保持存活。它每 60 秒向 API 校验被盗的 GitHub 令牌。只要令牌有效,就什么都不会发生。当响应变为 4xx——也就是你吊销令牌的那一刻——它就会通过 eval 执行 ~/.config/gh-token-monitor/handler 的内容:一条由攻击者在远程定义的任意命令。公开分析尚不清楚其中包含什么——可能是数据销毁、重新植入、勒索软件,也可能什么都没有。该风险无法评估;这正是响应顺序必须严格遵守的原因。

    影响响应的三个特性:

    • 隔离网络是安全的:没有连接就没有 HTTP 响应,也就不会有 4xx——陷阱不会触发,数据外传也会停止。先隔离,切勿关机(易失性内存是证据)。
    • 触发后是一次性且自我清除的——之后行为无从解释,也不会留下任何可供调查的构件。
    • 约 24 小时 TTL:监视器一天后自毁。未发现构件并不能证明机器是干净的——扫描器在 host 模式下会就此发出警告。

    为什么常规防御通常会漏掉它

    • “签名是有效的”——[email protected] 随附了通过验证的 SLSA 证明。来源证明证明的是构建的完整性,而非源码:合法的流水线编译的是已被植入木马的代码。
    • “代码 diff 没有变化”——没错:库本身并未被修改。恶意之处在于 package.json(preinstall 钩子)和添加到软件包中的两个新文件(setup.mjs、Math_Symbol.js)。
    • “我们不用 keyv”——你们在用,只是间接的:最常见的链路是 eslint → file-entry-cache → flat-cache → keyv。正因如此,扫描器在每条发现中都会展示该链路。
    • “没有人运行过 npm install”——这不够:见途径 B。

    本仓库中的脚本是什么

    scan.mjs 具有以下特性——对任何响应供应链事件的人来说都很重要:

    • **单文件、约 880 行可读代码、零依赖。**无需 npm install。运行之前,可花 15 分钟审查整个 scan.mjs。
    • **零出站流量。**你的机器不会有任何数据流出。没有遥测,也没有“将结果发送去分析”。唯一的网络操作是 --update(下载最新的 IOC 清单),显式且可选。
    • **只读。**扫描器不会修改、删除或执行它发现的任何东西。
    • 可离线运行。docker run --network=none 或一台隔离机器:只需复制 scan.mjs + iocs.json。

    如何在你的公司使用它

    要求:Node.js ≥ 18(任何装有 npm 的机器都已具备)。下载这两个文件——scan.mjs + iocs.json——就可以了:无需安装。

    提醒:如果你克隆了整个仓库,fixtures/ 文件夹中包含测试所用的惰性 IOC(真实的名称和版本、虚拟内容——不含恶意软件)。扫描器会自动跳过它,并在输出中发出警告;只有当你故意扫描它时,才会出现来自它的发现。

    有两种运行模式,回答不同的问题,而这决定了在哪里运行:

    • repo 模式读取锁文件和 node_modules——而锁文件位于 git 中,因此可以集中化:一个人即可扫描公司里的每个仓库。
    • host 模式查找植入物(监视器、LaunchAgent/systemd、IDE 钩子),它位于代码执行所在的那台机器上——它不在 git 中,也无法集中化。

    第 1 步——AppSec 扫描所有仓库(一人、一台机器)

    root@kitploit:~
    node scan.mjs repo /folder/with/all/the/repos --json=result.json --html=report.html
    

    几分钟内回答“哪些项目已暴露”,无需惊动任何人。接受多个路径;会遍历子目录(包括 monorepo 和 workspace)。

    第 2 步——接触过受影响项目的人员扫描各自的机器

    对于每个有发现的项目,确定自 2026-08-04 09:35 UTC 以来接触过它的人(git log、CI 日志)。这些人在自己的机器上运行:

    root@kitploit:~
    node scan.mjs        # current directory + host, in ~30 seconds
    

    范围内人员:(a) 在该时间窗口内运行过 npm install/npm ci 的任何人;或 (b) 仅仅克隆并在 VS Code 或 AI 代理中打开过该文件夹的人——途径 B 无需安装。

    由于成本只有约 30 秒,且漏斗可能漏掉(一次随手的克隆、一个个人项目),最安全的内部通知是:每位开发者运行一次 node scan.mjs,并把 --json/--html 结果发送给 AppSec。发送是刻意设计为手动的——扫描器没有遥测(零出站流量)。

    第 3 步——CI runner 和构建服务器

    最高优先级:这里存放着最有价值的凭据。在这里,扫描器有两种不同的角色——一种面向过去,一种面向未来:

    对过去进行分诊——不要通过扫描 runner 来下结论。“这个 runner 是否被命中?”这个问题无法由扫描来回答:如果自 08-04 以来,有任何作业在未使用 --ignore-scripts 的情况下安装了受影响版本,那么凭据在那一刻就已经失窃,而 runner 主机很少保留证据(临时 runner 在作业结束时销毁容器;监视器约 24 小时内自我清除)。能回答这个问题的是第 1 步的锁文件和 CI 日志。如果答案是“是的,它安装了”:重建 runner 并轮换其机密——runner 是临时的,没有理由去清理它们。

    **面向未来的预防——是的,在流水线中运行它。**将扫描器作为构建步骤加入,使用 repo 模式,在 checkout 之后、npm install 之前。它不检查 runner 主机——它检查即将被安装的代码,并在恶意的 preinstall 有机会运行之前,以退出码让构建失败:

    root@kitploit:~
    # example (GitHub Actions / GitLab CI — adapt):
    - run: node scan.mjs repo . --json    # exit 0 clean · 1 findings · 2 COMPROMISED
    - run: npm ci --ignore-scripts         # only runs if the previous step passed
    

    快速参考

    root@kitploit:~
    node scan.mjs                     # scan the current directory + the host
    node scan.mjs repo /path/a /path/b
    node scan.mjs host                # persistence/implants on the machine only
    node scan.mjs repo . --json=result.json --html=report.html
    node scan.mjs --update            # update iocs.json (the only network operation)
    

    分诊

    级别含义操作
    COMPROMISED恶意版本已安装到 node_modules、载荷经哈希确认,或发现持久化植入物将主机视为已受入侵;遵循响应顺序——先清理植入物,再轮换凭据
    EXPOSED锁文件中锁定了恶意版本,无执行证据锁定安全版本,删除 node_modules,使用 --ignore-scripts 重新安装
    AT_RISKpackage.json 中的范围(^/~)可解析到恶意版本锁定精确版本,或在 registry 代理处将其屏蔽
    SUSPECT启发式(蠕虫文件名但哈希不匹配、可疑的生命周期脚本)手动检查——可能是新变体,也可能是误报
    INFO存在攻击途径但无 IOC(例如通用的 folderOpen 任务)审查

    报告作为证据

    --html 生成一份自包含的报告,包含时间戳、主机名、IOC 清单版本以及扫描器自身的 SHA-256——可用作事件通知的附件和审计追踪依据。

    如果扫描器报告 COMPROMISED:响应顺序

    暂时不要吊销或轮换任何凭据——那就是陷阱的触发开关。顺序如下:

    1. 隔离——将机器与网络断开。这是安全的:没有 HTTP 响应就没有 4xx,陷阱不会触发,数据外传也会停止。切勿关机(易失性内存是证据)。

    2. 保全——在删除任何东西之前(监视器约 24 小时内自毁):

    root@kitploit:~
    mkdir -p /tmp/evidence && cp -r ~/.config/gh-token-monitor /tmp/evidence/ 2>/dev/null
    cp /tmp/gh-token-monitor.*.log /tmp/evidence/ 2>/dev/null
    shasum -a 256 /tmp/evidence/* 2>/dev/null
    

    handler 文件就是攻击者将被执行的命令——不要运行它,不要把它粘贴到 shell 中;将其视为惰性文本。started_at 文件界定了暴露窗口(审计人员和监管机构会索要它)。

    3. 清除——先终止监视器进程,然后:

    root@kitploit:~
    # macOS
    launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.user.gh-token-monitor.plist
    rm -f ~/Library/LaunchAgents/com.user.gh-token-monitor.plist
    
    # Linux
    systemctl --user disable --now gh-token-monitor.service
    loginctl disable-linger "$USER"
    rm -f ~/.config/systemd/user/gh-token-monitor.service
    
    # both
    rm -rf ~/.config/gh-token-monitor ~/.local/bin/gh-token-monitor.sh /tmp/bun-dl-*
    

    另外,从 .claude/settings.json 和 .vscode/tasks.json 中移除恶意钩子,删除 setup.mjs/Math_Symbol.js/math_init.js 文件,并清除缓存(~/.npm/_cacache、pnpm、yarn)。再次运行 node scan.mjs host,直到结果干净为止。

    4. 轮换——只有在所有受影响主机都已清理并验证之后(哪怕只有一个存活的监视器,也足以触发开关)。先吊销 npm 令牌(阻止蠕虫继续传播);然后轮换 GitHub(PAT、部署密钥)、AWS/GCP/Azure、Vault、Kubernetes、CI 机密——以及磁盘上出现过的任何机密,因为曾发生过正则扫描。

    5. 审计——蠕虫以你的名义行事:在你的组织中查找描述为 Shai-Hulud: Here We Go Again 的仓库、自 08-04 以来非预期发布的 npm 版本(弃用它们并通知使用者),以及 started_at 窗口内 CloudTrail/审计日志中这些凭据的使用情况。

    之后:删除 node_modules,使用 --ignore-scripts 从干净的锁文件重新安装。对于已确认发生过执行的 CI runner 和主机:始终从零重建——任意代码已经执行,而已知构件清单并不能保证完整性。

    **受监管机构(巴西):**已确认的凭据访问入侵事件可能触发报告义务(Res. CMN 4.893/2021、Res. BCB 85/2021;若涉及个人数据,则适用 LGPD 第 48 条)。以 UTC 记录时间线——started_at、检测、遏制、清除、轮换——并与法务/合规部门确认时限。

    更新 IOC(用户)

    事件仍在活跃,清单也在不断增长。要获取最新清单:

    root@kitploit:~
    node scan.mjs --update          # the only operation that touches the network
    

    --update 从这个仓库(securest8/npm-incident-response)获取 iocs.json,绝不从第三方获取——Securest8 是策展入口。你得到的是这里最后发布的内容。

    维护 IOC(维护者)

    软件包列表来自 Wiz 公开数据源;哈希、C2 域名、持久化 IOC 和安全版本是静态的,并在 tools/gen-iocs.mjs 中人工维护。Wiz CSV 的快照保存在 tools/keyv-packages.csv,用于保证可复现性和离线运行。

    root@kitploit:~
    node tools/gen-iocs.mjs               # fetch the latest Wiz CSV, regenerate iocs.json + refresh the snapshot
    node tools/gen-iocs.mjs --offline     # regenerate from the committed snapshot, no network
    node tools/gen-iocs.mjs --allow-shrink # allow a package count lower than the snapshot (guarded by default)
    

    生成器是幂等的:它会保留现有的 manifest_version,在没有实质性变化时不重写文件;它还会拒绝写入空清单或缩减后的清单(以防上游数据源被截断/被改动)。

    自动化:.github/workflows/update-iocs.yml 每天(也可按需)运行生成器,并且只在 IOC 实际发生变化时才提交到 main——这样用户的 --update 大约一天内就能跟踪到 Wiz 数据源,完整历史均可在提交中审计。当事件平息、你想改为手动合并时,可把它切换为拉取请求步骤(工作流中已有说明)。

    测试

    root@kitploit:~
    node test/run-tests.mjs         # 15 assertions against fixtures/demo-repo
    

    fixtures/demo-repo 是一个测试仓库,内含惰性 IOC(真实的名称和版本、虚拟内容——不含恶意软件)。在扫描扫描器自身所在的仓库时,fixtures/ 文件夹会被自动跳过(输出中会给出警告);测试通过显式传入该路径来扫描它。

    范围与致谢

    这是一个面向单一事件的工具,专为攻击活跃窗口期内的快速分诊而构建——并非 Socket、Snyk 或同类工具的替代品。研究与 IOC:Socket.dev、Wiz Research(公开 CSV)、Kodem Security。

    由 Securest8 维护。MIT 许可证。

    下载工具