窥探Homebrew的构建来源 - The Trail of Bits博客
Joe Sweeney, William Woodruff
2024年5月14日
密码学, 研究实践
去年11月,我们宣布与Alpha-Omega和OpenSSF合作,为Homebrew添加构建来源功能。今天,我们很高兴地宣布,这项工作的核心部分已经上线并进入公开测试阶段:homebrew-core现在对所有在官方Homebrew CI中构建的二进制包(bottles)进行密码学认证。您可以使用我们(目前是外部但即将上游化)的brew verify
命令来验证这些认证,该命令可以从我们的tap安装:
这意味着,从现在开始,每个由Homebrew构建的二进制包都将附带一个密码学可验证的声明,将该包的内容绑定到产生它的特定工作流和其他构建时元数据。这些元数据包括(但不限于)产生该包的工作流的git提交和GitHub Actions运行ID,使其成为符合SLSA Build L2的认证:
实际上,这为Homebrew构建过程注入了更大的透明度,并通过使普通用户无法被欺骗安装非CI构建的包,减少了由受损或恶意内部人员构成的威胁。
这项工作仍处于早期测试阶段,涉及Homebrew和GitHub内部仍在积极开发的功能和组件。因此,我们不建议普通用户开始验证来源认证。
然而,对于冒险者来说,请继续阅读!
快速回顾Homebrew
Homebrew是macOS和Linux的开源包管理器。Homebrew的瑰宝是homebrew-core,一个默认仓库,包含超过7,000个精选的开源包,默认随Homebrew一起提供。homebrew-core的包每年被下载数亿次,并构成了使用macOS进行开发的程序员的基础工具套件(node、openssl、python、go等)。
Homebrew的核心功能之一是使用二进制包(bottles):每个包的预编译二进制分发,加速brew install
并确保其在个别机器之间的一致性。当一个新的公式(描述如何构建包的可机读描述)被更新或添加到homebrew-core时,Homebrew的CI(通过BrewTestBot编排)自动触发一个过程来创建这些二进制包。
成功构建和测试二进制包后,就是分发的时候了。BrewTestBot获取编译好的二进制包并将其上传到GitHub Packages,Homebrew选择的homebrew-core托管服务。这一步确保用户可以通过Homebrew的命令行界面直接访问和下载最新的软件版本。最后,BrewTestBot更新对更改公式的引用以包括最新的二进制包构建,确保用户在下一次brew update
时收到更新的二进制包。
总之:Homebrew的二进制包自动化通过将人类从软件构建过程中移除,提高了homebrew-core的可靠性。这样做,它也消除了一种特定类型的供应链风险:通过将二进制包构建从个别Homebrew维护者转移到Homebrew CI,它降低了维护者受损的开发机器被用来对更大的Homebrew用户群发动攻击的可能性¹。
与此同时,该方案还有其他方面可能被攻击者利用:拥有足够权限的攻击者可能直接将恶意构建上传到homebrew-core的二进制包存储,可能利用警报疲劳欺骗用户安装,尽管校验和不匹配。更令人担忧的是,受损或恶意的Homebrew维护者可能秘密替换二进制包及其校验和,导致所有用户从此 silently compromised installs。
这种情况是软件供应链中的一个独特但严重的弱点,构建来源很好地解决了这个问题。
构建来源
简而言之,构建来源提供了密码学可验证的证据,证明一个软件包实际上是由预期的“构建身份”构建的,而不是被特权攻击者篡改或秘密插入的。实际上,构建来源提供了强密码学摘要的完整性属性,结合了一个断言,即该工件是由一个公开可审计的构建基础设施产生的。
在Homebrew的情况下,那个“构建身份”是一个GitHub Actions工作流,意味着每个二进制包构建的来源证明有价值的元数据,如GitHub所有者和仓库、触发工作流的分支、触发工作流的事件,甚至工作流运行的精确git提交。
这些数据(以及更多!)被封装在一个机器可读的in-toto声明中,给下游消费者提供了对个别认证表达复杂策略的能力:
构建来源和更一般的来源不是万能药:它们不能替代应用程序级别的保护,防止软件降级或混淆攻击,也不能防止“与撒旦的私人对话”场景,即软件本身是恶意或受损的。
尽管如此,来源是可审计供应链的有价值构建块:它通过将攻击者承诺到公开可验证时间线上的公共工件,迫使攻击者公开,并减少了攻击者可以隐藏其有效载荷的不透明格式转换的数量。这在像最近的xz-utils后门这样的案例中尤其突出,攻击者利用上游源仓库和后门tarball分发之间的脱节来维持其攻击的隐蔽性。或者换句话说:构建来源不会阻止完全恶意的维护者,但会迫使他们的攻击公开以供审查和事件响应。
我们的实现
我们对Homebrew的构建来源实现建立在GitHub的新工件认证功能上。我们被给予了早期(私人测试)访问该功能,包括generate-build-provenance操作和gh认证CLI,这使我们能够快速迭代一个可以轻松集成到Homebrew预先存在的CI中的设计。
这为我们提供了所有当前和未来二进制包构建的构建来源,但我们留下了一个问题:Homebrew有一个很长的“尾巴”的预先存在的二进制包,这些包仍然在公式中被引用,包括构建在GitHub Actions²不再支持的(架构,OS版本)元组上的二进制包。这个尾巴被广泛使用,给我们留下了一个困境:
尝试重建所有旧的二进制包。这在技术上和后勤上都是不可行的,既因为GitHub Actions自身支持的运行器的变化,也因为macOS版本之间的重大工具链变化。
仅在存在时验证二进制包的构建来源。这将在构建来源的预期安全合同中 effectively punch a hole,允许攻击者通过剥离任何来源元数据来降级到较低程度的完整性。
这些解决方案都不可行,所以我们寻求第三个。而不是重建世界或选择性验证,我们决定创建一组回填的构建认证,由一个完全不同的仓库(我们的tap)和工作流签名。有了每个二进制包背后的回填认证,验证看起来像一个瀑布:
我们首先检查与“上游”仓库绑定的构建来源,具有预期的工作流,即Homebrew/homebrew-core与publish-commit-bottles.yml。
如果“上游”来源不存在,我们在指定的截止日期前检查来自回填身份的回填认证,即trailofbits/homebrew-brew-verify与backfill_signatures.yml。
如果两者都不存在,那么我们产生一个硬失败。
这给了我们两全其美:回填允许我们在没有来源或认证时统一失败(消除降级),而不必重建每一个旧的homebrew-core二进制包。截止日期然后增加了一层额外的保证,防止攻击者试图使用回填认证注入一个意外的二进制包。
我们期望回填二进制包认证的尾巴随着时间的推移而减少,随着公式转向新版本。一旦所有可到达的二进制包完全转向,Homebrew将能够完全移除回填检查并断言完美的来源覆盖!
今天验证来源
如上所述:这个功能处于早期测试阶段。我们仍在解决已知的性能和UX问题;因此,我们不建议普通用户尝试它。
尽管如此,冒险的早期采用者可以用两个不同的界面尝试它:
一个专用的brew verify
命令,可通过我们的第三方tap获得
一个早期的上游集成到brew install
本身。
对于brew verify
,只需安装我们的第三方tap。一旦安装,brew verify
子命令将变得可用:
|
|
展望未来,我们将与Homebrew合作,将brew verify
直接上游化到brew作为一个开发者命令。
对于brew install
本身,在您的环境中设置HOMEBREW_VERIFY_ATTESTATIONS=1
:
|
|
无论您选择如何试验这个新功能,某些注意事项适用:
brew verify
和brew install
都在内部包装了gh CLI,并且如果尚未安装,将在本地引导gh。我们打算在中期用纯Ruby验证器替换我们对gh认证的使用。
构建来源测试版依赖于认证的GitHub API端点,意味着gh必须有权访问合适的访问凭证。如果您在使用brew verify
或brew install
时遇到初始失败,尝试运行gh auth login
或设置HOMEBREW_GITHUB_API_TOKEN
为一个具有最小权限的个人访问令牌。
如果您在试验brew install
时遇到错误或意外行为,请报告它!同样,对于brew verify
:请直接将任何报告发送给我们。
展望未来
以上所有内容都涉及homebrew-core,Homebrew公式的官方仓库。但Homebrew也支持第三方仓库(“taps”),它们提供了少数但显著的总体二进制包安装。这些仓库也值得构建来源,我们有实现这一点的想法!
更远地,我们计划尝试源来源:Homebrew的公式已经哈希固定它们的源工件,但我们可以更进一步,额外断言源工件是由隐藏在它们的URL中或 otherwise embedded into the formula specification的仓库(或其他签名身份)产生的。这将与GitHub的工件认证很好地组合,启用一个假设的DSL:
请继续关注这个领域的进一步更新,并且一如既往,不要犹豫联系我们!我们有兴趣合作改进其他开源打包生态系统,并很乐意听到您的消息。
最后但并非最不重要的是,我们要感谢Homebrew的维护者在此过程中的开发和审查。我们还要感谢Dustin Ingram对原始提案的作者身份和设计,GitHub包安全团队,以及Michael Winser和Alpha-Omega的其余部分,感谢他们对更好、更安全的软件供应链的愿景和支持。
¹在不太遥远的过去,Homebrew的二进制包是由维护者在自己的开发机器上产生并上传到一个共享的Bintray账户。Mike McQuaid的2023年演讲提供了Homebrew过渡到CI/CD构建历史的优秀概述。
²或者容易用自托管运行器提供,Homebrew用于一些构建。
如果您喜欢这篇文章,分享它:
Twitter LinkedIn GitHub Mastodon Hacker News
页面内容
快速Homebrew回顾
构建来源
我们的实现
今天验证来源
展望未来
最近帖子
构建安全消息传递很难:对Bitchat安全辩论的 nuanced take
用Deptective调查您的依赖项
系好安全带,Buttercup,AIxCC的评分回合正在进行中!
使您的智能合约成熟 beyond private key risk
Go解析器中意想不到的安全 footguns
© 2025 Trail of Bits。
用Hugo和Mainroad主题生成。