IPBUF安全漏洞报告
English
CVE-2026-45321 CVSS 9.6 严重

CVE-2026-45321 TanStack npm包供应链攻击漏洞 (GitHub Actions OIDC令牌窃取)

披露日期: 2026-05-12

漏洞信息

漏洞编号
CVE-2026-45321
漏洞类型
供应链攻击, 缓存投毒, 认证绕过
CVSS评分
9.6 严重
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
需要交互 (UI:R)
影响产品
TanStack (@tanstack/* npm packages)

相关标签

供应链攻击GitHub ActionsOIDCTanStacknpmCache PoisoningCVE-2026-45321

漏洞概述

2026年5月11日,TanStack项目遭遇了一起复杂的供应链攻击。攻击者利用GitHub Actions工作流中的配置缺陷,特别是`pull_request_target`的误用以及跨仓库的缓存投毒漏洞,成功从CI/CD运行环境中窃取了OIDC令牌。利用该令牌,攻击者以受信任的身份向npm官方仓库发布了84个恶意版本,覆盖了42个@tanstack/*相关软件包。这些恶意包包含凭据窃取恶意软件,对下游用户构成了极高的安全风险。

技术细节

该漏洞的核心在于攻击者精心构造的攻击链,突破了CI/CD的安全边界。首先,攻击者利用了`pull_request_target`触发器的特性,该触发器允许来自Fork仓库的Pull Request在基础仓库的高权限上下文中运行工作流。其次,攻击者利用了GitHub Actions缓存机制在Fork与基础仓库之间的共享特性,通过恶意PR将恶意代码注入到构建缓存中。当基础仓库运行CI流程时,加载了被污染的缓存并执行了其中的恶意脚本。最关键的一步是令牌窃取,攻击者的脚本通过扫描Actions Runner进程的内存空间(/proc/self/environ或内存转储),成功提取了用于npm OIDC认证的JWT令牌。由于该令牌具有合法的发布权限,攻击者无需修改发布工作流即可完成恶意包的发布。每个受影响包收到了两个相隔几分钟的恶意版本,这表明攻击者可能在进行多次尝试以确保覆盖不同的依赖解析场景。

攻击链分析

STEP 1
1. 初始化攻击
攻击者Fork目标仓库(TanStack/router),并创建一个恶意的Pull Request。
STEP 2
2. 触发工作流
利用`pull_request_target`事件触发CI工作流。该工作流在基础仓库的上下文中运行,拥有写入权限和访问OIDC令牌的权限。
STEP 3
3. 缓存投毒
工作流运行过程中,由于缓存配置不当,加载了被攻击者污染的构建缓存(包含恶意脚本)。
STEP 4
4. 令牌窃取
恶意脚本执行,通过读取进程内存(/proc/self/environ)提取了GitHub Actions OIDC JWT令牌。
STEP 5
5. 恶意发布
攻击者使用窃取的OIDC令牌,通过npm的trusted publisher机制,认证并发布了84个恶意版本的@tanstack/*包。

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
# Conceptual PoC: Detection script for suspicious TanStack package versions # Check if any @tanstack package was installed during the attack window (2026-05-11 19:20 - 19:26 UTC) import json import sys from datetime import datetime, timezone def check_package_lock(file_path): attack_start = datetime(2026, 5, 11, 19, 20, tzinfo=timezone.utc) attack_end = datetime(2026, 5, 11, 19, 26, tzinfo=timezone.utc) try: with open(file_path, 'r') as f: data = json.load(f) print(f"[*] Analyzing {file_path}...") # Simplified logic for package-lock.json structure if 'packages' in data: for path, details in data['packages'].items(): if '@tanstack' in path: # In a real scenario, check the 'integrity' hash or version publication time # Here we just flag the presence of the package for manual review print(f"[!] Suspicious package found: {path}") print(f" Version: {details.get('version', 'unknown')}") print(f" Action: Verify this version against official advisories.") except FileNotFoundError: print("Error: File not found.") except Exception as e: print(f"Error parsing JSON: {e}") if __name__ == "__main__": if len(sys.argv) > 1: check_package_lock(sys.argv[1]) else: print("Usage: python3 check_tanstack.py package-lock.json")

影响范围

@tanstack/* packages published between 2026-05-11 19:20 - 19:26 UTC

防御指南

临时缓解措施
开发者应立即检查项目中使用的TanStack相关依赖,确认是否安装了2026年5月11日UTC时间19:20至19:26之间发布的版本。如果发现受影响版本,请立即回滚并从官方渠道获取最新的安全版本。同时,建议清空本地npm缓存和构建缓存,防止残留恶意文件。对于仓库维护者,应全面审计GitHub Actions的工作流配置,修补缓存投毒漏洞。

参考链接