You shouldn't trust Trusted Publishing

You shouldn’t trust Trusted Publishing

你不该信任“可信发布”(Trusted Publishing)

…because Trusted Publishing isn’t for you (or me) to trust! It’s for the machines. Trusted Publishing is an authentication scheme that involves machine-to-machine trust. If you find yourself arguing against (or for!) Trusted Publishing on the basis that you (a human) can’t (or can) trust it then you’re making a category error, one that PyPI is careful to help you not make. I wrote about this indirectly about two years ago, but I left this observation implicit rather than laying it out explicitly. This is an attempt to correct that mistake.

……因为“可信发布”并不是让你(或我)去信任的!它是给机器用的。“可信发布”是一种涉及机器与机器之间信任的身份验证方案。如果你发现自己因为“作为人类的你无法(或能够)信任它”而反对(或支持)可信发布,那么你就犯了范畴错误,而 PyPI 一直很谨慎地避免让你犯这种错误。大约两年前我曾间接写过这一点,但我当时让这个观察结果保持了隐晦,而没有明确阐述。这篇文章旨在纠正那个疏忽。

Quick recap

快速回顾

“Trusted Publishing” is a term of art that PyPI uses to describe a form of authentication on top of OpenID Connect (OIDC) federation. PyPI released it in 2023, and it’s since been adopted widely by other packaging ecosystems (including npm, RubyGems, crates.io, and NuGet).

“可信发布”是 PyPI 使用的一个术语,用于描述一种基于 OpenID Connect (OIDC) 联合身份验证的认证形式。PyPI 于 2023 年发布了该功能,此后它已被其他包管理生态系统(包括 npm、RubyGems、crates.io 和 NuGet)广泛采用。

The basic observation behind Trusted Publishing is twofold: Long-lived credentials (like index API tokens) are difficult to secure, and are often over-scoped because users find it frustrating to determine the “right” minimal scope and expiry. Consequently, the impact of a compromised or leaked credential can be much broader than the specific system it was stolen from.

“可信发布”背后的基本观察点有两个:长期有效的凭据(如索引 API 令牌)难以保护,且往往权限过大,因为用户很难确定“正确”的最小权限范围和过期时间。因此,一旦凭据被泄露或窃取,其影响范围往往远超被窃取凭据的特定系统。

Many users provision credentials solely for the purpose of putting them in a CI/CD platform, which they then publish from. However, CI/CD platforms often also have identity mechanisms that allow a user to demonstrate control of a specific machine identity via OIDC. Trusted Publishing combines these into an authentication scheme: the user performs a one-time registration of their “Trusted Publisher” (their CI/CD machine identity) with their package index. Then, whenever the CI/CD presents an identity token, the package index verifies it and issues a corresponding, minimally scoped, short-lived publishing credential.

许多用户配置凭据仅仅是为了将其放入 CI/CD 平台,以便从中发布软件包。然而,CI/CD 平台通常也具备身份验证机制,允许用户通过 OIDC 证明其对特定机器身份的控制权。可信发布将这些结合成一种认证方案:用户在包索引中对其“可信发布者”(即其 CI/CD 机器身份)进行一次性注册。此后,每当 CI/CD 提供身份令牌时,包索引都会对其进行验证,并颁发相应的、权限最小化的、短期有效的发布凭据。

Broadly speaking, this approach to short-lived, self-scoping credentials has been a huge success: we’ve found that users prefer not to manually manage credentials when they don’t have to, and that large Open Source projects and companies alike both like the property of their publishing being tied to their source identity rather than any individual project maintainer.

总的来说,这种针对短期、自限权限凭据的方法取得了巨大成功:我们发现,用户在不必手动管理凭据时更倾向于不这样做;同时,大型开源项目和公司都喜欢这种特性——即发布权限与源代码身份绑定,而不是与任何特定的项目维护者绑定。

Of course, Trusted Publishing is not perfect: it has a complicated data model, requires bespoke treatment for each OIDC provider that an index chooses to support, and (of course) can still be compromised (since, at the end of the day, it’s still an authentication scheme and there needs to be a credential somewhere in the flow). Despite these qualifications, I think Trusted Publishing has been a net win for packaging ecosystems that adopt it. As mentioned in the earlier post, security is a matter of identifying and protecting the areas where your users congregate their trust (their “watering holes”), and Trusted Publishing accomplishes that by reducing the number of long-lived, over-scoped credentials that users are exposed to.

当然,可信发布并非完美:它拥有复杂的数据模型,需要为索引支持的每个 OIDC 提供商进行定制处理,并且(当然)仍然可能被攻破(毕竟它归根结底仍是一种认证方案,流程中总会有凭据存在)。尽管有这些局限,我认为可信发布对于采用它的包生态系统来说是净收益。正如之前文章所提到的,安全的关键在于识别并保护用户信任汇聚的区域(即“水源地”),而可信发布通过减少用户暴露在长期、权限过大的凭据下的数量,实现了这一目标。

What of trust?

那么“信任”呢?

Thus far, everything I’ve written makes Trusted Publishing sound pretty good, if not a silver bullet. So, why the emphasis on not trusting it? This is an important subtlety: Trusted Publishing is just an authentication method. The only thing Trusted Publishing does is establish a trust relationship between an external machine identity (like a CI/CD workflow) and a package identity on an index for the purpose of authenticating an upload; it does not tell a user that a package is safe to use, high quality, or anything else.

到目前为止,我所写的一切都让“可信发布”听起来相当不错,即便它不是万能药。那么,为什么要强调“不要信任它”呢?这是一个重要的微妙之处:可信发布仅仅是一种身份验证方法。它唯一的作用是在外部机器身份(如 CI/CD 工作流)与索引上的包身份之间建立信任关系,以验证上传行为;它并不会告诉用户某个包是安全的、高质量的,或者其他任何信息。

You can prove this to yourself easily: PyPI is a public index (by design), which means that anybody can upload to it, and anybody can use a Trusted Publisher to upload. Because anybody can use one, they can be used to upload anything, including malware or vulnerable code. They are exactly like API tokens (PyPI’s other upload authentication method) in this regard.

你可以很容易地验证这一点:PyPI 是一个公共索引(这是其设计使然),这意味着任何人都可以向其上传,任何人也都可以使用“可信发布者”来上传。因为任何人都可以使用它,所以它也可以被用来上传任何东西,包括恶意软件或存在漏洞的代码。在这方面,它与 API 令牌(PyPI 的另一种上传认证方式)完全一样。

PyPI is very careful to not mislead users into believing that they can or should trust a package based on its Trusted Publishing status. If you go to a project’s page on PyPI, you’ll notice that there is no “magic green checkmark” signaling a project’s Trusted Publishing status.

PyPI 非常谨慎,不会误导用户认为他们可以或应该基于“可信发布”状态来信任某个包。如果你访问 PyPI 上的项目页面,你会注意到并没有什么“神奇的绿色勾选标记”来标示项目的可信发布状态。

Summary

总结

Trusted Publishing is a mechanism for establishing trust between an external machine identity (like a CI/CD workflow) and one or more projects on a package index/registry. The “trust” in “Trusted Publishing” refers to that trust relationship, and not to anything else. It is not, and cannot be, a signal for package trust or quality. You cannot use it to determine whether a package is safe.

“可信发布”是一种在外部机器身份(如 CI/CD 工作流)与包索引/注册表中的一个或多个项目之间建立信任的机制。“可信发布”中的“信任”仅指代这种信任关系,而不指代其他任何事物。它不是,也不可能是包的信任度或质量的信号。你不能用它来判断一个包是否安全。