OpenAI 遭 TanStack npm 供应链攻击:两台设备受影响,代码签名证书全面轮换

2026-05-14 20 预计阅读时间:1 分钟
来源:oschina.net AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:10 分钟

2026年5月13日,OpenAI 发布安全公告,正式回应此前 TanStack npm 供应链攻击波及自身一事。结论是:两台员工设备被攻陷,但用户数据、生产系统、软件产物均未发现异常。尽管如此,OpenAI 依然选择全面轮换代码签名证书,并要求 macOS 用户在6月12日前完成应用更新。

这不是一次"没事就好"的轻描淡写——它暴露了 npm 供应链攻击的穿透力,以及代码签名证书在防御体系中的关键地位。

攻击是怎么穿透到 OpenAI 的

TanStack 是前端生态中广泛使用的开源库家族(Router、Query、Table 等),npm 周下载量达数百万次。攻击者通过某种方式获取了 TanStack 维护者的发布权限,在合法包名下推送了携带恶意代码的新版本。这类攻击的杀伤链很清晰:

  1. 劫持发布通道——拿到 npm publish 权限(凭据泄露、权限滥用或社会工程)。
  2. 植入恶意代码——在正常功能代码中夹带后门,通常在 install 或 postinstall 钩子触发。
  3. 沿依赖链扩散——任何直接或间接依赖该包的项目,npm install 时自动拉取恶意版本。

OpenAI 的两台员工设备,正是在开发环境中执行了 npm install 拉取到被篡改的 TanStack 包后受影响的。这说明:即便最终生产系统未被入侵,开发环境的"第一道防线"已经被突破。

为什么没有造成更大损失

OpenAI 公告强调三点未发现异常:

  • 用户数据未泄露——受影响设备是员工开发机,不含生产数据库访问凭据或用户数据直连通道。
  • 生产系统未入侵——开发环境与生产环境之间存在隔离(网络分段、CI/CD 管线审核),恶意代码未能跨越边界。
  • 软件产物未被篡改——最终交付给用户的二进制/安装包,经过独立签名和校验流程,未使用受影响设备上的构建产物。

这三条"未发现"背后,是多层防御在起作用:环境隔离、CI 管线控制、代码签名验证。但"未发现"不等于"不可能"——这正是 OpenAI 选择轮换证书的原因。

代码签名证书轮换意味着什么

代码签名证书是操作系统验证应用来源和完整性的信任锚点。macOS、Windows 在启动应用时,会校验签名证书链。如果证书私钥泄露或可能泄露,攻击者理论上可以签发看起来"来自 OpenAI"的恶意软件。

轮换证书的操作成本很高:

  • 旧证书签发的所有已发布版本将失去信任链(用户更新后才能识别新证书)。
  • macOS 用户必须在截止日期前更新,否则 Gatekeeper 会因为证书失效而拒绝启动应用。
  • CI/CD 管线中所有签名步骤需要重新配置。

OpenAI 设定6月12日为截止日期,本质上是在用时间窗口换安全余量——给用户足够的更新时间,同时确保旧证书在此日期后彻底失效。

开发者如何自查和加固

这次事件对任何依赖 npm 生态的团队都是一记警钟。以下是可直接操作的加固步骤。

1. 检查项目中是否曾拉取过被篡改的 TanStack 版本

# 查看项目中 TanStack 相关包的安装历史版本
# 将 @tanstack/react-query 替换为你实际使用的包名
npm ls @tanstack/react-query @tanstack/router @tanstack/table 2>/dev/null

# 检查 lockfile 中是否有可疑版本号(异常高的版本跳跃)
grep -E "@tanstack/(react-query|router|table)" package-lock.json | head -20

# 如果使用 pnpm
pnpm ls @tanstack/react-query @tanstack/router @tanstack/table

如果发现版本号异常(比如从 v5.x 突然出现 v5.x.99 或类似的可疑版本),立即锁定到已知安全版本:

# 锁定到确认安全的版本,然后重新安装
npm install @tanstack/react-query@5.62.0 --save-exact
npm install

2. 在 CI 中启用 npm 供应链安全审计

在 GitHub Actions 或任何 CI 管线中加入自动审计步骤,每次 install 前检查已知漏洞和可疑包:

# .github/workflows/supply-chain-audit.yml
name: Supply Chain Audit
on:
  pull_request:
  push:
    branches: [main]

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install dependencies
        run: npm ci

      - name: Run npm audit
        run: npm audit --audit-level=high
        # 如果发现 high/critical 漏洞,CI 直接失败

      - name: Check for suspicious postinstall scripts
        run: |
          # 扫描所有依赖中的 postinstall/preinstall 钩子
          SUSPICIOUS=$(npm ls --all --json 2>/dev/null | \
            python3 -c "
          import json, sys
          data = json.load(sys.stdin)
          for name, info in data.get('dependencies', {}).items():
            scripts = info.get('scripts', {})
            for hook in ['preinstall', 'install', 'postinstall']:
              if hook in scripts:
                print(f'{name}: {hook} -> {scripts[hook]}')
          ")
          echo "$SUSPICIOUS"
          # 人工审查输出,任何非必要脚本都应标记

      - name: Verify package integrity with sigstore
        run: |
          # 使用 npm sigstore 验证包签名(需 npm >= 10)
          npx sigstore verify @tanstack/react-query@5.62.0 || echo "签名验证失败,请审查"

3. 锁定依赖版本,禁止浮动版本号

// package.json — 禁止使用 ^ 或 ~ 前缀
{
  "dependencies": {
    // 错误做法:浮动版本,npm install 可能拉到新版本
    // "@tanstack/react-query": "^5.62.0"

    // 正确做法:精确锁定
    "@tanstack/react-query": "5.62.0"
  },
  // 强制 npm ci 使用 lockfile,禁止隐式升级
  "scripts": {
    "install:locked": "npm ci --ignore-scripts"
  }
}

--ignore-scripts 会跳过所有 postinstall 钩子,这是供应链攻击最常见的触发点。如果某些包确实需要 postinstall(如 native 二进制编译),单独白名单处理。

4. 如果你的团队也使用代码签名证书

轮换流程的核心步骤(以 macOS 应用为例):

# 1. 生成新的代码签名密钥对和 CSR
openssl req -new -newkey rsa:4096 -keyform PEM \
  -keyout new-signing-key.pem -out signing.csr \
  -subj "/O=YourCompany/CN=Your App Signing Certificate"

# 2. 向 Apple Developer Program 提交 CSR,获取新证书
#    (通过 Apple Developer Portal 手动操作)

# 3. 导入新证书到签名环境
security import new-signing-key.pem -k ~/Library/Keychains/signing.keychain

# 4. 更新 CI/CD 签名步骤,使用新证书 Identity
#    在 codesign 命令中指定新证书的 SHA-1 fingerprint
codesign --sign "NEW_CERTIFICATE_IDENTITY" \
  --force --timestamp --options runtime \
  dist/YourApp.app

# 5. 通知所有用户在截止日期前更新
#    在应用内弹窗、邮件通知、官网公告三管齐下

供应链攻击的防御清单

措施 作用 实施难度
npm ci + --ignore-scripts 阻止 postinstall 钩子执行
精确锁定版本号 防止浮动版本拉取恶意更新
CI 中 npm audit 自动拦截已知漏洞
sigstore 包签名验证 验证包来源真实性
开发环境与生产环境网络隔离 阻止攻击横向移动
代码签名证书定期轮换 限制私钥泄露的影响窗口
npm publish 权限最小化 减少凭据泄露面

OpenAI 这次"只损失两台开发机"的结果,不是运气——是环境隔离和签名验证在起作用。但两台设备被攻陷本身,说明开发环境的第一道防线(npm install 时的信任模型)已经失守。对任何依赖开源生态的团队来说,加固这条防线不是可选项,是必修课。

6月12日之前,如果你是 OpenAI macOS 应用用户,更新应用。如果你是 npm 生态的开发者,今天就可以跑一遍上面的审计脚本。


相关推荐