.. SPDX-FileCopyrightText: 2026 cusy GmbH
..
.. SPDX-License-Identifier: BSD-3-Clause
Software Bill of Materials (SBOM)
=================================
A Software Bill of Materials (SBOM) is a document used to exchange information
about software and its composition. This format is primarily used in the
security field to check software and its dependencies for vulnerabilities using
vulnerability databases such as `CVE `_ and `OSV
`_. The SBOM format used by the CPython project is `SPDX
`_, which
can be converted to other formats as needed. The SBOM file for the dependencies
included in CPython is maintained at `Misc/sbom.spdx.json
`_. The file is
generated using `Tools/build/generate_sbom.py
`_.
Generating an SBOM File
-----------------------
… with uv
~~~~~~~~~
:term:`uv` provides an easy way to generate an SBOM file in the CycloneDX v1.5
format using:
.. code-block:: console
$ uv export --format='cyclonedx1.5' > sbom.cdx.json
However, the file contains only very basic information; for example, for
`cusy.tasks `_:
.. code-block:: json
"component": {
"type": "library",
"bom-ref": "cusy-tasks-1@26.2.0",
"name": "cusy-tasks",
"version": "26.2.0",
"properties": [
{
"name": "uv:package:is_project_root",
"value": "true"
}
]
}
Using ``uv export --all-groups --format='cyclonedx1.5' > sbom.cdx.json``, you
can also include all dependency groups in the SBOM file.
… using CycloneDX Python
~~~~~~~~~~~~~~~~~~~~~~~~
The output from `CycloneDX Python
`_ is
considerably more comprehensive:
.. code-block:: json
{
"bom-ref": "cusy-tasks==26.2.0",
"description": "",
"externalReferences": [
{
"comment": "PackageSource: Local",
"type": "distribution",
"url": "file:///Users/veit/cusy/prj/cusy.tasks"
},
{
"comment": "from packaging metadata Project-URL: Documentation",
"type": "documentation",
"url": "https://tasks.cusy.io/"
},
{
"comment": "from packaging metadata Project-URL: Mastodon",
"type": "other",
"url": "https://mastodon.social/@Python4DataScience"
},
{
"comment": "from packaging metadata Project-URL: GitHub",
"type": "vcs",
"url": "https://github.com/cusyio/cusy.tasks"
}
],
"licenses": [
{
"license": {
"acknowledgement": "declared",
"id": "BSD-3-Clause"
}
}
],
"name": "cusy-tasks",
"type": "library",
"version": "26.2.0"
}
The command to generate the file is:
.. code-block:: console
$ uvx --from cyclonedx-bom cyclonedx-py environment .venv --output-file sbom.cdx.json
.. warning::
CycloneDX Python generates the SBOM file from the current :file:`.venv`
directory. So if you run ``cyclonedx-bom`` in your development environment,
you will also find all your development tools listed in your SBOM file.
… with sbomify
~~~~~~~~~~~~~~
sbomify provides a GitHub Action for generating the SBOM file, which uses
CycloneDX Python under the bonnet. The file can then be attested using
`actions/attest-sbom `_:
.. literalinclude:: sbomify.yml
:caption: .github/workflows/sbomify.yml
:language: yaml
In GitLab CI, you can use sbomify as follows:
.. literalinclude:: .gitlab-ci.yml
:caption: .gitlab-ci.yml
:language: yaml
:lines: 1-12, 32-
You can also integrate dependency scanning:
.. literalinclude:: .gitlab-ci.yml
:caption: .gitlab-ci.yml
:language: yaml
:lines: 13-30
.. seealso::
* `SBOM Generation in CI/CD Pipelines `_
* `Dependency scanning by using SBOM
`_
PEP 770 – SBOMs in Python packages
---------------------------------~
:pep:`770` standardises the inclusion of SBOMs in Python wheels via the
:file:`.dist-info/sboms/` directory. If you publish Python packages on
:term:`PyPI`, this means that your users will automatically receive the SBOM
file when they install your package, for example:
.. code-block:: console
myapp-26.2.0.dist-info
├── METADATA
├── RECORD
└── sboms/
└── myapp.cdx.json
Build backends such as Hatchling ≥ 1.28 already support this via the
``sbom-files`` configuration:
.. code-block:: toml
:caption: pyproject.toml
[tool.hatch.build.targets.wheel]
sbom-files = ["myapp.cdx.json"]
Instead of generating the SBOM file from scratch during the build, a minimal
CycloneDX SBOM file can be checked into the repository:
.. code-block:: json
{
"bomFormat": "CycloneDX",
"specVersion": "1.6",
"version": 1,
"metadata": {
"component": {
"type": "library",
"name": "mylib",
"version": "0.0.0-placeholder"
}
},
"components": []
}
In the :term:`CI` workflow, the placeholder SBOM file is then checked out along
with the code. sbomify then enriches it with the latest information. Hatchling
subsequently builds the wheel using the latest SBOM file, and finally the :term:`wheel` is published to :term:`PyPI`.
Analysis
--------
There are numerous tools available for security and licence checks, each
focusing on different problem areas. Two open-source tools for SBOM analysis are
`Dependency Track `_ and `GUAC `_.
With ``sbomify-action``, you can upload SBOMs directly from the :term:`CI`
pipeline to your Dependency Track instance using:
.. code-block:: yaml
UPLOAD_DESTINATIONS=dependency-track