Configuration¶
The [tool.python-sbom] table¶
The options live in a [tool.python-sbom] table of the project’s pyproject.toml, the one place every plugin, the
wrapper backend, python-sbom embed and python-sbom archive read, so every SBOM of a project
names it alike. For the pdm-backend and setuptools plugins, the table’s presence, even empty, is what turns them on.
Each option is optional; an unknown key fails the build, so a typo cannot pass silently.
supplierThe organization that supplies the project: a table with a
namestring and an optionalurlstring array. It becomes the supplier and manufacturer of the document and the supplier of the project. Left out, the document names no supplier.[tool.python-sbom] supplier = { name = 'Python Packaging Authority', url = ['https://www.pypa.io'] }
repositoryThe repository URL, used for the link to the source revision, the license file and, on GitHub, the security policy and advisories. It defaults to the first
Source,RepositoryorGitHubURL in[project.urls].[tool.python-sbom] repository = 'https://gitlab.com/example/project'
default-branchThe branch in links to files of the repository when the build’s commit is unknown or the checkout has uncommitted changes,
mainby default; otherwise the links name the commit.[tool.python-sbom] default-branch = 'trunk'
bundled-wheelsGlob patterns, relative to the project root, of wheels the project ships as data files. Each matching wheel becomes a component with its SHA-256, license, files and the packages it vendors.
[tool.python-sbom] bundled-wheels = ['src/project/wheels/*.whl']
content-providerA
ContentProvider, asmodule:attributeimportable from the project root, that adds what the project knows beyond its metadata; Add what your project knows shows one. Loading it imports, and so runs, that module.[tool.python-sbom] content-provider = 'sbom_content:Content'
build-backendThe build backend
python_sbom.backendwraps, asmoduleormodule:object, the form[build-system] build-backendtakes. Only the wrapper reads it, and it fails the build when the project uses the wrapper without it; Use it with any other backend shows it.[tool.python-sbom] build-backend = 'mesonpy'
Bundled wheels¶
A bundled wheel’s files come from its RECORD, and the build fails when a member is missing from it, a row
names a member the wheel lacks, or a digest differs from the member’s content. Its vendored packages come from _vendor/vendor.txt, pip’s manifest, whose lines must each pin one exact version, and from any
.dist-info/METADATA under _vendor/. A bundled wheel gets a supplier only from the project’s content
provider, never from its own metadata.
Environment variables¶
SOURCE_DATE_EPOCHThe document’s timestamp, as a Unix time. Unset, a reproducible hatchling build uses hatchling’s fixed 2020-02-02, a pdm-backend build pdm-backend’s fixed 2016-01-01, and any other build the current time.
PYTHON_SBOM_COMMITThe source revision to record, a full commit hash, for a wheel built from an sdist without
.python-sbom-revision. It wins over every other source.
The source revision¶
The SBOM names the commit the wheel was built from. It takes the first source that knows it:
the
PYTHON_SBOM_COMMITenvironment variable, or--commiton the command line;git, when the project’s
pyproject.tomlis tracked by the checkout that holds it, so a project unpacked inside an unrelated repository never borrows that repository’s commit;.python-sbom-revision, which every integration writes into an sdist built from a clean checkout, so a wheel built from the sdist, aspython -m buildanduv builddo by default, keeps the commit;the
nodeline of an expanded.git_archival.txt, for agit archive.
A commit must be a full hash of 40 or 64 hex characters. A checkout with changes, including untracked files that are not
ignored, gets a <project>:vcs-dirty property, and the link to the revision says so; its sdist records no revision.
When git cannot read the checkout, the build moves on to the next source, and warns with git’s error only when none of
them names the commit. uv unpacks an sdist under an empty .git file that git rejects, so this keeps its builds
quiet. git runs with core.fsmonitor off, so a repository’s configuration runs no command.
Validation limits¶
Before anything else, python-sbom validate counts the components an SBOM lists, nested ones included, and fails an
SBOM that lists more than --max-components, 100,000 by default, without checking it further. Every check takes time
in proportion to the count: 100,000 files take about a second, and 100,000 packages, each also checked in the
SPDX rendering, about six. The cap bounds what an untrusted SBOM can ask of a CI job while staying far
above real SBOMs: every file of the wheel, of each bundled wheel and of each build tool counts, and virtualenv’s wheel
lists about 5,200.
The cap also sets the size limit: 1 KiB per component plus 1 MiB, 103,448,576 bytes at the default, about twice the 54
MB python-sbom writes for 100,000 components. validate refuses a larger SBOM before parsing it, and reads the SBOMs
of a wheel one at a time, so memory holds only one however many the wheel packs. It also refuses an SBOM nested more
than 128 levels deep; the SBOMs python-sbom and other tools write nest about a dozen levels.