From b0a9f5062c0fa489580330eb5b4504ae2274a452 Mon Sep 17 00:00:00 2001 From: Quentin Kaiser Date: Mon, 15 Dec 2025 12:27:16 +0100 Subject: [PATCH] fix: ensure integer bomref discrimination The discriminator previously used str(random()) pieces, which could emit scientific notation (e.g. 4.1e-05) and generate invalid BOM ref fragments. Switch to uuid4().int for each segment so we always produce integer-only values while maintaining uniqueness. Add a regression test to lock the BomRef.. format. uuid4() gives ~122 bits of entropy (non-crypto), compared to ~53 bits from random.random(), and the prior decimal-string slicing wasted some of those bits while allowing scientific notation. Signed-off-by: Quentin Kaiser --- cyclonedx/output/__init__.py | 4 ++-- tests/test_output.py | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cyclonedx/output/__init__.py b/cyclonedx/output/__init__.py index 95f66e0e..042dd80f 100644 --- a/cyclonedx/output/__init__.py +++ b/cyclonedx/output/__init__.py @@ -25,8 +25,8 @@ from abc import ABC, abstractmethod from collections.abc import Iterable, Mapping from itertools import chain -from random import random from typing import TYPE_CHECKING, Any, Literal, Optional, Union, overload +from uuid import uuid4 from ..schema import OutputFormat, SchemaVersion @@ -166,7 +166,7 @@ def reset(self) -> None: bomref.value = original_value def _make_unique(self) -> str: - return f'{self._prefix}{str(random())[1:]}{str(random())[1:]}' # nosec B311 + return f'{self._prefix}.{uuid4().int}.{uuid4().int}' @classmethod def from_bom(cls, bom: 'Bom', prefix: str = 'BomRef') -> 'BomRefDiscriminator': diff --git a/tests/test_output.py b/tests/test_output.py index e29d12a3..7ecb3f28 100644 --- a/tests/test_output.py +++ b/tests/test_output.py @@ -76,3 +76,8 @@ def test_discriminate_and_reset_manually(self) -> None: discr.reset() self.assertEqual('djdlkfjdslkf', bomref1.value) self.assertEqual('djdlkfjdslkf', bomref2.value) + + def test_make_unique_generates_integers(self) -> None: + discr = BomRefDiscriminator([]) + for _ in range(1000): + self.assertRegex(discr._make_unique(), r'^BomRef\.\d+\.\d+$')