1616#
1717# SPDX-License-Identifier: Apache-2.0
1818# Copyright (c) OWASP Foundation. All Rights Reserved.
19+
1920import warnings
2021from datetime import datetime , timezone
2122from typing import Iterable , Optional
2627from ..exception .model import UnknownComponentDependencyException
2728from ..parser import BaseParser
2829from . import ExternalReference , LicenseChoice , OrganizationalContact , OrganizationalEntity , Property , ThisTool , Tool
30+ from .bom_ref import BomRef
2931from .component import Component
3032from .service import Service
33+ from .vulnerability import Vulnerability
3134
3235
3336class BomMetaData :
@@ -242,6 +245,7 @@ def __init__(self, *, components: Optional[Iterable[Component]] = None,
242245 self .components = components or [] # type: ignore
243246 self .services = services or [] # type: ignore
244247 self .external_references = external_references or [] # type: ignore
248+ self .vulnerabilities = SortedSet ()
245249
246250 @property
247251 def uuid (self ) -> UUID :
@@ -356,15 +360,46 @@ def external_references(self) -> "SortedSet[ExternalReference]":
356360 def external_references (self , external_references : Iterable [ExternalReference ]) -> None :
357361 self ._external_references = SortedSet (external_references )
358362
363+ def get_vulnerabilities_for_bom_ref (self , bom_ref : BomRef ) -> "SortedSet[Vulnerability]" :
364+ """
365+ Get all known Vulnerabilities that affect the supplied bom_ref.
366+
367+ Args:
368+ bom_ref: `BomRef`
369+
370+ Returns:
371+ `SortedSet` of `Vulnerability`
372+ """
373+
374+ vulnerabilities : SortedSet [Vulnerability ] = SortedSet ()
375+ for v in self .vulnerabilities :
376+ for target in v .affects :
377+ if target .ref == bom_ref .value :
378+ vulnerabilities .add (v )
379+ return vulnerabilities
380+
359381 def has_vulnerabilities (self ) -> bool :
360382 """
361383 Check whether this Bom has any declared vulnerabilities.
362384
363385 Returns:
364- `bool` - `True` if at least one `cyclonedx.model.component.Component` has at least one Vulnerability,
365- `False` otherwise.
386+ `bool` - `True` if this Bom has at least one Vulnerability, `False` otherwise.
387+ """
388+ return bool (self .vulnerabilities )
389+
390+ @property
391+ def vulnerabilities (self ) -> "SortedSet[Vulnerability]" :
392+ """
393+ Get all the Vulnerabilities in this BOM.
394+
395+ Returns:
396+ Set of `Vulnerability`
366397 """
367- return any (c .has_vulnerabilities () for c in self .components )
398+ return self ._vulnerabilities
399+
400+ @vulnerabilities .setter
401+ def vulnerabilities (self , vulnerabilities : Iterable [Vulnerability ]) -> None :
402+ self ._vulnerabilities = SortedSet (vulnerabilities )
368403
369404 def validate (self ) -> bool :
370405 """
@@ -389,7 +424,7 @@ def validate(self) -> bool:
389424 # 2. Dependencies should exist for the Component this BOM is describing, if one is set
390425 if self .metadata .component and not self .metadata .component .dependencies :
391426 warnings .warn (
392- f'The Component this BOM is describing { self .metadata .component .purl } has no defined dependencies'
427+ f'The Component this BOM is describing { self .metadata .component .purl } has no defined dependencies '
393428 f'which means the Dependency Graph is incomplete - you should add direct dependencies to this Component'
394429 f'to complete the Dependency Graph data.' ,
395430 UserWarning
0 commit comments