From f81d6bbafdb1b9d307e116135906573642174b98 Mon Sep 17 00:00:00 2001 From: saquibsaifee Date: Tue, 1 Sep 2026 17:34:40 -0400 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9A=A1=20Optimize=20get=5Flocalised=5Fve?= =?UTF-8?q?ctor=20with=20pre-compiled=20regex?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: saquibsaifee --- cyclonedx/model/vulnerability.py | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/cyclonedx/model/vulnerability.py b/cyclonedx/model/vulnerability.py index 5f3bf0240..1fc23673a 100644 --- a/cyclonedx/model/vulnerability.py +++ b/cyclonedx/model/vulnerability.py @@ -36,14 +36,6 @@ from enum import Enum from typing import Any, Optional, Union -if sys.version_info >= (3, 13): - from warnings import deprecated -else: - from typing_extensions import deprecated - -import py_serializable as serializable -from sortedcontainers import SortedSet - from .._internal.bom_ref import bom_ref_from_str as _bom_ref_from_str from .._internal.compare import ComparableTuple as _ComparableTuple from ..exception.model import MutuallyExclusivePropertiesException, NoPropertiesProvidedException @@ -59,6 +51,19 @@ ) from .tool import Tool, ToolRepository, _ToolRepositoryHelper +if sys.version_info >= (3, 13): + from warnings import deprecated +else: + from typing_extensions import deprecated + +import py_serializable as serializable +from sortedcontainers import SortedSet + +_RE_CVSS_V4 = re.compile(r'^CVSS:4\.\d/?') +_RE_CVSS_V3 = re.compile(r'^CVSS:3\.\d/?') +_RE_CVSS_V2 = re.compile(r'^CVSS:2\.\d/?') +_RE_OWASP = re.compile(r'^OWASP/?') + @serializable.serializable_class(ignore_unknown_during_deserialization=True) class BomTargetVersionRange: @@ -643,15 +648,15 @@ def get_localised_vector(self, vector: str) -> str: The vector without any scheme prefix as a `str`. """ if self is VulnerabilityScoreSource.CVSS_V4 and vector.startswith('CVSS:4.'): - return re.sub(r'^CVSS:4\.\d/?', '', vector) + return _RE_CVSS_V4.sub('', vector) if ( self in (VulnerabilityScoreSource.CVSS_V3_1, VulnerabilityScoreSource.CVSS_V3) ) and vector.startswith('CVSS:3.'): - return re.sub(r'^CVSS:3\.\d/?', '', vector) + return _RE_CVSS_V3.sub('', vector) if self is VulnerabilityScoreSource.CVSS_V2 and vector.startswith('CVSS:2.'): - return re.sub(r'^CVSS:2\.\d/?', '', vector) + return _RE_CVSS_V2.sub('', vector) if self is VulnerabilityScoreSource.OWASP and vector.startswith('OWASP'): - return re.sub(r'^OWASP/?', '', vector) + return _RE_OWASP.sub('', vector) return vector def get_value_pre_1_4(self) -> str: From 276cfe4d8de86dd3e427beaaee7af27f58a4786f Mon Sep 17 00:00:00 2001 From: Saquib Saifee Date: Tue, 15 Sep 2026 23:55:20 -0400 Subject: [PATCH 2/2] Refactor regex patterns and imports in vulnerability.py Refactor vulnerability.py to use version-specific regex patterns for CVSS and OWASP vectors, and clean up deprecated imports. Signed-off-by: Saquib Saifee --- cyclonedx/model/vulnerability.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/cyclonedx/model/vulnerability.py b/cyclonedx/model/vulnerability.py index 1fc23673a..19ac077ee 100644 --- a/cyclonedx/model/vulnerability.py +++ b/cyclonedx/model/vulnerability.py @@ -36,6 +36,14 @@ from enum import Enum from typing import Any, Optional, Union +if sys.version_info >= (3, 13): + from warnings import deprecated +else: + from typing_extensions import deprecated + +import py_serializable as serializable +from sortedcontainers import SortedSet + from .._internal.bom_ref import bom_ref_from_str as _bom_ref_from_str from .._internal.compare import ComparableTuple as _ComparableTuple from ..exception.model import MutuallyExclusivePropertiesException, NoPropertiesProvidedException @@ -51,18 +59,11 @@ ) from .tool import Tool, ToolRepository, _ToolRepositoryHelper -if sys.version_info >= (3, 13): - from warnings import deprecated -else: - from typing_extensions import deprecated - -import py_serializable as serializable -from sortedcontainers import SortedSet -_RE_CVSS_V4 = re.compile(r'^CVSS:4\.\d/?') -_RE_CVSS_V3 = re.compile(r'^CVSS:3\.\d/?') -_RE_CVSS_V2 = re.compile(r'^CVSS:2\.\d/?') -_RE_OWASP = re.compile(r'^OWASP/?') +_VSS_VECTOR_RE_CVSS_V4 = re.compile(r'^CVSS:4\.\d/?') +_VSS_VECTOR_RE_CVSS_V3 = re.compile(r'^CVSS:3\.\d/?') +_VSS_VECTOR_RE_CVSS_V2 = re.compile(r'^CVSS:2\.\d/?') +_VSS_VECTOR_RE_OWASP = re.compile(r'^OWASP/?') @serializable.serializable_class(ignore_unknown_during_deserialization=True) @@ -648,15 +649,15 @@ def get_localised_vector(self, vector: str) -> str: The vector without any scheme prefix as a `str`. """ if self is VulnerabilityScoreSource.CVSS_V4 and vector.startswith('CVSS:4.'): - return _RE_CVSS_V4.sub('', vector) + return _VSS_VECTOR_RE_CVSS_V4.sub('', vector) if ( self in (VulnerabilityScoreSource.CVSS_V3_1, VulnerabilityScoreSource.CVSS_V3) ) and vector.startswith('CVSS:3.'): - return _RE_CVSS_V3.sub('', vector) + return _VSS_VECTOR.sub('', vector) if self is VulnerabilityScoreSource.CVSS_V2 and vector.startswith('CVSS:2.'): - return _RE_CVSS_V2.sub('', vector) + return _VSS_VECTOR_RE_CVSS_V2.sub('', vector) if self is VulnerabilityScoreSource.OWASP and vector.startswith('OWASP'): - return _RE_OWASP.sub('', vector) + return _VSS_VECTOR_RE_OWASP.sub('', vector) return vector def get_value_pre_1_4(self) -> str: