Skip to content

Commit 3d8700a

Browse files
authored
Improve the ORT CycloneDX support (#1843)
* Upgrade the cyclonedx-python-lib to 11.0.0 #1727 The "Ignore unknown properties when deserializing" new feature is required Signed-off-by: tdruez <tdruez@nexb.com> * Fix the validate_document following library upgrade #1727 Signed-off-by: tdruez <tdruez@nexb.com> * Add support when the "components" entry is missing #1727 Signed-off-by: tdruez <tdruez@nexb.com> * Add support when the "components" entry is missing #1727 Signed-off-by: tdruez <tdruez@nexb.com> --------- Signed-off-by: tdruez <tdruez@nexb.com>
1 parent c4689c1 commit 3d8700a

File tree

5 files changed

+40
-4
lines changed

5 files changed

+40
-4
lines changed

CHANGELOG.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ v35.4.0 (unreleased)
2323
- Add a Resources tree view.
2424
https://github.com/aboutcode-org/scancode.io/issues/1682
2525

26+
- Improve CycloneDX SBOM support.
27+
* Upgrade the cyclonedx-python-lib to 11.0.0
28+
* Fix the validate_document following library upgrade.
29+
* Add support when the "components" entry is missing.
30+
https://github.com/aboutcode-org/scancode.io/issues/1727
31+
2632
v35.3.0 (2025-08-20)
2733
--------------------
2834

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ dependencies = [
8282
# Profiling
8383
"pyinstrument==5.1.1",
8484
# CycloneDX
85-
"cyclonedx-python-lib==10.2.0",
86-
"jsonschema==4.24.0",
85+
"cyclonedx-python-lib==11.0.0",
86+
"jsonschema==4.25.1",
8787
# MatchCode-toolkit
8888
"matchcode-toolkit==7.2.2",
8989
# Univers

scanpipe/pipes/cyclonedx.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,10 @@ def validate_document(document):
123123
The validator is loaded from the document specVersion property.
124124
"""
125125
if isinstance(document, str):
126+
document_str = document
126127
document = json.loads(document)
128+
else:
129+
document_str = json.dumps(document)
127130

128131
spec_version = document.get("specVersion")
129132
if not spec_version:
@@ -132,7 +135,8 @@ def validate_document(document):
132135
schema_version = SchemaVersion.from_version(spec_version)
133136

134137
json_validator = JsonStrictValidator(schema_version)
135-
return json_validator._validata_data(document)
138+
json_validation_errors = json_validator.validate_str(document_str)
139+
return json_validation_errors
136140

137141

138142
def is_cyclonedx_bom(input_location):
@@ -281,7 +285,7 @@ def is_empty(value):
281285
elif isinstance(value, list) and not any(value):
282286
return True
283287

284-
for component in cyclonedx_document_json["components"]:
288+
for component in cyclonedx_document_json.get("components", []):
285289
for property_name, property_value in component.items():
286290
if is_empty(property_value) or property_name in ignored_properties:
287291
entries_to_delete.append((component, property_name))
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"$schema": "http://cyclonedx.org/schema/bom-1.6.schema.json",
3+
"bomFormat": "CycloneDX",
4+
"specVersion": "1.6",
5+
"serialNumber": "urn:uuid:b74fe5df-e965-415e-ba65-f38421a0695d",
6+
"version": 1,
7+
"metadata": {
8+
"component": {
9+
"bom-ref": "804c3391-e6f9-415f-bb7a-cb6653853a46",
10+
"name": "name",
11+
"type": "library"
12+
},
13+
"timestamp": "2024-03-07T17:05:37.329061+00:00",
14+
"tools": [
15+
{
16+
"name": "ScanCode.io",
17+
"version": "0.0.0"
18+
}
19+
]
20+
}
21+
}

scanpipe/tests/pipes/test_cyclonedx.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,11 @@ def test_scanpipe_cyclonedx_resolve_cyclonedx_packages_pre_validation(self):
270270
expected = [{"name": "asgiref", "package_uid": "pkg:pypi/asgiref@3.3.0"}]
271271
self.assertEqual(expected, package_data)
272272

273+
def test_scanpipe_cyclonedx_resolve_cyclonedx_packages_missing_components(self):
274+
input_location = self.data / "missing_components.json"
275+
package_data = cyclonedx.resolve_cyclonedx_packages(input_location)
276+
self.assertEqual([], package_data)
277+
273278
def test_scanpipe_cyclonedx_cleanup_components_properties(self):
274279
cyclonedx_document_json = {
275280
"components": [

0 commit comments

Comments
 (0)