Coverage for /home/benjarobin/Bootlin/projects/Schneider-Electric-Senux/sbom-cve-check/src/sbom_cve_check/cve_db/annot_spdx2.py: 52%
56 statements
« prev ^ index » next coverage.py v7.11.1, created at 2025-11-28 15:37 +0100
« prev ^ index » next coverage.py v7.11.1, created at 2025-11-28 15:37 +0100
1# -*- coding: utf-8 -*-
2# SPDX-License-Identifier: GPL-2.0-only
4import re
5from collections.abc import Generator, Iterable
6from datetime import datetime
7from typing import Any
9from ..sbom import sbom_spdx2
10from ..sbom.component import CompId
11from ..vuln.cpe import Cpe23
12from ..vuln.cve import (
13 CveId,
14 CveVexAssessment,
15 CveVexFixedAssessment,
16)
17from ..vuln.version import SemVerRange
18from .annot_base import AnnotDatabase, AnnotDbEntry
19from .db_base import CveDatabase
22class Spdx2AnnotEntry(AnnotDbEntry):
23 def __init__(
24 self,
25 parent_db: CveDatabase,
26 cve_id: CveId,
27 cpes: set[Cpe23],
28 pkg_version: str | None,
29 ) -> None:
30 super().__init__(parent_db)
31 self._cve_id = cve_id
32 self._cpes = cpes
33 self._pkg_version = pkg_version
35 def add_cpes(self, cpes: Iterable[Cpe23]) -> None:
36 self._cpes.update(cpes)
38 @property
39 def identifier(self) -> CveId:
40 return self._cve_id
42 @property
43 def date_modified(self) -> datetime | None:
44 return None
46 @property
47 def description(self) -> str | None:
48 return None
50 @property
51 def vex_assessment(self) -> CveVexAssessment | None:
52 return CveVexFixedAssessment(vex_version="1.0", status_notes="patched")
54 def _iterate_cpes(self, pkg: Any) -> Generator[Cpe23, None, None]:
55 yield from self._cpes
57 def get_associated_sem_ver_ranges(
58 self, comp_ids: Iterable[CompId]
59 ) -> Iterable[SemVerRange]:
60 return self._get_associated_sem_ver_ranges(comp_ids, self._pkg_version)
63class Spdx2AnnotDatabase(AnnotDatabase):
64 def __init__(
65 self,
66 name: str,
67 sbom: "sbom_spdx2.Spdx2Sbom",
68 **kwargs: Any,
69 ) -> None:
70 super().__init__(name, **kwargs)
71 self._sbom = sbom
72 self._vulns: dict[CveId, Spdx2AnnotEntry] = {}
74 def _initialize(self) -> None:
75 re_cve = re.compile(r"CVE-[0-9]+-[0-9]+")
77 for _, recipe_pkg in self._sbom.iterate_recipes():
78 cpes = sbom_spdx2.parse_ext_refs_cpe(recipe_pkg)
79 pkg_vers: str | None = recipe_pkg.get("versionInfo")
80 source_info: str = recipe_pkg.get("sourceInfo", "")
82 for cve in re_cve.findall(source_info):
83 cve_id = CveId(cve)
84 annot = self._vulns.get(cve_id)
85 if annot:
86 annot.add_cpes(cpes)
87 else:
88 self._vulns[cve_id] = Spdx2AnnotEntry(self, cve_id, cpes, pkg_vers)
90 def get_cve(self, cve_id: CveId) -> Spdx2AnnotEntry | None:
91 return self._vulns.get(cve_id)
93 def iterate_cves(self) -> Generator[Spdx2AnnotEntry, None, None]:
94 yield from self._vulns.values()