Information Security 10 min read

Applying the SLSA Framework to Build, Sign, Publish, and Verify Python Packages on GitHub

This article demonstrates how to apply the SLSA (Supply chain Levels for Software Artifacts) framework to the Python ecosystem by building clean packages, generating provenance statements, uploading them to PyPI, and verifying the package origin using GitHub Actions and the slsa‑verifier tool.

DevOps Engineer
DevOps Engineer
DevOps Engineer
Applying the SLSA Framework to Build, Sign, Publish, and Verify Python Packages on GitHub

Software supply‑chain attacks have risen dramatically, prompting Google to propose the SLSA (Supply chain Levels for Software Artifacts) framework. This guide shows how to use SLSA in the Python ecosystem for projects hosted on GitHub, taking a package from build to verification.

Contents

Build a clean Python package

Generate provenance (origin) statements

Upload the package to PyPI

Verify the package provenance

Project references

Build a clean Python package

A pure‑Python wheel and source distribution can be created with the command python3 -m build . The following GitHub Actions job builds the wheel and source distribution and records a SHA‑256 hash for each artifact:

jobs:
build:
steps:
- uses: actions/checkout@...
- uses: actions/setup-python@...
with:
python-version: 3.x
- run: |
# install build, create sdist and wheel
python -m pip install build
python -m build
# collect hashes
cd dist && echo "hashes=$(sha256sum * | base64 -w0)" >> $GITHUB_OUTPUT
- uses: actions/upload-artifacts@...
with:
path: ./dist

The hash values are stored in the hashes output variable for later use in the provenance job.

Generate provenance

The provenance job consumes the hash output via the needs relationship and invokes the reusable SLSA builder workflow to create a signed provenance file ( .intoto.jsonl ).

jobs:
provenance:
needs: [build]
uses: slsa-framework/slsa-github-builder/.github/workflows/[email protected]
permissions:
actions: read
id-token: write
contents: write
with:
subject-base64: ${{ provenance.needs.build.output.hashes }}
upload-assets: true

The resulting JSON‑Lines file contains the cryptographic proof that the artifacts were produced by the declared workflow.

Upload to PyPI

The official pypa/gh-action-pypi-publish action uploads the wheel to PyPI after the build and provenance steps have succeeded:

publish:
needs: ["build", "provenance"]
permissions:
contents: write
runs-on: "ubuntu-latest"
steps:
- uses: actions/download-artifact@...
with:
name: "dist"
path: "dist/"
- env:
GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
run: gh release upload ${{ github.ref_name }} dist/* --repo ${{ github.repository }}
- uses: "pypa/gh-action-pypi-publish@..."
with:
user: __token__
password: ${{ secrets.PYPI_TOKEN }}

Verify the package provenance

To verify a published package, the article uses the slsa‑verifier tool. As an example, it downloads the urllib3 wheel (version 2.1.0) and the matching provenance file from the GitHub release, then runs:

# download wheel
python3 -m pip download --only-binary=:all: urllib3
# download provenance
curl --location -O https://github.com/urllib3/urllib3/releases/download/2.1.0/multiple.intoto.jsonl
# verify
slsa-verifier verify-artifact --provenance-path multiple.intoto.jsonl --source-uri github.com/urllib3/urllib3 urllib3-2.1.0-py3-none-any.whl

The verifier confirms the builder ID, source repository, tag, and commit, proving that the wheel was built exactly as described. After a successful verification, the wheel can be safely installed.

Projects and tools referenced

SLSA GitHub Builder

slsa‑framework/slsa‑verifier

pypa/gh-action-pypi-publish

pypa/build

urllib3/urllib3

PythonGitHub Actionspypisupply chain securitySLSAProvenance
DevOps Engineer
Written by

DevOps Engineer

DevOps engineer, Pythonista and FOSS contributor. Created cpp-linter, commit-check, etc.; contributed to PyPA.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.