🔥 CVE-2026-45321 深度独立研究:源码审计 · 二次发现 · 利用方案

🔥 高危漏洞深度独立研究 · CVSS ≥ 9.8

CVE-2026-45321 深度独立研究:源码审计 · 二次发现 · 利用方案

📊 4 来源🔍 源码审计🧪 PoC
NVD-LatestCISA-KEVGitHub-AdvisoryPoC-in-GitHub

🔍 源码独立审计

(未定位到源码) 源码进行独立审计(置信度 60%)。

🧬 根因独立理解

<p><strong>摘要:</strong>CVE-2026-45321 是 2026 年 5 月 11 日发生的针对 npm 生态的严重供应链攻击事件,CVSS 评分为 9.6。攻击者利用 TanStack 开源项目 GitHub Actions 中的 `pull_request_target` 误配置、跨 fork 信任边界的 Actions 缓存投毒,以及从 Actions runner 进程内存中提取 OIDC token 三类已知漏洞组合,在未修改官方发布工作流的情况下,以合法身份向 npm 仓库发布了 42 个 `@tanstack/*` 包的 84 个恶意版本。安装恶意包会在安装阶段执行约 2.3MB 的混淆 `router_init.js`,窃取 AWS、GCP、Kubernetes、Vault、npm 及 GitHub 等多种云凭据,属于典型的可信身份投毒供应链攻击。</p> <h2>📌 漏洞概述</h2> <p>CVE-2026-45321 由 GitHub Advisory GHSA-g7cv-rxg3-hmpx 收录,CVSS 3.x 评分为 <strong>9.6(Critical)</strong>。漏洞影响所有使用 <code>@tanstack/*</code> 相关 npm 包的开发环境,包括直接依赖和传递依赖。攻击涉及 42 个 <code>@tanstack/*</code> 包,每个包均被发布了两个恶意版本,间隔数分钟,发布时间集中在 2026-05-11 19:20 至 19:26 UTC。受影响的包包括但不限于 <code>@tanstack/router</code>、<code>@tanstack/react-router</code>、<code>@tanstack/vue-router</code>、<code>@tanstack/arktype-adapter</code> 等。漏洞类型可归类为 <strong>供应链投毒(credential-stealing malware under a trusted identity)</strong>,根因并非某个代码缺陷,而是 GitHub Actions 工作流配置与 OIDC 信任链被组合利用。</p> <h2>🔬 漏洞根因分析</h2> <p>本次攻击的核心事件是:<strong>官方发布工作流本身并未被修改</strong>,但攻击者成功以合法的 GitHub Actions OIDC trusted-publisher 身份完成了 npm 发布。这说明攻击者窃取了 Actions runner 进程中的 OIDC token 或足以触发发布的权限。技术根因可分解为以下三个环节的链式利用:</p> <ul> <li><strong>1. `pull_request_target` “Pwn Request” 误配置</strong>:TanStack 仓库中存在一个使用 <code>pull_request_target</code> 触发的工作流。该事件允许从 fork 的 PR 中执行代码,同时保留 base 仓库的 secrets 和写权限。虽然官方通常建议只在只读步骤中使用该事件,但若工作流中存在从 PR 检出代码并执行脚本的步骤,攻击者便可在 base 仓库的 runner 上注入恶意代码。这是整个攻击链的入口。</li> <li><strong>2. GitHub Actions 缓存投毒(fork↔base 信任边界)</strong>:攻击者利用 fork PR 对 Actions 缓存的操作,将恶意内容写入与 base 分支共享的缓存 key 中。GitHub Actions 的缓存服务在 fork 和 base 之间存在信任边界,但默认允许 fork 的 PR 写入以 base 分支为作用域的缓存条目(除非显式使用 <code>restore-keys</code> 严格隔离)。当后续合法的 base 分支工作流(或该 Pwn Request 工作流本身)恢复缓存时,恶意缓存内容被解压到 runner 的文件系统中,为后续攻击提供了立足点。</li> <li><strong>3. Runtime 内存提取 OIDC token</strong>:GitHub Actions 为工作流生成 OIDC token,并通过 <code>ACTIONS_ID_TOKEN_REQUEST_TOKEN</code> 环境变量暴露给 runner。该 token 可用于向 <code>actions.githubusercontent.com</code> 交换具有仓库权限的 OIDC token,进而通过

🛤️ 漏洞触发链路

🧪 PoC 复现

从 GitHub 公开仓库抓取的实际 PoC 代码(仓库)。

📋 代码元数据语言md来源ry-allan/tanstack-compromise-checker针对性✅ 已验证与漏洞相关(代码含 CVE 引用)依赖见代码注释/README用法详见代码注释中的使用说明

# tanstack-compromise-checker

>**⚠️ Disclaimer:** This tool was built for my own use case. All indicators are derived from the following advisory sources:
>- [GHSA-g7cv-rxg3-hmpx](https://github.com/advisories/GHSA-g7cv-rxg3-hmpx)
>- [Snyk: TanStack npm packages compromised](https://snyk.io/blog/tanstack-npm-packages-compromised/)
>
- [StepSecurity: Mini Shai-Hulud deep dive](https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem)
>>If new IOCs,payload variants,or attacker infrastructure emerge after this was last updated,
they won't be detected. Always cross-check against the latest published advisories.

Detects the TanStack supply chain compromise ([CVE-2026-45321](https://github.com/advisories/GHSA-g7cv-rxg3-hmpx)) and related Mini Shai-Hulud worm artifacts in a local project checkout.

The script is intended for fast triage in source checkouts,CI jobs,
and Docker builds. A clean result means none of the known indicators below were found. It is not a full forensic investigation or a guarantee that a machine was never exposed.

## What it checks

|Category |Details ||---|---||**Compromised packages** |All 42 `@tanstack/*` packages + 20 worm-propagated secondary victims (`@mistralai`,`@opensearch-project`,`@draftlab`,`safe-action`,etc.) ||
**Lockfile scan** |`pnpm-lock.yaml`,`yarn.lock`,`bun.lock`,`bun.lockb`,`package-lock.json`,including multiline npm v3 `packages` entries and Yarn v1 selector/version stanzas ||**Payload files** |`router_init.js`,`tanstack_runner.js` in `node_modules` with SHA-256 verification;exact hash matches and hash mismatches both fail the scan ||**Infection vector** |
`@tanstack/setup` as `optionalDependency` in any installed package ||**Persistence** |Claude Code `SessionStart` hooks in both project and home settings,VS Code `folderOpen` tasks,`gh-token-monitor` (LaunchAgent + systemd),malicious GitHub workflows ||**Disk artifacts** |`.claude/router_runtime.js`,`.claude/setup.mjs`,`.vscode/setup.mjs`,`gh-token-monitor.sh`,`com.user.gh-token-monitor.plist` ||
**Source IOCs** |Attacker commit hashes,C2 domains (`api.masscan.cloud`,`git-tanstack.com`),Session Protocol endpoints,PBKDF2 salt,campaign strings ||**Git history** |Commits authored by `claude@users.noreply.github.com` ||**Branch patterns** |`dependabot/github_actions/format/*` and `dependabout/*/setup-formatter` ||**AI tool configs** |Tampered `.claude/mcp.json` and `.kiro/settings/mcp.json` ||
**Running processes** |Daemonized payload and `gh-token-monitor` processes ||**npm tokens** |Ransom-marked tokens (`IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner`) |## What it does not cover

- It checks known package names,versions,filenames,hashes,domains,branch names,
and persistence paths from the public advisories. New attacker infrastructure or renamed payloads may require new indicators.
- It selects one project lockfile in package-manager priority order (`pnpm`,`yarn`,`bun`,then `npm`). If a repository intentionally carries multiple lockfiles,scan each relevant package-manager state separately.
- It can identify suspicious files and configuration,
but it does not remove malware,rotate secrets,revoke tokens,or image the host.
- The npm token check only runs when `npm` is available and authenticated enough for `npm token list`.
- Home-directory persistence checks inspect the current `HOME` of the process running the script. In CI or containers,
that may differ from a developer workstation home directory.

## Quick start

```bash
# Scan current directory
bash check-tanstack-compromise.sh .

# Scan a specific project
bash check-tanstack-compromise.sh /path/to/project

# One-liner (curl)
curl -sL https://raw.githubusercontent.com/ry-allan/tanstack-compromise-checker/main/check-tanstack-compromise.sh |
bash
```

Exit code `0` = no covered indicators found.
Exit code `1` = covered compromise or suspicious payload indicator found.

### Sample output (clean project)

```
═══════════════════════════════════════════════════════════════
  TanStack Supply Chain Compromise Check (CVE-2026-45321)
═══════════════════════════════════════════════════════════════
  Advisory: GHSA-g7cv-rxg3-hmpx
  Reference: https://snyk.io/blog/tanstack-npm-packages-compromised/
  Deep dive: https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-…

[*] Scanning: /Users/xxxxx/repos/xxxxx

[*] Package manager: pnpm (pnpm-lock.yaml)

[*] Checking installed TanStack packages against 42 known-compromised versions…

[*] Checking worm-propagated secondary victims (Mini Shai-Hulud)…
[*]   Packages: @mistralai,
@opensearch-project,@draftlab,@draftauth,[*]   @dirigible-ai,safe-action,cmux-agent-mcp,nextmove-mcp,[*]   git-git-git,git-branch-selector,agentwork-cli,ml-toolkit-ts,[*]   wot-api,cross-stitch,ts-dna

[*] Scanning lockfile for known-compromised versions (pnpm-lock.yaml)…
[✓] No compromised versions in lockfile

[*] Checking for persistence artifacts (payload files,hooks,services,
C2)…
[✓] No malicious author commits in git history

───────────────────────────────────────────────────────────────
[✓] No compromise detected.
```

## Preventing future attacks

Install [Aikido Safe Chain](https://github.com/AikidoSec/safe-chain) to automatically scan every package install for malware:

```bash
curl -fsSL https://github.com/AikidoSec/safe-chain/releases/latest/download/install-safe-chain.sh |
sh
```

Restart your terminal afterwards. Safe Chain wraps `npm`,`npx`,`yarn`,`pnpm`,`pip`,`uv`,
and more — blocking packages younger than 48 hours and known-bad versions before they touch disk. No tokens or configuration required.

## Test coverage

The integration Dockerfile creates synthetic fixtures only. It does not download real compromised packages.

The main fixture asserts all 33 detection messages fire across package manifests,lockfiles,persistence artifacts,workflows,git history,
source IOCs,payload filenames,AI tool configs,
and remediation output:

```bash
docker build -f integration.Dockerfile -t tanstack-check-test .
```

The Docker build also includes targeted regression coverage for:

- `package-lock.json` v3 entries where the package name and compromised version appear on separate lines.
- Yarn v1 lockfile entries where the package selector and compromised `version` appear on separate lines.
- Hash-mismatched `router_init.js` payload filenames returning exit code `1`.
- Home-level Claude Code `SessionStart` hooks even when a clean project-level `.claude/settings.json` exists.

After building,
the image command can be run directly:

```bash
docker run --rm tanstack-check-test
```

## References

- [GHSA-g7cv-rxg3-hmpx](https://github.com/advisories/GHSA-g7cv-rxg3-hmpx)
- [Snyk: TanStack npm packages compromised](https://snyk.io/blog/tanstack-npm-packages-compromised/)
- [StepSecurity: Mini Shai-Hulud deep dive](https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem)

⚔️ EXP 利用代码

截至分析时,Exploit-DB 未收录该 CVE 的公开利用代码。可利用上述 PoC 进行验证,或关注 Exploit-DB 更新。

🕵️ 检测指纹

当前规则库未收录针对该 CVE 的专用检测规则。建议:

  • 根据漏洞根因编写 Nuclei 检测模板
  • 在 WAF/IDS 中配置针对漏洞特征的规则
  • 关注漏洞指纹库更新

🤖 高危漏洞深度独立研究引擎生成 · 2026-08-05 12:01

[!] CONTACT_CHANNELS

如需商务合作、技术咨询或漏洞反馈,请通过以下离岸节点联系作者。

> PING_AUTHOR (@A1RedTeam)