python-sbom¶
Every wheel you ship, with its SBOM inside.
A build plugin that writes a software bill of materials (SBOM) in the CycloneDX format into each wheel your build backend makes, where PEP 770 (a Python Enhancement Proposal) tells installers and scanners to look for it.
python-sbom writes a CycloneDX 1.6 SBOM into every wheel you build, at
<name>-<version>.dist-info/sboms/<name>.cdx.json. That is where PEP 770 tells installers to keep SBOMs, so
they land in the environment next to the installed package, where scanners look for them.
General-purpose scanners read the dependencies a package declares or the packages an environment has installed. They cannot see a wheel your project ships as a data file, and they cannot say how the wheel was built. The SBOM python-sbom writes records both. The Changelog lists the changes in each version.
A plugin for hatchling, pdm-backend and setuptools, and a wrapper backend for meson-python, maturin and the rest.
The source commit, the interpreter and every build tool down to its files, so a third party can rebuild the wheel and compare the bytes.
Each wheel a project ships as data, with its hashes, license, files and the packages it vendors.
A build, the SBOM it wrote, and the check a CI job runs before publishing:
$ uv build
Successfully built dist/greet-1.0.tar.gz
Successfully built dist/greet-1.0-py3-none-any.whl
$ unzip -Z1 dist/greet-1.0-py3-none-any.whl | grep sboms
greet-1.0.dist-info/sboms/greet.cdx.json
$ python-sbom validate dist/ --allow-license MIT
SBOM in greet-1.0-py3-none-any.whl is valid
Install¶
python-sbom runs inside your build, so it goes in [build-system] requires with the extra for your backend, and a
[tool.python-sbom] table names you as the supplier. It needs Python 3.11 or later.
[build-system]
build-backend = "hatchling.build"
requires = [ "hatchling>=1.28", "python-sbom[hatch]>=0.3" ]
[project]
name = "greet"
version = "1.0"
description = "says hello"
license = "MIT"
license-files = [ "LICENSE" ]
requires-python = ">=3.11"
classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3.15",
]
dependencies = [ "packaging>=24" ]
urls.Source = "https://github.com/you/greet"
[tool.hatch]
build.hooks.python-sbom = {}
[tool.python-sbom]
supplier = { name = "You", url = [ "https://github.com/you" ] }
[build-system]
build-backend = "pdm.backend"
requires = [ "pdm-backend>=2.4", "python-sbom[pdm]>=0.3" ]
[project]
name = "greet"
version = "1.0"
description = "says hello"
license = "MIT"
requires-python = ">=3.11"
classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3.15",
]
dependencies = [ "packaging>=24" ]
[tool.python-sbom]
supplier = { name = "You", url = [ "https://github.com/you" ] }
[build-system]
build-backend = "setuptools.build_meta"
requires = [ "python-sbom[setuptools]>=0.3", "setuptools>=77" ]
[project]
name = "greet"
version = "1.0"
description = "says hello"
license = "MIT"
requires-python = ">=3.11"
classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3.15",
]
dependencies = [ "packaging>=24" ]
[tool.python-sbom]
supplier = { name = "You", url = [ "https://github.com/you" ] }
[build-system]
build-backend = "python_sbom.backend"
requires = [ "meson>=1.6", "meson-python>=0.18", "ninja", "python-sbom>=0.3" ]
[project]
name = "greet"
version = "1.0"
description = "says hello"
license = "MIT"
requires-python = ">=3.11"
classifiers = [
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3.15",
]
dependencies = [ "packaging>=24" ]
[tool.python-sbom]
build-backend = "mesonpy"
supplier = { name = "You", url = [ "https://github.com/you" ] }
Every wheel you build from then on carries the SBOM. How-to guides covers each backend in detail.
The command line, which describes wheels built elsewhere and checks SBOMs, installs as a tool:
uv tool install 'python-sbom[validate]'
python-sbom --help
pipx install 'python-sbom[validate]'
python-sbom --help
Where to go next¶
The tutorial builds a first package with an SBOM, reads it, and checks it.
Each guide sets python-sbom up for one backend or handles one kind of artifact.
The backends, the configuration, the command line and the Python API.
Why each backend gets its integration, what the SBOM records, and how the code is laid out.