☰
PyPI Trusted Publishing + Attestations 实战:告别 API Token,建立可信 Python 发布链
2026/10/13 5:41:19 网站建设 项目流程

PyPI Trusted Publishing + Attestations 实战:告别 API Token,建立可信 Python 发布链

摘要

很多 Python 项目的 PyPI 发布流程仍然是:

GitHub Actions + PYPI_API_TOKEN

问题在于:API Token 是长期凭据,一旦 CI Secret、第三方 Action 或 Runner 被攻陷,攻击者可能直接向 PyPI 发布恶意版本。

PyPI Trusted Publishing 通过 OIDC 把“长期 Token”替换成“工作流身份”;同时 PyPI 已支持将 Attestations 与每个发布文件绑定,使 Python 包可以拥有更加完整的发布来源证据。

本文给出一套可直接落地的 Python 包可信发布流程。


1. 传统 PyPI 发布链的问题

典型配置:

password:${{secrets.PYPI_API_TOKEN}}

攻击者的目标非常明确:

偷到 Token ↓ 上传恶意版本 ↓ 用户 pip install

一个长期 Token 可能跨越:

  • 多次发布;
  • 多个 Workflow;
  • 很长生命周期。

这与现代供应链安全的“短期身份”方向相矛盾。


2. 什么是 Trusted Publishing?

Trusted Publishing 的核心是:

CI Identity ↓ OIDC ↓ PyPI Verify ↓ Temporary Publishing Authorization

不需要在 GitHub Secrets 里保存 PyPI 用户名、密码或长期 API Token。

PyPI 当前支持多类 Trusted Publisher,包括 GitHub Actions、GitLab CI/CD、Google Cloud 等。


3. GitHub Actions 中最关键的权限

发布 Job:

permissions:id-token:write

这个权限允许 Workflow 请求 OIDC Token。

推荐再使用 GitHub Environment:

environment:name:pypi

结合人工审批与保护规则。


4. 一个推荐发布流程

Git Tag

Build

Test

Generate Distribution

OIDC

PyPI Trusted Publishing

Attestation

PyPI Release


5. 官方 PyPA Action

PyPI 官方文档推荐使用 PyPA 的发布 Action。

示意:

jobs:pypi-publish:runs-on:ubuntu-latestenvironment:pypipermissions:id-token:writesteps:-name:Publish packageuses:pypa/gh-action-pypi-publish@release/v1

这样无需:

PYPI_API_TOKEN

6. 什么是 PyPI Attestation?

PyPI 允许 Attestation 与单个 Release File 绑定。

例如一个 Release 可能包含:

demo-1.0.0.tar.gz demo-1.0.0-py3-none-any.whl

每个文件都可以拥有对应证明。

证明的价值是:

这个文件来自哪个可信发布身份?

7. 官方发布 Action 会自动生成证明

根据 PyPI 文档,使用官方:

pypa/gh-action-pypi-publish

时,Attestations 默认会自动生成并上传。

这意味着发布链可以自然变成:

OIDC Identity + Trusted Publishing + Attestation

8. 手工生成 Attestation

PyPI 提供:

pypi-attestations

工具。

例如:

python-mpipinstallpypi-attestations python-mpypi_attestations sign dist/*

在 GitHub Actions 中,如果启用了:

id-token:write

工具可以使用工作流的环境身份生成证明。


9. Twine 上传 Attestation

如果使用 Twine:

twine upload--attestationsdist/*

即可在上传发行文件时携带相应 Attestations。


10. 为什么 Attestation 很重要?

以前:

PyPI 上有这个包

大家自然认为:

这是官方发布

但现代供应链安全要求更严格:

Package exists ≠ Trusted Build

我们更希望验证:

这个文件 来自这个项目 由这个 CI 身份 在这个发布流程中生成

11. 建议拆分 Build 与 Publish

不要让:

Build Job

同时拥有 PyPI 发布身份。

推荐:

Build Job ↓ Artifact ↓ Publish Job ↓ OIDC ↓ PyPI

Publish Job:

  • 不执行不可信 PR 代码;
  • 只消费已构建的发行文件;
  • 只在 Tag/Release 时执行;
  • 绑定 Environment。

12. 第三方 Action 风险

Trusted Publishing 消除了长期 Token,但并不代表 Workflow 自动安全。

仍然需要:

  • 固定第三方 Action Commit;
  • 最小化 Job 权限;
  • 防止 PR 注入;
  • 限制 Tag 创建权限;
  • 保护 Release Workflow。

否则攻击者仍然可能借合法工作流身份发布恶意包。


13. Python 项目的可信发布基线

推荐:

Protected Branch + Protected Tag + Dedicated Release Workflow + OIDC Trusted Publishing + Attestation + SBOM + Reproducible Build

如果是高价值软件,还可以增加:

Manual Approval

14. 如何迁移旧项目?

第一步

在 PyPI 项目设置中配置 Trusted Publisher。

第二步

给 GitHub Workflow 增加:

permissions:id-token:write

第三步

切换到官方发布 Action。

第四步

删除:

PYPI_API_TOKEN

第五步

确认 Attestation 正常生成。


15. 安全收益

从:

Secret-based Publishing

升级到:

Identity-based Publishing

直接减少了:

  • Token 泄露;
  • Token 轮换;
  • Secret 管理;
  • Token 跨工作流复用。

同时 Attestation 又增加了发布来源可验证性。


总结

Python 包发布链正在从:

API Token

向:

OIDC Identity + Trusted Publishing + Attestation

升级。

对于企业 Python 项目,建议把 Trusted Publishing 作为新的默认发布模式,而不是额外增强项。

最终目标是:

每个发布到 PyPI 的文件,都能证明它来自预期的项目和可信发布流程。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询