Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
f6430ec
feat: prepare "contrib" area
jkowalleck Nov 26, 2025
a8a4190
feat: prepare "contrib" area
jkowalleck Nov 27, 2025
0e68f6e
feat: prepare "contrib" area
jkowalleck Nov 27, 2025
3c2ad7d
feat: prepare "contrib" area
jkowalleck Nov 28, 2025
3947eb7
feat: prepare "contrib" area
jkowalleck Nov 28, 2025
885d47e
feat: prepare "contrib" area
jkowalleck Nov 28, 2025
bd37a9e
feat: prepare "contrib" area
jkowalleck Nov 28, 2025
119690d
feat: prepare "contrib" area
jkowalleck Nov 28, 2025
562049c
feat: prepare "contrib" area
jkowalleck Nov 28, 2025
ef83a07
feat: prepare "contrib" area
jkowalleck Nov 28, 2025
7d14191
feat: prepare "contrib" area
jkowalleck Nov 28, 2025
b88d831
feat: prepare "contrib" area
jkowalleck Nov 28, 2025
28b94a7
feat: prepare "contrib" area
jkowalleck Nov 28, 2025
66d199c
feat: prepare "contrib" area
jkowalleck Nov 28, 2025
c1abdc3
feat: prep contrib
jkowalleck Nov 30, 2025
f8c43e6
feat: prepare "contrib" area
jkowalleck Nov 30, 2025
c0ca9bc
feat: prepare "contrib" area
jkowalleck Dec 1, 2025
be8d607
feat: prepare "contrib" area
jkowalleck Dec 1, 2025
840fbd4
feat: prepare "contrib" area
jkowalleck Dec 1, 2025
f61abe9
feat: prepare "contrib" area
jkowalleck Dec 1, 2025
5b98ab4
feat: prepare "contrib" area
jkowalleck Dec 1, 2025
07c2a70
feat: prepare "contrib" area
jkowalleck Dec 1, 2025
0e36aac
feat: prepare "contrib" area
jkowalleck Dec 1, 2025
bccb7e3
feat: prepare "contrib" area
jkowalleck Dec 1, 2025
ff0e11d
typos
jkowalleck Dec 2, 2025
9436747
typos
jkowalleck Dec 2, 2025
0d0443d
typos
jkowalleck Dec 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat: prepare "contrib" area
Signed-off-by: Jan Kowalleck <jan.kowalleck@gmail.com>
  • Loading branch information
jkowalleck committed Dec 1, 2025
commit be8d60734362bfc0f219dd1e1a9304f5cc0bd5ca
5 changes: 3 additions & 2 deletions cyclonedx/contrib/component/builders.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@


from hashlib import sha1
from typing import Optional
from os.path import exists
from typing import Optional

from ...model import HashType, HashAlgorithm
from ...model import HashAlgorithm, HashType
from ...model.component import Component, ComponentType


class ComponentBuilder:

def make_for_file(self, absolute_file_path: str, *,
Expand Down
6 changes: 2 additions & 4 deletions cyclonedx/contrib/hash/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,8 @@

__all__ = ['HashTypeFactory']

from ...model import HashType, HashAlgorithm

from ...exception.model import UnknownHashTypeException


from ...model import HashAlgorithm, HashType

_MAP_HASHLIB: dict[str, HashAlgorithm] = {
# from hashlib.algorithms_guaranteed
Expand All @@ -43,6 +40,7 @@
# shake_256:
}


class HashTypeFactory:

def from_hashlib_alg(self, hashlib_alg: str, content: str) -> HashType:
Expand Down
18 changes: 18 additions & 0 deletions cyclonedx/contrib/vulnerability/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# This file is part of CycloneDX Python Library
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) OWASP Foundation. All Rights Reserved.

"""Vulnerability related functionality"""
58 changes: 58 additions & 0 deletions cyclonedx/contrib/vulnerability/cvss.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# This file is part of CycloneDX Python Library
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) OWASP Foundation. All Rights Reserved.

"""CVSS related utilities"""

__all__ = ['vs_from_cvss_scores']

from typing import Union

from ...model.vulnerability import VulnerabilitySeverity


def vs_from_cvss_scores(scores: Union[tuple[float, ...], float, None]) -> VulnerabilitySeverity:
"""
Derives the Severity of a Vulnerability from it's declared CVSS scores.

Args:
scores: A `tuple` of CVSS scores. CVSS scoring system allows for up to three separate scores.

Returns:
Always returns an instance of :class:`cyclonedx.model.vulnerability.VulnerabilitySeverity`.
"""
if type(scores) is float:
scores = (scores,)

if scores is None:
return VulnerabilitySeverity.UNKNOWN

max_cvss_score: float
if isinstance(scores, tuple):
max_cvss_score = max(scores)
else:
max_cvss_score = float(scores)

if max_cvss_score >= 9.0:
return VulnerabilitySeverity.CRITICAL
elif max_cvss_score >= 7.0:
return VulnerabilitySeverity.HIGH
elif max_cvss_score >= 4.0:
return VulnerabilitySeverity.MEDIUM
elif max_cvss_score > 0.0:
return VulnerabilitySeverity.LOW
else:
return VulnerabilitySeverity.NONE
2 changes: 1 addition & 1 deletion cyclonedx/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from typing import Any, Optional, Union
from urllib.parse import quote as url_quote
from uuid import UUID
from warnings import warn, deprecated
from warnings import deprecated, warn
from xml.etree.ElementTree import Element as XmlElement # nosec B405

import py_serializable as serializable
Expand Down
18 changes: 18 additions & 0 deletions cyclonedx/model/bom.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import py_serializable as serializable
from sortedcontainers import SortedSet
from typing_extensions import deprecated

from .._internal.compare import ComparableTuple as _ComparableTuple
from .._internal.time import get_now_utc as _get_now_utc
Expand Down Expand Up @@ -706,6 +707,8 @@ def get_component_by_purl(self, purl: Optional['PackageURL']) -> Optional[Compon

Returns:
`Component` or `None`

.. deprecated:: next
"""
if purl:
found = [x for x in self.components if x.purl == purl]
Expand All @@ -720,6 +723,8 @@ def get_urn_uuid(self) -> str:

Returns:
URN formatted UUID that uniquely identified this Bom instance.

.. deprecated:: next
"""
return self.serial_number.urn

Expand All @@ -733,6 +738,8 @@ def has_component(self, component: Component) -> bool:

Returns:
`bool` - `True` if the supplied Component is part of this Bom, `False` otherwise.

.. deprecated:: next
"""
return component in self.components

Expand All @@ -751,6 +758,8 @@ def get_vulnerabilities_for_bom_ref(self, bom_ref: BomRef) -> 'SortedSet[Vulnera

Returns:
`SortedSet` of `Vulnerability`

.. deprecated:: next
"""

vulnerabilities: SortedSet[Vulnerability] = SortedSet()
Expand All @@ -766,6 +775,8 @@ def has_vulnerabilities(self) -> bool:

Returns:
`bool` - `True` if this Bom has at least one Vulnerability, `False` otherwise.

.. deprecated:: next
"""
return bool(self.vulnerabilities)

Expand All @@ -788,6 +799,10 @@ def register_dependency(self, target: Dependable, depends_on: Optional[Iterable[
self.register_dependency(target=_d2, depends_on=None)

def urn(self) -> str:
"""
.. deprecated:: next
"""
# idea: have 'serial_number' be a string, and use it instead of this method
return f'{_BOM_LINK_PREFIX}{self.serial_number}/{self.version}'

def validate(self) -> bool:
Expand All @@ -797,7 +812,10 @@ def validate(self) -> bool:

Returns:
`bool`

.. deprecated:: next
"""
# !! deprecated function. have this as an part of the normlization process, like the BomRefDiscrimator
# 0. Make sure all Dependable have a Dependency entry
if self.metadata.component:
self.register_dependency(target=self.metadata.component)
Expand Down
7 changes: 4 additions & 3 deletions cyclonedx/model/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,12 @@
from . import (
AttachedText,
ExternalReference,
HashAlgorithm,
HashType,
IdentifiableAction,
Property,
XsUri,
_HashTypeRepositorySerializationHelper, HashAlgorithm,
_HashTypeRepositorySerializationHelper,
)
from .bom_ref import BomRef
from .component_evidence import ComponentEvidence, _ComponentEvidenceSerializationHelper
Expand Down Expand Up @@ -966,8 +967,8 @@ def for_file(absolute_file_path: str, path_for_bom: Optional[str]) -> 'Component

component = ComponentBuilder().make_for_file(absolute_file_path, name=path_for_bom)
sha1_hash = next(h.content for h in component.hashes if h.alg is HashAlgorithm.SHA_1)
component.version=f'0.0.0-{sha1_hash[0:12]}'
component.purl=PackageURL( # DEPRECATED: a file has no PURL!
component.version = f'0.0.0-{sha1_hash[0:12]}'
component.purl = PackageURL( # DEPRECATED: a file has no PURL!
type='generic', name=path_for_bom if path_for_bom else absolute_file_path,
version=f'0.0.0-{sha1_hash[0:12]}'
)
Expand Down
6 changes: 5 additions & 1 deletion cyclonedx/model/license.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ class LicenseAcknowledgement(str, Enum):
# In an error, the name of the enum was `LicenseExpressionAcknowledgement`.
# Even though this was changed, there might be some downstream usage of this symbol, so we keep it around ...
LicenseExpressionAcknowledgement = LicenseAcknowledgement
"""Deprecated alias for :class:`LicenseAcknowledgement`"""
"""Deprecated - Alias for :class:`LicenseAcknowledgement`

.. deprecated:: next Import `LicenseAcknowledgement` instead.
The exported original symbol itself is NOT deprecated - only this import path.
"""


@serializable.serializable_class(
Expand Down
37 changes: 9 additions & 28 deletions cyclonedx/model/vulnerability.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

import py_serializable as serializable
from sortedcontainers import SortedSet
from typing_extensions import deprecated

from .._internal.bom_ref import bom_ref_from_str as _bom_ref_from_str
from .._internal.compare import ComparableTuple as _ComparableTuple
Expand Down Expand Up @@ -724,38 +725,18 @@ class VulnerabilitySeverity(str, Enum):
UNKNOWN = 'unknown'

@staticmethod
@deprecated('Deprecated - use cyclonedx.contrib.vulnerability.cvss.vs_from_cvss_scores instead')
def get_from_cvss_scores(scores: Union[tuple[float, ...], float, None]) -> 'VulnerabilitySeverity':
"""
"""Deprecated — Alias of :func:`cyclonedx.contrib.vulnerability.cvss.vs_from_cvss_scores()`.

Derives the Severity of a Vulnerability from it's declared CVSS scores.

Args:
scores: A `tuple` of CVSS scores. CVSS scoring system allows for up to three separate scores.
.. deprecated:: next
Use ``cyclonedx.contrib.vulnerability.cvss.VulnerabilitySeverity_from_cvss_scores()`` instead.
"""
from ..contrib.vulnerability.cvss import vs_from_cvss_scores

Returns:
Always returns an instance of `VulnerabilitySeverity`.
"""
if type(scores) is float:
scores = (scores,)

if scores is None:
return VulnerabilitySeverity.UNKNOWN

max_cvss_score: float
if isinstance(scores, tuple):
max_cvss_score = max(scores)
else:
max_cvss_score = float(scores)

if max_cvss_score >= 9.0:
return VulnerabilitySeverity.CRITICAL
elif max_cvss_score >= 7.0:
return VulnerabilitySeverity.HIGH
elif max_cvss_score >= 4.0:
return VulnerabilitySeverity.MEDIUM
elif max_cvss_score > 0.0:
return VulnerabilitySeverity.LOW
else:
return VulnerabilitySeverity.NONE
return vs_from_cvss_scores(scores)


@serializable.serializable_class(ignore_unknown_during_deserialization=True)
Expand Down
Loading