From 5c3cb3a47cdec8b2a86592c5ae59721f3350690b Mon Sep 17 00:00:00 2001 From: mesutoezdil Date: Mon, 15 Jun 2026 21:40:37 +0200 Subject: [PATCH] fix(sbom): detect sha256 hashes in expression-form licenses in needs_fix CycloneDX allows licenses as either {"license": {"id": "..."}} or {"expression": "..."}. needs_fix only checked the license form, so expression entries with sha256 hashes were silently skipped. Add expression-form check to needs_fix, mirroring the fix in extract_licenses (#1898). Add tests covering both forms. --- deploy/sbom/resolve_licenses.py | 4 +++ deploy/sbom/test_resolve_licenses.py | 44 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 deploy/sbom/test_resolve_licenses.py diff --git a/deploy/sbom/resolve_licenses.py b/deploy/sbom/resolve_licenses.py index fbdfc5fa5..6082f823c 100644 --- a/deploy/sbom/resolve_licenses.py +++ b/deploy/sbom/resolve_licenses.py @@ -344,6 +344,10 @@ def needs_fix(comp: dict) -> bool: if not licenses: return True for entry in licenses: + if "expression" in entry: + if entry["expression"].startswith("sha256:"): + return True + continue lic = entry.get("license", {}) lid = lic.get("id", "") lname = lic.get("name", "") diff --git a/deploy/sbom/test_resolve_licenses.py b/deploy/sbom/test_resolve_licenses.py new file mode 100644 index 000000000..9c01e1cd6 --- /dev/null +++ b/deploy/sbom/test_resolve_licenses.py @@ -0,0 +1,44 @@ +# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +"""Tests for deploy/sbom/resolve_licenses.py.""" + +from __future__ import annotations + +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).parent)) +from resolve_licenses import needs_fix + + +def test_empty_licenses_needs_fix() -> None: + assert needs_fix({"licenses": []}) + + +def test_no_licenses_key_needs_fix() -> None: + assert needs_fix({}) + + +def test_sha256_in_license_id_needs_fix() -> None: + assert needs_fix({"licenses": [{"license": {"id": "sha256:abc123"}}]}) + + +def test_sha256_in_license_name_needs_fix() -> None: + assert needs_fix({"licenses": [{"license": {"name": "sha256:abc123"}}]}) + + +def test_sha256_expression_needs_fix() -> None: + assert needs_fix({"licenses": [{"expression": "sha256:abc123"}]}) + + +def test_valid_spdx_expression_no_fix() -> None: + assert not needs_fix({"licenses": [{"expression": "MIT OR Apache-2.0"}]}) + + +def test_valid_license_id_no_fix() -> None: + assert not needs_fix({"licenses": [{"license": {"id": "MIT"}}]}) + + +def test_valid_license_name_no_fix() -> None: + assert not needs_fix({"licenses": [{"license": {"name": "MIT"}}]})