diff --git a/cve_bin_tool/sbom_manager/__init__.py b/cve_bin_tool/sbom_manager/__init__.py index 3146e3c9ec..7b0b588d25 100644 --- a/cve_bin_tool/sbom_manager/__init__.py +++ b/cve_bin_tool/sbom_manager/__init__.py @@ -3,6 +3,7 @@ from __future__ import annotations +import re from collections import defaultdict from logging import Logger from pathlib import Path @@ -44,7 +45,9 @@ def __init__( self.cvedb = CVEDB(version_check=False) def scan_file(self) -> dict[ProductInfo, TriageData]: - LOGGER.info(f"Processing SBOM {self.filename} of type {self.type.upper()}") + self.logger.debug( + f"Processing SBOM {self.filename} of type {self.type.upper()}" + ) modules = [] try: if Path(self.filename).exists(): @@ -63,16 +66,15 @@ def scan_file(self) -> dict[ProductInfo, TriageData]: # Now process list of modules to create [vendor, product, version] tuples parsed_data: list[ProductInfo] = [] for m in modules: - # Using lower to normalize product names across databases - product, version = m[0].lower(), m[1] - if version != "": - # Now add vendor to create product record.... - # print (f"Find vendor for {product} {version}") - vendor_set = self.get_vendor(product) - for vendor in vendor_set: - # if vendor is not None: - parsed_data.append(ProductInfo(vendor, product, version)) - # print(vendor,product,version) + if m and m[0]: + # Using lower to normalize product names across databases + product, version = m[0].lower(), m[1] + if version != "": + # Now add vendor to create product record.... + vendor_set = self.get_vendor(product) + for vendor in vendor_set: + # if vendor is not None: + parsed_data.append(ProductInfo(vendor, product, version)) for row in parsed_data: self.sbom_data[row]["default"] = { @@ -97,8 +99,14 @@ def get_vendor(self, product: str) -> list: vendorlist.append("UNKNOWN") return vendorlist + def is_valid_purl(self, purl_string): + """Returns true if give purl_string is a valid purl string""" + purl_pattern = r"^\w+://[\w\-.]+/[\w\-.]+(?:/[\w\-.]+)*(?:\?[\w\-.]+=[\w\-.]+(?:&[\w\-.]+=[\w\-.]+)*)?$" + return re.match(purl_pattern, purl_string) is not None + def parse_sbom(self): """parse SBOM, using PURL identifiers preferentially if found""" + # Set up SBOM parser sbom_parser = SBOMParser(sbom_type=self.type) # Load SBOM @@ -121,11 +129,14 @@ def parse_sbom(self): if ext_ref is not None: for ref in ext_ref: if ref[1] == "purl": - # Process purl identifier - purl_info = PackageURL.from_string(ref[2]).to_dict() - if purl_info["name"] and purl_info["version"]: - modules.append([purl_info["name"], purl_info["version"]]) - purl_found = True + if self.is_valid_purl(ref[2]): + # Process purl identifier + purl_info = PackageURL.from_string(ref[2]).to_dict() + if purl_info["name"] and purl_info["version"]: + modules.append( + [purl_info["name"], purl_info["version"]] + ) + purl_found = True if not purl_found: if package.get("version") is not None: modules.append([package["name"], package["version"]]) diff --git a/test/test_cli.py b/test/test_cli.py index 110ac716f0..1ba56292ee 100644 --- a/test/test_cli.py +++ b/test/test_cli.py @@ -623,7 +623,7 @@ def test_SBOM(self, caplog): assert ( "cve_bin_tool", logging.INFO, - "There are 1 products with known CVEs detected", + "There are 3 products with known CVEs detected", ) in caplog.record_tuples def test_sbom_detection(self, caplog):