Skip to content

✨ feat(build): ship a CycloneDX SBOM in every wheel - #3265

Merged
gaborbernat merged 1 commit into
pypa:mainfrom
gaborbernat:sbom-attestation
Sep 19, 2026
Merged

gaborbernat merged 1 commit into
pypa:mainfrom
gaborbernat:sbom-attestation

Conversation

@gaborbernat

Copy link
Copy Markdown
Contributor

Downstream consumers scanning for bundled software cannot see the pip and setuptools wheels virtualenv embeds under src/virtualenv/seed/wheels/embed. 📦 I tested syft, cyclonedx-py, and GitHub's own dependency-graph export against a real build of this project: each one reads declared dependency metadata or an installed environment, and these wheels are neither. They are data files, invisible to every tool tried, so anyone auditing what a virtualenv install actually contains has no way to find them today.

PEP 770 exists for exactly this case. hatch_build.py adds a hatchling build hook that writes a CycloneDX 1.6 document into the wheel's .dist-info/sboms/ directory, declaring each bundled wheel with its name, version, licence, and the SHA-256 already computed for integrity checking at install time. The hook reads BUNDLE_SUPPORT and BUNDLE_SHA256 straight out of the existing embed/__init__.py with ast.literal_eval, the same approach tasks/upgrade_wheels.py already uses to regenerate those tables, so a wheel bump keeps the SBOM current without a separate update step.

No scanner runs in CI. Every one I tested against this repository either found nothing or a component list that omitted the four things actually worth declaring, so adding one here would add a dependency and an upgrade treadmill just to reproduce data pyproject.toml already states. 🔍

hatchling>=1.28 is now required, since that is the release that added sbom-files support. The release workflow extracts the SBOM from the built wheel and attests it against the sdist and wheel with actions/attest, whose required permissions (id-token, attestations, artifact-metadata) I checked against the action's own documentation rather than assume, and whose pinned SHA I resolved from its real tags rather than copy from a neighbouring step.

Downstream consumers scanning for bundled software cannot see the
pip and setuptools wheels virtualenv embeds under
src/virtualenv/seed/wheels/embed: syft, cyclonedx-py and GitHub's own
dependency-graph export all read declared dependency metadata or an
installed environment, and these wheels are neither. They are data
files, invisible to every one of those tools, verified empirically
against a real build of this project.

PEP 770 exists for exactly this case. A build hook now writes a
CycloneDX 1.6 document into the wheel's .dist-info/sboms/ directory,
declaring each bundled wheel with its name, version, licence and the
SHA-256 already computed for integrity checking at install time. The
hook reads BUNDLE_SUPPORT and BUNDLE_SHA256 straight out of the
existing embed/__init__.py with ast.literal_eval, the same approach
tasks/upgrade_wheels.py already uses, so a wheel bump keeps the SBOM
current with no separate update step.

No scanner runs in CI. Every one tested against this repository
either found nothing or a component list that omitted the four
things worth declaring, so adding one would add a dependency and an
upgrade treadmill to reproduce data pyproject.toml already states.

hatchling>=1.28 is required for sbom-files support, but that release
also dropped Python 3.9 from hatchling itself, which is still a
supported build environment here. build-system.requires now splits
on python_version so anything older stays on hatchling<1.28, and the
hook checks for the sbom_files key before touching it rather than
assuming the newer hatchling ran, so those builds proceed without an
SBOM instead of failing.

The release workflow extracts the SBOM from the built wheel and
attests it against the sdist and wheel with actions/attest, verified
against the action's own documented required permissions.
@gaborbernat
gaborbernat merged commit 777dc41 into pypa:main Sep 19, 2026
64 checks passed
@gaborbernat gaborbernat added the security Fixes a vulnerability or hardens the supply chain, CI or release label Sep 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement security Fixes a vulnerability or hardens the supply chain, CI or release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant