TanStack npm 供应链攻击后,代码 Agent 还该不该默认放行 npm install?

TanStack npm 供应链攻击后,代码 Agent 还该不该默认放行 npm install?

上周这类问题还很容易被当成“前端生态自己的事”。但到了 2026-05-11 这波 TanStack npm 供应链攻击,判断门槛已经变了:如果你的代码 Agent、CI runner 或开发机还默认放行 npm install,而且同一进程还能读到云凭据、GitHub token、SSH key 或 ~/.npmrc,那它现在就不该被视为“低风险默认动作”。

短答案: npm install 权限现在更像生产写权限,不像普通依赖安装动作。更稳妥的做法是把“审包”和“执行安装”拆开:先用 npm pack 拉 tarball 做静态检查,再把真正的安装放进隔离环境,默认加 --ignore-scripts,只有白名单包再放开脚本执行。

这篇的最小复现实验(本文写作时,Node 22.22.0 / npm 10.9.4):

npm pack ./postinstall-proof-fixture
POSTINSTALL_MARKER=/tmp/default-marker npm install ./postinstall-proof-fixture-1.0.0.tgz
POSTINSTALL_MARKER=/tmp/ignore-marker npm install ./postinstall-proof-fixture-1.0.0.tgz --ignore-scripts

我本地看到的结果是:npm pack 不会触发测试包里的 postinstall,普通 npm install 会写出 marker 文件,而 npm install --ignore-scripts 不会。这不等于所有风险都消失了,但它足够说明一件事:你真正要先收口的,不是“能不能装包”,而是“装包时脚本能拿到什么、能往外发什么”。

如果你还没补代码 Agent 的基础隔离,可以先对照这篇 代码 Agent 沙箱最小验收清单。如果你最近在补整个开发工具链的风险面,也可以顺手翻一下 TG Hubs 的 devtools 主题页

这次 TanStack 事件,真正该改的是 npm install 权限模型

截至 2026-05-14,TanStack 官方 GitHub Security Advisory 给出的关键信息已经很明确:2026-05-11 的 6 分钟窗口里,42 个 @tanstack/* 包被发布了 84 个恶意版本;安装命中这些版本时,payload 会在安装阶段执行,目标包括 AWS/GCP/Kubernetes/Vault 凭据、~/.npmrc、GitHub token、gh 配置、.git-credentials~/.ssh/ 私钥。

OpenAI 同一天的官方 RSS 条目《Our response to the TanStack npm supply chain attack》在这里值得引用,不是因为本文要展开 OpenAI 自身的客户端处置,而是因为它证明了:这类安装阶段的供应链事件会一路波及到上层产品、签名证书和更新节奏。OpenAI 甚至明确要求 macOS 用户在 2026-06-12 前完成应用更新。

所以这题对 AI builder、Agent workflow 团队的意义不是“以后少装 TanStack”,而是:

  • 任何会自动跑 npm install 的 Agent,都不该继续默认摸到长期凭据
  • 任何把安装脚本当成普通构建步骤的 CI,都要补一次边界检查
  • 任何“先让 Agent 试试,出问题再说”的开发流程,都该把依赖安装单独拉出来做验收

这和前阵子讲的镜像投毒问题是同一类运营面:供应链动作不该再和高价值凭据共居一台默认开放的执行器。 如果你更偏容器侧排查,可以再看那篇 KICS 镜像被投毒后团队该先查什么

适合谁 / 不适合谁

适合谁:

  • 让代码 Agent 自动装 npm 依赖、跑脚手架、修 PR 的团队
  • npm install 放进 CI、预览环境、代码生成流水线的团队
  • 维护内部 npm 镜像、私有包或共享 runner 的平台团队

不适合谁:

  • 只想知道 TanStack 具体受影响版本号、并且已经完成逐包排查的纯前端项目
  • 完全不让 Agent/CI 触发 npm 安装、也不在开发机保留高价值凭据的离线环境

npm install 权限怎么收口:先做这 4 步

第 1 步:把“审包”从“执行安装”里拆出来

TanStack 官方 advisory 已经给了一个非常实用的方向:先拉 tarball,再看包内容。 这一步的关键不是检测一切恶意代码,而是先把“会执行脚本的安装动作”降成“不会执行脚本的静态检查动作”。

最小做法可以从这两条命令开始:

npm pack <package>@<version>
tar -xzf <package-version>.tgz

我这轮本地复现里,npm pack 对带 postinstall 的测试包没有触发脚本;这正是它适合作为预检查入口的原因。你至少可以先看:

  • package/package.json 里有没有额外的 optionalDependencies
  • 包根目录有没有异常的大体积脚本文件
  • 版本号是不是命中了公告里的受影响窗口

验收通过状态: 你能在不执行安装脚本的前提下拿到 tarball,并完成一次静态检查。
常见失败点: 团队把 npm install 当成“顺便看一下依赖内容”的唯一入口,结果把检查动作和执行动作绑死了。

第 2 步:把 Agent 默认安装命令改成 --ignore-scripts

如果你的代码 Agent 只是为了补类型、拉 SDK、生成 lockfile、更新 demo 依赖,默认没必要给它脚本执行权。

我本地做的最小复现实验是这样的:

POSTINSTALL_MARKER=/tmp/default-marker npm install ./postinstall-proof-fixture-1.0.0.tgz
POSTINSTALL_MARKER=/tmp/ignore-marker npm install ./postinstall-proof-fixture-1.0.0.tgz --ignore-scripts

结果很直接:普通安装写出了 marker;--ignore-scripts 那次没有写出 marker。也就是说,同一个包,是否给安装脚本执行机会,默认值就能决定一大截风险暴露面。

更适合今天先落地的做法是:

  1. Agent 路径默认使用 npm install --ignore-scripts
  2. 必须执行脚本的包走白名单
  3. 白名单包的安装动作单独放进隔离 runner,不和通用补丁任务共用执行器

验收通过状态: Agent 的默认安装路径不再执行 lifecycle scripts。
常见失败点: 误以为 lockfile 足够安全;其实 lockfile 约束版本,不等于自动阻止安装脚本运行。

第 3 步:把长期凭据从安装进程旁边搬走

TanStack 官方 advisory 列出来的目标很说明问题:攻击者盯的不是“项目能不能编译”,而是安装进程边上的高价值材料。

如果你今天只能做一轮最小整改,优先收这几样:

  • ~/.npmrc 里的长期 token 换成短期或按 job 注入
  • 不要让装包 runner 默认挂着云厂商长期 AK/SK
  • 不要让执行安装的机器同时持有可推私仓的 SSH key
  • gh.git-credentials、部署密钥和依赖安装解耦

这一步和 代码 Agent 批量提 PR 时 reviewer 该信什么证据链 是连着的:你不只是要让 Agent 能干活,还要让后续 reviewer 能看见它到底接触了哪些外部输入、拿到了哪些权限。

验收通过状态: 就算安装脚本被执行,它也读不到长期凭据和生产级推送能力。
常见失败点: 只关心 repo 只读、网络默认关闭,却忘了依赖安装往往发生在另一个更宽松的执行路径里。

第 4 步:把 incident 后的排查顺序固定下来

如果你的团队在 2026-05-11 当天确实跑过相关安装,不要只做“升级到 patched version”这一件事。更稳的顺序是:

  1. 先识别是否命中过受影响包和时间窗口
  2. 立即轮换安装进程可见的 token、SSH key、云凭据
  3. 回看 CI / 开发机 / 预览环境的出站访问和云审计日志
  4. 再决定哪些依赖安装路径要永久改成 npm pack 预检 + --ignore-scripts 默认

验收通过状态: 你的 incident runbook 里已经把“版本升级”和“凭据轮换 / 出站回看”拆成两步。
常见失败点: 团队只修版本,不回看凭据是否已经暴露。

哪些团队今天就该收,哪些可以后补

今天就该收的:

  • 让 Agent 自动跑 npm install 修 bug、补 demo、生成脚手架的团队
  • 共用 CI runner、但还没把依赖安装和部署权限拆开的团队
  • 开发机上同时放了 npm token、云凭据和 SSH key 的小团队

可以后补、但别拖太久的:

  • 只在本地人工安装依赖、且开发机没有高价值凭据的个人项目
  • 纯只读评审 Agent,不执行 npm 安装和脚手架命令的流程

FAQ

1. TanStack 这次事件里,单纯 npm install 就会中招吗?

按 TanStack 官方 GitHub Security Advisory 的描述,只要安装命中了受影响版本,payload 就会在安装阶段执行,所以这次问题的关键不在“运行你的业务代码”,而在“你有没有给安装阶段脚本执行机会”。

2. package-lock.json 能不能解决这类风险?

不能单独解决。lockfile 主要解决版本可重复,不自动阻止 lifecycle scripts,也不自动隔离安装进程旁边的 token、SSH key 和云凭据。

3. npm install --ignore-scripts 会不会把很多包装坏?

会有兼容性成本,所以更现实的做法不是全公司一刀切,而是:Agent 默认 --ignore-scripts,再为确实依赖安装脚本的包做白名单和隔离执行。

4. npm pack 能不能替代真正安装?

不能。npm pack 更像预检查入口:它适合先看 tarball、manifest 和可疑文件,但不等于已经验证运行时、编译链或真实依赖树都安全。

5. 如果我们已经做了 repo 只读和默认无网,还需要再管 npm install 权限吗?

需要。repo 只读和默认无网解决的是一部分执行边界;npm install 权限解决的是安装脚本能否执行、执行时能读到什么凭据。这两层不是互相替代,而是前后相接的最小控制面。

结论

TanStack 这次事件最值得团队立刻改的,不是再记一次受影响版本号,而是把 npm install 权限当成生产动作来管。对代码 Agent、CI 和共享开发环境来说,今天最实用的最小闭环就是:npm pack 审包,默认 npm install --ignore-scripts,把真正需要脚本执行的安装放进隔离 runner,再把长期凭据从安装进程旁边搬走。

如果你的代码 Agent 还在默认路径里直接跑 npm install,那现在最该补的一次排查,不是“它能不能装成功”,而是“它装成功时到底拿到了什么权限”。

Read more

Cloudflare Dynamic Workflows 上线前先过哪 5 关?我把官方 basic example 和一个失败路径都跑了一遍

Cloudflare Dynamic Workflows 上线前先过哪 5 关?我把官方 basic example 和一个失败路径都跑了一遍

先说结论:如果你只是想把一个固定的长任务搬到 Cloudflare 上,直接用 Cloudflare Workflows 就够了,不必为了 Cloudflare Dynamic Workflows 增加一层调度器。它真正适合的是“每个租户、每个 agent、每个 repo 都可能在运行时生成不同工作流代码”的场景。本文写作时(2026-05-11),我按 Cloudflare 官方 basic-example 在本地跑通了一次成功路径,又补了一次缺少 TenantWorkflow 的失败路径;结论是:先验收调度器绑定、动态 worker 入口和失败回执,再谈多租户 agent 平台上生产。 最小判断 * 你只有一套固定流程:先别上 Cloudflare Dynamic Workflows。 * 你需要让租户或 agent 在运行时提交不同工作流代码:可以继续看这篇。 * 你还没想清楚

By One AI
代码 Agent 沙箱怎么做最小验收?我用 4 条命令先验 repo 只读、scratch 可写、默认无网

代码 Agent 沙箱怎么做最小验收?我用 4 条命令先验 repo 只读、scratch 可写、默认无网

我在 Docker 28.5.2 上直接跑了 4 条命令,先验 代码 Agent 沙箱 最容易被讲空的 3 条底线:repo 只读、scratch 可写、默认无网。短答案是:这轮最小验收值得所有准备让代码 Agent 读仓库、跑测试、改文件的团队先做一遍;但如果你只是起了个容器,还没有把审批和日志留在控制面,那还不能算拿到了可上线的代码 Agent 沙箱。 OpenAI 刚在 Running Codex safely at OpenAI 里把这个边界讲得很直白:Codex 新闻稿说的是产品内部部署,文档里更通用的名字则是 Sandbox Agents 和 Guardrails and human review;前者是执行环境,

By One AI
GitHub Copilot CLI 企业托管插件怎么落地:我先按官方 marketplace 跑了一次,再说哪些能统一、哪些还统一不了

GitHub Copilot CLI 企业托管插件怎么落地:我先按官方 marketplace 跑了一次,再说哪些能统一、哪些还统一不了

GitHub Copilot CLI 企业托管插件怎么落地:我先按官方 marketplace 跑了一次,再说哪些能统一、哪些还统一不了 如果你们团队已经把 GitHub Copilot CLI 当成开发工具链的一部分,现在最值得先看的,不是“又多了一个 Copilot 预览功能”,而是 GitHub 终于给 Copilot CLI 补上了企业统一下发插件的入口。短答案是:值得平台团队现在就做一轮小范围试点,但别把它误解成“Copilot CLI 已经有了完整企业治理面”。它现在更像一个能统一 marketplace 和 auto-install 插件的分发层,不等于 MCP、IDE 插件策略、模型权限这些边界也一起被接管了。 这里先把名字说准。GitHub 这次公开预览的官方名称是 enterprise-managed plugins for GitHub Copilot CLI。

By One AI
GitHub Copilot 的 GPT-5.2 / GPT-5.2-Codex 6 月要退役:手动锁模型的团队现在就该补一次排查

GitHub Copilot 的 GPT-5.2 / GPT-5.2-Codex 6 月要退役:手动锁模型的团队现在就该补一次排查

GitHub Copilot 的 GPT-5.2 / GPT-5.2-Codex 6 月要退役:手动锁模型的团队现在就该补一次排查 截至 2026-05-02,GitHub 已在官方 changelog 里写明:从 2026-06-01 开始,GPT-5.2 和 GPT-5.2-Codex 会从大多数 GitHub Copilot 体验里退役,例外只剩 Copilot Code Review 里的 GPT-5.2-Codex。短答案也很直接:如果你们平时手动选模型、给团队设过 model policies,或者把某些 Copilot 流程默认绑在旧模型上,这不是“到点自动变好”的提醒,而是现在就该补的一轮排查。 反过来,如果团队大部分人一直用 Auto

By One AI
Follow @Fuuqius