How PyPI Trusted Publishing Uses OIDC in CI/CD
Trusted Publishing on the Python Package Index (PyPI) utilizes OpenID Connect (OIDC) to establish a cryptographic trust relationship between PyPI and continuous integration (CI/CD) providers like GitHub Actions, GitLab CI, and Google Cloud. This article examines how this mechanism functions, why it replaces static credentials, and the architectural process of exchanging temporary cryptographic identity proofs for short-lived package upload privileges.
The Problem with Traditional API Tokens
Historically, publishing a Python wheel or source distribution required developers to generate a long-lived PyPI API token and store it as a secret inside their CI/CD platform (such as repository secrets in GitHub). This approach introduced significant supply chain vulnerabilities:
- Credential Leakage: Static secrets can accidentally be printed to build logs, leaked through compromised build environments, or extracted by malicious third-party dependencies during the build phase.
- Lack of Expiration: Long-lived tokens often remain valid indefinitely, making forgotten or abandoned credentials permanent attack vectors.
- Management Overhead: Organizations had to manually rotate, track, and audit secrets across multiple repositories and environments.
The Architecture of OIDC-Based Trusted Publishing
Trusted Publishing eliminates the need to store secrets in your CI/CD platform entirely. Instead, it relies on OpenID Connect (OIDC), an identity layer built on top of the OAuth 2.0 framework.
The publishing process follows a deterministic exchange:
- Trust Configuration: The package maintainer configures a "Trusted Publisher" directly inside their PyPI account or organization settings. This defines trusted parameters, including the CI/CD provider (e.g., GitHub), the repository owner and name, the workflow filename, and optional constraints such as specific branches or tags.
- Identity Token Generation: When a build runs, the
CI runner requests a signed JSON Web Token (JWT) from its platform's
internal OIDC token service. This token contains structured claims about
the job execution, such as
repository,workflow,ref, andactor. - Token Exchange: The build step (for example, the
official
pypa/gh-action-pypi-publishaction) sends this unsigned identity token to the PyPI token exchange endpoint (https://pypi.org/_/oidc/mint-token). - Claim Verification: PyPI fetches the CI provider's public keys via its OpenID Connect discovery document and verifies the cryptographic signature on the JWT. PyPI then checks the token's claims against the pre-configured parameters saved for that project.
- Ephemeral Credential Issuance: Once verified, PyPI mints an ephemeral, highly restricted API token. This token is scoped exclusively to the specific package and expires automatically within minutes (typically 15 minutes).
- Artifact Upload: The CI runner uses this short-lived token to authenticate the upload of artifacts via standard PyPI APIs before the token expires.
Security and Operational Benefits
By shifting from stored secrets to ephemeral claims-based authentication, Trusted Publishing improves supply chain security:
- Zero Secret Storage: Maintainers no longer need to copy, paste, or manage static credentials in repository settings. Compromised build environments yield no permanent secrets.
- Granular Scoping: Tokens are valid strictly for the intended repository, branch, and package, preventing privilege escalation.
- Provable Provenance: Because PyPI verifies the exact build identity directly with the provider, releases can be verified as originating exclusively from the designated CI/CD pipeline, laying the groundwork for verifiable software supply chain attestation (SLSA).