发生了什么?
2026 年 7 月 7 日,知名安全研究员 William Woodruff(网名 yossarian)发表了一篇题为 You shouldn’t trust Trusted Publishing 的博文,对 PyPI 近年来力推的「可信发布」(Trusted Publishing)机制提出了审慎的安全反思。这篇文章迅速登上了 Lobsters 首页(32 points,20 comments),并在 LWN 等社区引发了热烈讨论。
Woodruff 的核心论点直接而犀利:「可信发布」中的「信任」指的是机器对机器的信任——它是机器身份(如 CI/CD 工作流)与包索引之间建立的认证关系,而非人类用户可以用来判断包质量或安全的信任信号。 试图用 Trusted Publishing 来判断一个包是否「安全」或「靠谱」,从根本上说是一种范畴错误。

什么是 Trusted Publishing?——一个快速回顾
要理解这场争论,先要搞清楚 Trusted Publishing 到底做了什么。
在传统模式下,将 Python 包发布到 PyPI 需要手动创建 API Token,将其配置到 CI/CD 流水线中。这些 Token 是长期有效的——一旦泄露,攻击者可以一直使用它们直到有人发现并手动撤销。近年来的供应链攻击事件中,API Token 盗窃正是罪魁祸首之一。
Trusted Publishing 用 OpenID Connect(OIDC)标准替代了这套方案。工作流程大致如下:
- 注册阶段(一次性):项目维护者在 PyPI 上配置一个「信任关系」,指定哪个 GitHub 仓库、哪个工作流文件有权发布该包。
- 运行时:GitHub Actions 工作流向 GitHub 的 OIDC 提供商请求一个短效的 JWT(JSON Web Token),包含仓库名、工作流名、环境名等身份声明。
- 交换:CI 流水线将此 JWT 提交给 PyPI,PyPI 验证 Token 签名和声明后,返回一个短效 API Key。
- 发布:使用该短效 Key 完成包上传。
这个过程的核心优势是:不再需要手动管理长期密钥。JWT 在几分钟后过期,PyPI 返回的 API Key 也仅在工作流运行期间有效。从密钥管理的角度看,这大大缩小了攻击面。
信任的边界:Woodruff 到底在质疑什么?
Woodruff 并非否定 Trusted Publishing 的技术价值。他的关切更偏向于语义和安全认知层面——而这两个层面往往被人们混淆。
问题一:「可信」这个命名
社区中有不少人认为这个机制的名称本身就埋下了误解的种子。LWN 的读者 walters 直接建议:「改名叫 OIDC-linked publishing 不好吗?」另一位读者 rgmoore 更不客气:
如果这真的是一个认证机制而非信任机制,他们就不该在名字里放「trusted」这个词。这是他们自己的锅。
即便是 PyPI 开发者 LawnGnome 也承认这个名字「使得向人们解释它实际做什么变得更加困难了」。Woodruff 自己也在 Lobsters 的回复中指出:
Trusted Publishing 只是一个认证方案。它告诉你的唯一信息是「这次上传经过了认证」——而 PyPI 上的每一次上传都是认证过的。
问题二:信任关系的单向性
Woodruff 在博文中强调了一个微妙但关键的点:Trusted Publishing 建立的信任是单向的——PyPI 信任某个 CI Provider(如 GitHub Actions)对特定身份的断言。但这个信任链对下游用户来说意味着什么?
它不意味着:
- 包的代码经过了审计
- 包的维护者是可信的人
- 包的功能如其所声称的那样
- 包中没有恶意代码
它只意味着:
- 这次上传确实来自某个特定的 GitHub 仓库的特定工作流
PyPI 自己对此非常清醒。项目页面上没有任何「绿色对勾」来标记 Trusted Publishing 状态——这是刻意为之。PyPI 竭力避免用户将 Trusted Publishing 误解为某种「包质量认证」。
问题三:信任链下移而非消除
这是安全社区中最微妙的批评。Trusted Publishing 消除了长期 API Token 的风险,但将信任负担转移到了 OIDC 提供商身上。
Woodruff 的论证沿着这条路径展开:一旦你选择 Trusted Publishing,你实际上在信任——
- GitHub 的 OIDC 实现:Token 生成、签名、声明逻辑是否正确无误
- PyPI 的 OIDC 验证实现:声明校验、Token 解析是否正确
- 两者之间的身份映射:仓库所有者、仓库名、工作流名——这些声明的完整性
如果 GitHub 的 OIDC 基础设施出现漏洞,或者某个 CI/CD 工作流被攻陷,Trusted Publishing 并不能阻止恶意发布。LWN 读者 LtWorf 简洁地总结了这一点:
别担心,下次他们换种方式——偷你的 SSH 私钥和 GitHub Token,或者直接攻陷你的 GitHub runner。
换言之,Trusted Publishing 并没有消灭信任问题——它只是把信任从「自己保管好 API Token」下移到了「信任 GitHub 和 PyPI 的 OIDC 基础设施」。对于大多数用户来说,这个取舍是合理的(集中管理的 OIDC 基础设施大概率比你自己管理的 API Token 更安全),但它不是没有代价的。
来自社区的多棱镜
Lobsters 讨论区呈现了多元化的视角,折射出这个问题的不同切面。
「这仍然是一个有用的信号」
LWN 读者 roguelazer 的评论获得了大量关注。他从实际从业者的角度提供了对比视角:
我在多家公司见过 PyPI 凭据被专门攻击——它是一个高价值凭据,而且直到不久前 PyPI 还只支持用户名+密码认证。再加上团队管理在 PyPI、NPM 等平台上有多痛苦,很多公司最终都在使用共享凭据,这些凭据不可避免地会被泄露。
在他看来,通过正规 IdP(如 GitHub)的 Trusted Publishing 传递了有用的信号:认证已经外包给了一个有能力实施 passkey、企业身份治理等安全措施的第三方。相比那些「自 2011 年以来一直在用同一个共享用户名密码发布所有包」的场景,Trusted Publishing 发布的内容在认证层面可信度更高——虽然这并不能替代对代码内容的审查。
「这加剧了集中化的锁定效应」
Lobsters 用户 justJanne 从另一个角度切入:去中心化的消失。Trusted Publishing 之所以可能,正是因为过去 15 年间大量开源项目从自托管(邮件列表、自有 Git 仓库、自有构建服务器)迁移到了集中式 Forge(如 GitHub、GitLab)。他认为这形成了一种新的锁定:
2010 年代是便利性和社交网络效应推动项目进入集中式 Forge;现在,Trusted Publishing 等因素正在成为新的锁定理由。
他的引用颇具力量——来自 Steven Levy Hackers: Heroes of the Computer Revolution 中的 Hacker Ethics:「不信任权威——推动去中心化。」
Woodruff 对此作了回应:Trusted Publishing 并非锁定——你可以随时使用其他认证方式,包括 PyPI 已知如何与之联合的主机上的认证。而且,「把一个联合身份认证方案称为锁定,这本身就有些讽刺」。
「我的地下室 mini-PC 怎么办?」
Lobsters 用户 matklad 提出了一个很实际的问题:
假设我有一台地下室里的 mini-PC,运行着我所有开源项目的 CI。我应该阅读哪些文档来了解如何从这台机器使用 Trusted Publishing 发布到 PyPI?
Woodruff 的回答很坦率:你应该用 API Token,而不是 Trusted Publishing。
原因在于规模经济:在与小型自托管主机联合时,管理 OIDC 密钥对的价值与直接管理一个 API Token 相比,后者更优。这也是为什么 PyPI 从未建议放弃 API Token——它们仍然是大量合法场景下最合适的方案。
用户 finn 补充了另一个角度:Forgejo(Gitea 的社区分支)已经相当好地支持了自托管 OIDC,并为 CI 提供短效 JWT——「如果 PyPI 能让我们信任自己的 Forgejo 实例,那就太好了。」但现实是,npm 和某些注册表只允许 GitHub 和 GitLab.com,对自托管实例的支持仍然有限。
比较视角:其他生态怎么做的?
Trusted Publishing 并非 PyPI 独有。npm 在 2023 年引入了类似机制,crates.io(Rust 生态)也有相应的支持。但各平台的态度和推进力度不尽相同。
- npm:更激进的 OIDC 推广策略,甚至在讨论逐步淘汰长期 API Token。但 npm 的 Trusted Publishing 目前仅支持 GitHub Actions 和 GitLab.com 两个提供商。
- crates.io:同样支持 OIDC 联合,但社区规模较小,讨论热度相对低。
- PyPI:采取了最谨慎的路径——不剥夺 API Token、不暗示安全保证、不展示「信任徽章」。
一些 Lobsters 评论者指出,npm 的激进策略可能「外溢」到了 PyPI,让部分用户误以为 PyPI 也在推动类似的淘汰计划。但 PyPI 的官方立场是清醒而克制的。
真实的攻击面在哪里?
回到安全本质:Trusted Publishing 到底改变了什么攻击面?
它消除的风险(明确的胜利)
- 长期凭据泄漏:不再有可以静静躺在 CI 配置中数月甚至数年的 Token
- 手动凭据管理的失误:不会再有开发者把 API Token 复制粘贴到错误的地方
- 共享凭据问题:每个仓库、每个工作流都有自己的身份,不再需要团队共享同一个 Token
它引入的风险(值得关注)
- OIDC 基础设施单点:GitHub 的 OIDC 提供商如果出现漏洞,大量项目的发布通道同时受影响
- 工作流被攻陷:一旦 GitHub Actions 工作流本身被投毒(如 2025 年的 GhostAction 攻击),攻击者可以以合法身份发布恶意包
- 身份映射的完整性:PyPI 验证的是声明——如果 GitHub 对某个仓库的身份判断出错,信任链断裂
- 集中化的信任模型:将信任交给少数几个云平台,本质上是与去中心化的开源精神之间的张力
关键结论是:Trusted Publishing 并没有消除风险——它把风险从「你管理好 API Token」转移到了「GitHub 和 PyPI 管理好它们的基础设施」。对于绝大多数项目来说,这是一个合理的取舍(GitHub 的安全团队大概率比你能投在密钥管理上的精力多),但认识到这种转移本身的存在,就是 Woodruff 博文的核心价值所在。
那么,该不该用 Trusted Publishing?
综合所有讨论,一个务实的立场大概是这样的:
如果你的发布流程依托 GitHub Actions 或 GitLab CI,Trusted Publishing 几乎总是在安全上优于手动管理的长期 API Token。它消除了最实际的日常风险——凭据泄漏。
如果你自托管 CI,传统 API Token(带适当的轮换和权限限制)仍然是正确选择。
如果你在下游使用包,不要看一个项目是否使用了 Trusted Publishing 来判断它是否安全。它只告诉你包的来源是某个特定仓库——仅此而已。审查代码、检查依赖链、评估维护者信誉,这些工作省不掉。
正如 Woodruff 所说:Trusted Publishing 是给机器之间建立信任的,不是给你建立对包的信任的。搞混这两个概念,就是问题所在。
参考链接:
- https://blog.yossarian.net/2026/07/07/You-shouldnt-trust-trusted-publishing
- https://lobste.rs/s/8d9pgd/you_shouldn_t_trust_trusted_publishing
- https://docs.pypi.org/trusted-publishers/
本文的素材来自公开信息和社区讨论。如果你对这个话题有更深入的一手经验,欢迎指出文中的不足。