Deno 2.6 在去年12月推出了一项针对 npm 供应链攻击的功能:你可以让 deno install 和 deno add 拒绝安装发布太近的依赖。逻辑是,恶意包版本通常会在几小时或几天内被下架或举报,所以只要坚持只装"活过等待期"的依赖,就能躲开这一类攻击。
有人装了当前稳定版 Deno 2.9.6,花了一个下午拿真实 npm 包做测试。结论是:它大部分时候能工作,但存在一个静默失败模式——如果按 CLI 自身语法看起来允许的方式去配置,保护会被完全抵消。
![]()
这个 flag 是什么
相关 flag 是 --min-dep-age,它接受分钟数、ISO-8601 时长或绝对日期。CLI 帮助文本给出的说明是:--min-dep-age (Unstable),值为分钟数、ISO-8601 时长或 RFC3339 绝对时间戳,例如 '120' 表示两小时,'P2D' 表示两天,'2025-09-16' 表示截止日期,'2025-09-16T12:00:00+00:00' 表示截止时间,'0' 表示禁用。
20个包跑一遍,12个被降级
测试选了 20 个几乎每个 JavaScript 项目都会用到的包——react、vite、typescript、express、eslint、webpack 等等——在同一个项目、同样的无 lockfile 起点、同一条命令下跑了两遍:一遍不加限制,一遍加上 --min-dep-age=P30D(30天)。只有 flag 不同。
结果是 20 个包里有 12 个在 30 天策略下解析到了更老的版本。剩下 8 个——chalk、commander、dayjs、esbuild、express、lodash、prettier、typescript——没有变化,因为它们的最新版本本来就发布超过 30 天了。
其中最突出的是 vitest。它真正的最新版本 5.0.1 在测试时发布才 1.8 天。能通过 30 天门槛的最新版本是 4.1.10——整整落后一个大版本。在一个全新项目上执行 deno add npm:vitest --min-dep-age=P30D,会把你钉在去年的主版本上,没有任何错误、警告或提示。
月份和年份参数,直接失效
问题出在别的地方。CLI 帮助文本里只给了基于天的示例(P2D),但 ISO-8601 时长本身也支持月和年,而参数说明里并没有说这些单位不被支持。
用 --min-dep-age=P7D(7天)装 zod,得到的是 4.6.1,运行前 7.3 天发布。换成 --min-dep-age=P30D(30天),得到 4.4.3,运行前 135.9 天发布。这两个都符合预期。
但换成 --min-dep-age=P1M(1个月),得到的是 4.6.5——运行前 3.2 天发布。也就是说,用"月"作单位时,年龄过滤完全没有生效。CLI 的语法看起来允许这么写,实际却是一个静默失效模式,一旦按这种写法配置,保护就彻底归零。
不知道策略在跑,会以为是自己写错了
这种静默降级最麻烦的地方在于它不告诉你发生了什么。在一个全新项目上执行带 30 天限制的安装命令,你会被钉在去年的主版本上,而系统不会给出任何错误、警告或"存在更新主版本"的提示。如果你不知道策略正在生效,大概率会去提一个困惑的 bug 报告,说 vitest 5"装不上"。
换句话说,这个功能的设计目标——挡住刚发布的恶意版本——在按天配置时是成立的,但配置语法本身留了一个口子:写月、写年,过滤器就当没看见。对于冲着供应链安全来用这个功能的人来说,这个口子比没有功能更危险,因为它会让人误以为防护已经打开。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.