Cached at:
07/07/26, 02:17 PM
# You shouldn't trust Trusted Publishing
Source: [https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing](https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing)
## ENOSUCHBLOG
## *Programming, philosophy, pedaling\.*
- [Home](https://blog.yossarian.net/)
- [Tags](https://blog.yossarian.net/tags)
- [Series](https://blog.yossarian.net/series)
- [Favorites](https://blog.yossarian.net/favorites)
- [Archive](https://blog.yossarian.net/archive)
- [Main Site](https://yossarian.net/)
- [TILs](https://yossarian.net/til)
---
## *Jul 7, 2026*Tags:[oss](https://blog.yossarian.net/tags#oss),[python](https://blog.yossarian.net/tags#python),[security](https://blog.yossarian.net/tags#security)
---
…because[Trusted Publishing](https://docs.pypi.org/trusted-publishers/)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 \(or for\!\) against 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](https://blog.yossarian.net/2024/11/18/Security-means-securing-people-where-they-are), but I left this observation implicit rather than laying it out explicitly\. This is an attempt to correct that mistake\.
## Quick recap[\#](https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing#quick-recap)
“Trusted Publishing” is a term of art that[PyPI](https://pypi.org/)uses to describe a form of authentication on top of OpenID Connect \([OIDC](https://openid.net/developers/how-connect-works/)\) federation\. PyPI released it in 2023[1](https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing#fn:dev), and it’s since been adopted widely by other packaging ecosystems \(including[npm](https://docs.npmjs.com/trusted-publishers),[RubyGems](https://guides.rubygems.org/trusted-publishing/),[crates\.io](https://crates.io/docs/trusted-publishing), and[NuGet](https://learn.microsoft.com/en-us/nuget/nuget-org/trusted-publishing)\)\.
The basic observation behind Trusted Publishing is twofold:
1. 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\.
2. 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[2](https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing#fn: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\.
This can be hard to visualize;[Seth Larson](https://sethmlarson.dev/)’s diagram is instructive:
*\(Source:[OpenSSF](https://repos.openssf.org/trusted-publishers-for-all-package-repositories.html)\)*
Broadly speaking, this approach to short\-lived, self\-scoping credentials has been a*huge success*: we’ve found that users[3](https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing#fn:pypi)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[4](https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing#fn:datamodel), requires bespoke treatment for each OIDC provider that an index chooses to support[5](https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing#fn: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\)[6](https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing#fn:compromised)\.
Despite these qualifications, I think Trusted Publishing has been a net win for packaging ecosystems that adopt it\. As mentioned in[the earlier post](https://blog.yossarian.net/2024/11/18/Security-means-securing-people-where-they-are), 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\.
## What of trust?[\#](https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing#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*\.
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[7](https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing#fn:can)\. 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 is*very careful*[8](https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing#fn: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\.
Using[zizmor](https://pypi.org/project/zizmor/)as an example:

Observe that the only “green checkmark” for user\-controlled state on this page is for links that PyPI can prove came from the same source as the package itself\. These links, too, are intentionally not described as “trusted”; as the[PyPI docs explain](https://docs.pypi.org/project_metadata/#verified-details):
> A URL being verified only attests that the URL is under control of the PyPI package owner at the time of verification, and does not imply any additional safety about that URL or any other relationship to the project in question\.
If you*do*want to see the Trusted Publishing status of a particular file on PyPI you’ll need to dig for it\. You’ll find it ignominiously rendered as a simple “Yes/No” deep in the[file details](https://pypi.org/project/zizmor/#zizmor-1.26.1.tar.gz):

I say “ignominiously” because you can*see*how little effort has been placed into rendering the “file metadata” section, because it’s**not important trust information**\. We don’t even bother to properly render the blob of JSON that comes from the uploading client’s user agent\!
Here, too, you can see that no normative statement of trust is applied to the Trusted Publishing status: there’s a boolean state, and**nothing whatsoever**to imply that a user can or should trust a project more or less because of that state\.
## Summary[\#](https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing#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 or “good,” and PyPI*consciously stymies*attempts to misuse it for that purpose by not rendering it as a “green checkmark” or anything else of the sort\.
Or as another framing: Trusted Publishing is**just a form of authentication**\. It doesn’t tell you*anything*other than that an upload was authenticated, which all uploads to PyPI are\.
[With apologies to Anatole France](https://www.goodreads.com/quotes/361132-the-law-in-its-majestic-equality-forbids-rich-and-poor):
> Trusted Publishing, in its majestic equality, permits seasoned maintainer and script kiddy alike to publish malware, to release slop for HN karma, and to obtain security advisories for embarassing flaws\.
## Afterword[\#](https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing#afterword)
This post is about Trusted Publishing,*not*[attestations](https://docs.pypi.org/attestations/)\. Attestations are a technically distinct topic on PyPI that \(currently\) also use OIDC machine identities, but are**simiarly not a signal of trust**\.
To analogize: an attestation is effectively a signature on top of a machine identity, but*anybody*can upload to PyPI and therefore*anybody*can sign with any machine identity they control\. The*presence*of an attestation is not guaranteed by the presence of a Trusted Publisher, and similarly does not imply any particular end\-user trust*until*you*separately*establish trust in that identity\.
This, too, is[explicitly documented](https://docs.pypi.org/attestations/security-model/#trustworthiness)\.
---
---