Ruby Bundler 的冷却支持

Hacker News Top 工具

摘要

Bundler 4.0.13 引入了一项冷却功能,阻止解析发布不足 N 天的 gem,以缓解供应链攻击。该功能为可选加入,并可根据不同源、设置或命令行标志进行配置。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/06/05 14:08

# 安装前先冷静一下:给新 gem 几天时间接受审查 来源:https://blog.rubygems.org/2026/06/03/cooldown-let-new-gems-be-vetted.html 大多数针对 RubyGems 的供应链攻击都利用一个短暂窗口:账户被劫持,恶意版本发布,随后几分钟内的任何 `bundle install` 都会直接解析到该版本。**Bundler 4.0.13** 引入了**冷却期(cooldown)**,这是一种基于时间的过滤器,拒绝解析到已公开时间少于 *N* 天的版本。那些太新、尚未经过审查的版本将被跳过,转而选择已超过该窗口期的版本。 该功能是[公开设计的](https://github.com/ruby/rubygems/discussions/9113),借鉴了[其他生态系统处理同一问题的方式](https://dev.to/hsbt/should-rubygemsbundler-have-a-cooldown-feature-40cp)。它是可选的,与强制 2FA 和可信发布等现有防御措施互补而非替代。 冷却期会读取 rubygems.org 的 v2 紧凑索引现在提供的每个版本的 `created_at` 时间戳。如果某个版本来源不暴露 `created_at`(例如较旧的 gem 服务器、v2 切换前的历史条目,或仍在使用 v1 格式的私有仓库),则该版本被视为在窗口之外,仍然可解析。冷却期不会静默阻止解析;它只会阻止那些被证明太新的版本。 ### 入门 冷却期随 [Bundler 4.0.13](https://blog.rubygems.org/2026/06/03/4.0.13-released.html) 一起发布。如果你在更早的版本上,请就地更新 Bundler 并在你的 lockfile 中固定相同版本,以便整个团队同步: ``` $ gem update --system # 或:gem install bundler -v 4.0.13 $ bundle update --bundler=4.0.13 ``` 然后在 `Gemfile` 中为你的源声明一个小的冷却期。这对大多数团队来说是正确的设置:它与你的代码一起提交,因此每个开发者和 CI 运行都会强制执行相同的窗口,无需额外配置。 ``` source "https://rubygems.org", cooldown: 7 gem "rails" gem "puma" ``` 冷却期在解析期间生效。当没有 lockfile 时运行 `bundle install`,或者当 lockfile 存在时运行 `bundle update` 以重新解析;现有的 `Gemfile.lock` 始终按原样保留,因此添加冷却期永远不会干扰你已锁定的版本。冷却期默认未设置,因此没有它的项目将继续解析到最新版本。 这就是大多数项目所需要的。本文的其余部分涵盖了更细粒度的控制。 ### 其他设置方式 除了每个源的关键字外,`cooldown` 设置可以将一个值应用到每个源,范围可以是项目级、全局级或通过环境变量: ``` $ bundle config set cooldown 7 # 存储在此项目的 .bundle/config 中 $ bundle config set --global cooldown 7 # 应用于此用户的每个项目 $ BUNDLE_COOLDOWN=7 bundle install # 还没有 lockfile,例如新的 CI 检出 $ BUNDLE_COOLDOWN=7 bundle update # lockfile 已存在时重新解析 ``` 对于一次性运行,将 `--cooldown` 传递给 `install`、`update`、`add` 或 `outdated`: ``` $ bundle install --cooldown 7 $ bundle update --cooldown 7 $ bundle add rails --cooldown 7 $ bundle outdated --cooldown 7 ``` 当存在多个设置时,它们按固定优先级顺序解析:**命令行标志 > 配置设置 > `Gemfile` 中每个源的 `cooldown:`**。`--cooldown` 标志会覆盖 `cooldown` 设置(`bundle config` 或 `BUNDLE_COOLDOWN`),而后者又会覆盖在源上声明的 `cooldown:`。冷却期值始终是一个**非负整数天数**;字符串、浮点数、负数或数组将被拒绝并抛出 `InvalidOption` 错误。 ### 混合源 因为标志和设置**统一应用于每个源**,所以当不同仓库的策略不同时,你需要使用每个源的关键字,例如冷却公共 gem 同时信任你运营的内部仓库: ``` source "https://rubygems.org", cooldown: 7 source "https://gems.internal.example.com", cooldown: 0 do gem "internal-tool" end ``` 私有源上的 `cooldown: 0` 使其永久豁免,而公共 gem 仍会老化。请注意,命令行 `--cooldown N` 会覆盖该次运行中的每个源,包括豁免的那个。 ### 应急出口 传递 `0` 将禁用该次运行的冷却期。这是按需获取最新版本的可靠方法,也是覆盖每个源或已配置冷却期的方法。这在等待成为错误默认值的情况下尤为重要:针对正在被积极利用的零日漏洞发布了修复,或者安全漏洞披露要求你立即升级。在这种情况下,最新版本正是你想要的,而 `--cooldown 0` 让你可以获取它,而不必为其他人移除策略: ``` $ bundle install --cooldown 0 $ BUNDLE_COOLDOWN=0 bundle update rails # 这次忽略任何已配置的冷却期 ``` 当你想要解析的 gem 的每个候选版本仍在窗口内时,你会用到这个。Bundler 不会回退到太新的版本,而是停止解析,报告冷却期排除了多少个版本,并提示你使用 `--cooldown 0` 继续。 ### 查看哪些被阻止 `bundle outdated` 是支持冷却期的。它会注释那些更新但仍在窗口内的版本,并显示它们变得可解析之前剩余的天数,因此“已是最新”与“正在有意等待”是有区别的: ``` $ bundle outdated --cooldown 7 Gem Current Latest Requested Groups aws-partitions 1.1251.0 1.1256.0 (cooldown 3d) = 1.1251.0 default ``` ### 众多防线中的一层 冷却期是 rubygems.org 上更广泛安全投入的一部分。该仓库现在在推送时验证 gem 内容,并检查登录是否与 Have I Been Pwned 匹配,以便不能重复使用泄露的密码,相关工作在[从外到内保护 rubygems.org](https://blog.rubygems.org/2026/04/09/protecting-rubygems-from-the-outside-in.html) 中进行了描述。一个专门的团队正在与 Alpha Omega 和 Anthropic 合作,针对[最关键的 gem 运行 AI 辅助漏洞扫描](https://blog.rubygems.org/2026/04/29/scaling-rubys-defenses-with-ai.html),所有这些工作的方向都在一个[公开路线图](https://blog.rubygems.org/2026/04/15/rubygems-org-has-a-public-roadmap.html)中进行了跟踪。可信发布和强制 2FA 已经提高了首先能够发布版本的门槛。 冷却期之所以有效,完全是因为 rubygems.org 现在通过其 [v2 紧凑索引](https://github.com/rubygems/rubygems.org/issues/6412)(v2 是内部格式版本,不是公共 API 变更)发布了每个版本的 `created_at` 时间戳,这通过一次谨慎的双写迁移和一次有标记的切换来完成,对客户端没有中断。我感谢 rubygems.org 团队为此打下的基础。冷却期是在此之上的一个薄客户端过滤器。 这些防御措施各自覆盖不同的缺口,并且相互叠加。将你的依赖项解析到 rubygems.org 可以将所有这些措施都用于你,这使其成为 Ruby 项目最安全的默认选择。

相似文章

引用 GitHub Changeling

Simon Willison's Blog

GitHub 的 Dependabot 现在默认在开启版本更新拉取请求之前有一个三天的冷却期,无需配置。

Ruby 4.0 通用 RCE 反序列化 Gadget 链

Hacker News Top

本文发布了一条全新的通用 Ruby 反序列化 gadget 链,可将一次 Marshal.load 转变为命令执行,适用于 Ruby 4.0.6,并可回溯至 Ruby 3.3 无需修改,由新 gadget 和改装后的 gadget 共同构建。

Ruby Central 的破坏性遗产

Hacker News Top

一篇博客文章批评了 Ruby Central 对 RubyGems 和 Bundler 的处理方式,称其“敌意收购”导致大量辞职、赞助商流失以及项目移交给 Matz。