Speakeasy Logo
Skip to Content

SDKs

Secure your Python SDK publishing with PyPI trusted publishing

Speakeasy Team

Speakeasy Team

February 6, 2026 - 4 min read

SDKs

If you’re publishing Python SDKs to PyPI, there’s now a better way to handle authentication in your CI/CD pipelines: trusted publishing.

The problem with long-lived tokens

Traditional PyPI publishing workflows rely on API tokens stored as GitHub secrets. While functional, this approach has well-known drawbacks:

  • Token leaks are a leading cause of supply chain attacks. A single exposed PYPI_TOKEN can give an attacker full publishing access to your package.
  • Token rotation is manual and easy to forget, leaving stale credentials in your workflows.
  • Broad permissions mean that a compromised token can publish any version of your package from anywhere.

The Python packaging ecosystem has been moving toward a more secure model, and PyPI’s trusted publishers  feature is now the recommended approach for publishing from CI/CD pipelines.

A better way: trusted publishing with OIDC

Trusted publishing uses OpenID Connect (OIDC) to establish a trust relationship between PyPI and your GitHub Actions workflow. Instead of storing a long-lived token, your workflow requests a short-lived token from PyPI at publish time, scoped to that specific workflow run.

Here’s why it’s worth adopting:

  • No secrets to manage — OIDC tokens are generated on the fly and expire immediately
  • Scoped to your workflow — only the configured GitHub repository and workflow can publish
  • No rotation required — there’s nothing to rotate when there are no stored credentials
  • Better auditability — every publish is tied to a specific commit, workflow run, and repository

Setting up PyPI trusted publishing with Speakeasy

Speakeasy now supports PyPI trusted publishing out of the box. There are two ways to set it up: the Speakeasy CLI handles everything automatically, or you can configure the workflow files by hand.

Option A: Automatic setup via CLI

The fastest path. Run a single command in the root of your SDK repository:

speakeasy configure publishing --pypi-trusted-publishing

This command:

  • Adds the id-token: write permission to your publishing workflow
  • Adds the publish-pypi job to .github/workflows/sdk_publish.yaml
  • Updates .speakeasy/workflow.yaml with the trusted publishing configuration

After running the command, skip ahead to configure the trusted publisher on PyPI.

Option B: Manual setup

If you prefer to configure the workflow files yourself, or need to understand exactly what changes, follow the steps below.

Update GitHub workflow permissions

Add the id-token: write permission to your publishing workflow. This is required to request OIDC tokens from GitHub:

permissions: checks: write contents: write pull-requests: write statuses: write id-token: write # Required for OIDC trusted publishing

Add the publish-pypi job

Add a new job to .github/workflows/sdk_publish.yaml that runs after the main publish job:

publish-pypi: needs: publish if: ${{ needs.publish.outputs.python_regenerated == 'true' && needs.publish.outputs.publish_python == 'true' && needs.publish.outputs.use_pypi_trusted_publishing == 'true' }} runs-on: ubuntu-latest permissions: id-token: write contents: read steps: - uses: actions/checkout@v4 - uses: speakeasy-api/sdk-generation-action/publish-pypi@v15 with: python-directory: ${{ needs.publish.outputs.python_directory }} speakeasy_api_key: ${{ secrets.SPEAKEASY_API_KEY }} github_access_token: ${{ secrets.GITHUB_TOKEN }}

The job-level permissions block ensures the OIDC token is available to the action. The if condition gates publishing on three outputs from the main publish job: the Python SDK was regenerated, publishing is enabled, and trusted publishing is configured.

Configure the trusted publisher on PyPI

Whether you used the CLI or manual setup, you’ll still need to configure the trusted publisher on pypi.org :

  • Navigate to Manage > Publishing for your package
  • Select GitHub Actions as the trusted publisher
  • Enter the GitHub owner and repository name for your SDK
  • Set the workflow name to the publishing workflow file (typically sdk_publish.yaml)
  • Leave the environment field blank

For detailed instructions, see the PyPI trusted publishers documentation .

Test your configuration

  • Navigate to your repository’s Actions tab on GitHub
  • Run the Generate workflow with Force generation of SDKs checked
  • Bump the SDK version using the set a specific SDK version field
  • Once the workflow completes, verify the new version appears on pypi.org 

After a successful publish, you can safely remove the PYPI_TOKEN secret from your repository settings.

The bottom line

Trusted publishing is the direction the Python ecosystem is heading, and the benefits are clear: better security, less maintenance, and a simpler workflow. If you’re publishing Python SDKs with Speakeasy, migrating takes just a few minutes.


For more details on publishing Speakeasy-generated SDKs, check out the publishing documentation.

Last updated on

Build with
confidence.

Ship what's next.