装依赖要查供应链信任,删依赖却直接放行——pnpm 这次把 remove 和 update 也一起收编了
你给 pnpm install 配了 minimumReleaseAge 和 trustPolicy: no-downgrade,以为供应链就守住了。但只要有人跑一次 pnpm remove 或 pnpm update,锁文件会被整个重写,而那些曾经被校验过的条目,可能就在这一次重写里悄悄换了身份——以前的版本根本不查。pnpm 11.26 把这道口子补上了:remove 和 update 现在接受同一套供应链策略开关,而且 remove 默认会拿整份锁文件重新跑一遍校验,除非你显式加上 –trust-lockfile。
先说清楚「信任校验」到底在校验什么。pnpm 从 10.x 起有三条默认防线:minimumReleaseAge 让新发布的版本先「冷静」一段时间(内置默认 1440 分钟,也就是 1 天)才允许解析;trustPolicy: no-downgrade 会在某个包的可信证据相对上一版下降时报错——比如之前版本来自带 provenance 的可信发布者,新版本却只剩普通 token 发布,这通常就是账号被盗的信号;blockExoticSubdeps 则拦住传递依赖直接从 GitHub 仓库或原始 tarball URL 拉代码。这三条都是基于「发布证据」而不是 semver,所以光看版本号是发现不了的。
真正的问题出在锁文件被改写的时机。pnpm 11.1.3 起,install 在真正下载任何 tarball 之前,会重新拿整份 pnpm-lock.yaml 对一遍 minimumReleaseAge 和 trustPolicy——因为一份在别处(别人机器、CI 缓存、旧版 pnpm、或更弱策略下)生成的锁文件,本来是可以静默装进一个「新鲜出炉」或「信任降级」的版本的。但 remove 和 update 是另一个入口:它们会就地重写锁文件,旧版本没有把同一套校验接上去。也就是说,你精心配的信任策略,可能被一次普通的删包或升级操作绕过。
pnpm 11.26 的改法很直接:pnpm remove 和 pnpm update 现在支持 –trust-lockfile、–no-trust-lockfile、–trust-policy、–trust-policy-exclude、–trust-policy-ignore-after 这一整组参数。关键在于 remove 的默认行为变了——它会拿整个锁文件对着当前生效的策略重新校验一遍,除非你主动用 –trust-lockfile 告诉它「这份锁文件已经可信,跳过校验」。原因也写得很清楚:删一个包就会重写锁文件,重写完的这份东西,值得重新检查一次。
同一批更新里还有一个更适合塞进 CI 的命令:pnpm change check。它不需要读任何变更意图,只拿工作区里已经提交的版本,去对 versioning.epics 里的版本区间和 versioning.fixed 分组校验一遍,一次把所有越界的版本全列出来。放在每个 pull request 上跑,版本在引入它的那个 PR 里就被抓住了,而不是拖到发版才炸。
为什么这件事值得你今天就动手,看两组数字就够。2025 年 Sonatype 统计到超过 454,600 个新的恶意开源包,其中 99% 以上在 npm 上;到 2026 年 3 月,连周下载量 1 亿的 axios 都被劫持过,攻击路径正是被盗的发布凭证和生命周期脚本。好消息是,绝大多数恶意包在几小时内就会被发现并下架,所以「让新版本先冷静一天」这类基于时间的策略覆盖率其实很高——前提是,你的每一条改动路径都真的在跑校验,而不是留一个 remove/update 的后门。
顺带说一句别踩的坑:pnpm 11.3 引入的 trustLockfile: true(在 pnpm-workspace.yaml 里设)是用来跳过 install 阶段的锁文件校验的,本意是给「每次提交都来自可信作者的闭源项目」省内存和耗时——大型工作区跑校验确实可能吃掉 CI runner 的堆内存。但如果仓库允许外部 contributor 改锁文件,或者你要防的正是从 PR 进来的依赖变更,这个开关一定要保持默认的 false。别用「跳过安全检查」去掩盖一个本该定位的性能问题。
落地就三步。第一,升级到 pnpm 11.26(或等价的 pnpm 12 行为),把 –trust-lockfile 当成「显式放弃校验」的信号,而不是顺手加上的默认项。第二,在 CI 里把 pnpm change check 接进 pull request 流程,让版本漂移在引入处就暴露;本地先用 pnpm config get minimumReleaseAge / trustPolicy 确认策略来源,再跑 pnpm install –frozen-lockfile 并用 git diff –exit-code 检查锁文件有没有被偷偷改动。第三,审计一下你们的流水线里有没有 pnpm remove / pnpm update 这类会重写锁文件的步骤——如果有,确认它们不是在绕过你已经配好的信任策略。供应链安全从来不是「配了一次就永久生效」,而是每一条能改依赖的路径,都得在同一个标准下被检查一遍。
评论区
登录后可评论。