CycloneDX Python Library
The CycloneDX Python Library provides data models, validators, and serialization/deserialization capabilities for creating, rendering, and reading CycloneDX Software Bill of Materials (SBOM) documents. It is an OWASP Flagship Project and is intended as a programmatic library, not a standalone SBOM generation tool. The library maintains a frequent release cadence, often releasing new minor versions multiple times a quarter.
Common errors
-
AttributeError: type object 'datetime.datetime' has no attribute 'fromisoformat'
cause This error occurs when running `cyclonedx-python-lib` on Python versions older than 3.7, as the `datetime.fromisoformat()` method was introduced in Python 3.7.fixUpgrade your Python environment to version 3.7 or newer (the library officially supports Python >=3.9). Alternatively, for older Python 3 versions, you can use the `backports-datetime-fromisoformat` library. -
ValueError: Unexpected key <KEY_NAME> in data being serialized to cyclonedx.model.bom.BomMetaData
cause This error typically arises during serialization (e.g., to JSON or XML) when the data model you've constructed contains an attribute or field that is not expected or recognized by the `cyclonedx-python-lib`'s internal data model for the specific CycloneDX schema version being used.fixReview the CycloneDX specification for the target schema version and ensure that all fields in your Python data model (`cyclonedx.model.*` objects) correspond correctly to the specification. Remove or rename unexpected keys, or ensure they are nested correctly within the expected parent elements. -
cyclonedx.exception.ValidationError: Validation failed: <detailed error message>
cause This exception is raised when attempting to validate a CycloneDX Bill of Materials (BOM) object, and the BOM does not conform to the specified CycloneDX schema version or contains invalid data according to the schema rules (e.g., incorrect data types, missing required fields, or malformed structures).fixExamine the detailed error message provided in the `ValidationError` to identify the specific part of your BOM that is invalid. Correct the data in your `cyclonedx.model.bom.Bom` object to ensure it strictly adheres to the CycloneDX specification for your chosen schema version. For example, ensuring `metadata.authors` are lists of `OrganizationalContact` objects rather than simple strings.
Warnings
- breaking Deserialization behavior changed to ignore unknown properties by default. Previously, unknown properties might have caused errors during deserialization.
- deprecated Certain exports were deprecated, and non-standard implementations were moved to a `contrib` sub-package. This includes methods like `Bom.get_component_by_purl()` which were previously available directly on the `Bom` object.
- gotcha This package is a software library for data models and manipulation, not a standalone command-line tool for generating SBOMs from projects. For CLI tools, refer to `cyclonedx-python` or `Jake`.
- breaking Support for Python versions older than 3.8 was dropped. Also, significant changes were made to license models and validation behavior (e.g., `Bom.validate()` can now throw `LicenseExpressionAlongWithOthersException`). The `SchemaVersion` and `OutputVersion` enums are no longer string-like.
- gotcha Serialization of unsupported enum values (e.g., component types, external reference types not defined in the target schema version) might result in downgrading, migration, or omission of those values in the output, potentially causing data loss.
Install
-
pip install cyclonedx-python-lib -
pip install cyclonedx-python-lib[validation] -
pip install cyclonedx-python-lib[json-validation] -
pip install cyclonedx-python-lib[xml-validation]
Imports
- Bom
from cyclonedx.model.bom import Bom
- Component
from cyclonedx.model.component import Component
- Purl
from cyclonedx.model.component import Purl
from packageurl.contrib.url2purl import url2purl
- JsonV15
from cyclonedx.output import Json
from cyclonedx.output import JsonV15
Quickstart
from cyclonedx.model.bom import Bom
from cyclonedx.model.component import Component
from cyclonedx.model.dependency import Dependency
from packageurl.contrib.url2purl import url2purl
from cyclonedx.output import JsonV15
# 1. Create a new BOM
bom = Bom()
# 2. Define components
component_a = Component(name='my-app', version='1.0.0')
component_a.bom_ref.value = 'pkg-a-1.0.0'
component_b_purl = url2purl('pkg:pypi/requests@2.28.1')
component_b = Component(name='requests', version='2.28.1', purl=component_b_purl)
component_b.bom_ref.value = 'pkg-b-2.28.1'
# 3. Add components to the BOM
bom.add_component(component_a)
bom.add_component(component_b)
# 4. Add a dependency relationship (optional)
dep_a_to_b = Dependency(ref=component_a.bom_ref)
dep_a_to_b.add_dependency(component_b.bom_ref)
bom.add_dependency(dep_a_to_b)
# 5. Serialize the BOM to JSON (using CycloneDX Schema Version 1.5)
outputter = JsonV15(bom)
json_output = outputter.output_as_string(indent=2)
print(json_output)
# Example of deserialization (requires `validation` extra)
# from cyclonedx.validation.schema import SchemaVersion
# from cyclonedx.parsers.json.parser import JsonParser
# parsed_bom = JsonParser(json_output).parse(SchemaVersion.V1_5)
# print(f"Parsed BOM version: {parsed_bom.get_spec_version().to_string()}")