Skip to content

feat: OutputEngine updates for no-scan #5195

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 6 additions & 1 deletion cve_bin_tool/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import textwrap
import time
from collections import ChainMap
from datetime import datetime
from pathlib import Path

from cve_bin_tool.available_fix import (
Expand Down Expand Up @@ -1091,6 +1092,7 @@ def main(argv=None):
check_exploits=args["exploits"],
exploits_list=cvedb_orig.get_exploits_list(),
disabled_sources=disabled_sources,
no_scan=args["no_scan"],
) as cve_scanner:
triage_data: TriageData
total_files: int = 0
Expand Down Expand Up @@ -1267,7 +1269,9 @@ def main(argv=None):
scanned_dir=args["directory"],
filename=args["output_file"],
themes_dir=args["html_theme"],
time_of_last_update=cvedb_orig.time_of_last_update,
time_of_last_update=(
cvedb_orig.time_of_last_update if cvedb_orig else datetime.now()
),
tag=args["tag"],
products_with_cve=cve_scanner.products_with_cve,
products_without_cve=cve_scanner.products_without_cve,
Expand All @@ -1290,6 +1294,7 @@ def main(argv=None):
sbom_root=sbom_root,
strip_scan_dir=args["strip_scan_dir"],
offline=args["offline"],
no_scan=args["no_scan"],
)

if not args["quiet"]:
Expand Down
43 changes: 31 additions & 12 deletions cve_bin_tool/cve_scanner.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,22 @@ def __init__(
check_exploits: bool = False,
exploits_list: List[str] = [],
disabled_sources: List[str] = [],
no_scan: bool = False,
):
self.logger = logger or LOGGER.getChild(self.__class__.__name__)
self.error_mode = error_mode
self.score = score
self.check_metrics = check_metrics
self.epss_percentile = epss_percentile
self.epss_probability = epss_probability
self.products_with_cve = 0
self.products_without_cve = 0
self.all_cve_data = defaultdict(CVEData)
self.all_cve_version_info = dict()
self.logger = logger or LOGGER.getChild(self.__class__.__name__)
self.error_mode = error_mode
self.check_exploits = check_exploits
self.exploits_list = exploits_list
self.disabled_sources = disabled_sources
self.no_scan = no_scan
self.products_with_cve = 0
self.products_without_cve = 0
self.all_cve_data = defaultdict(lambda: {"cves": [], "paths": set()})
self.all_cve_version_info = dict()
self.all_product_data = dict()

def get_cves(self, product_info: ProductInfo, triage_data: TriageData):
Expand All @@ -74,6 +76,21 @@ def get_cves(self, product_info: ProductInfo, triage_data: TriageData):
if self.score > 10 or self.epss_probability > 1.0 or self.epss_percentile > 1.0:
return

# Handle no-scan mode
if self.no_scan:
# In no-scan mode, just populate the product data without CVE scanning
if product_info not in self.all_product_data:
self.logger.debug(f"Add product {product_info} (no-scan mode)")
self.all_product_data[product_info] = 0

# Also populate all_cve_data with empty CVE list and paths
if product_info not in self.all_cve_data:
self.all_cve_data[product_info] = {"cves": [], "paths": set()}

# Update paths
self.all_cve_data[product_info]["paths"] |= set(triage_data["paths"])
return

if product_info.vendor == "UNKNOWN":
# Add product
if product_info not in self.all_product_data:
Expand Down Expand Up @@ -298,7 +315,7 @@ def get_cves(self, product_info: ProductInfo, triage_data: TriageData):
self.epss_percentile,
self.epss_probability,
)
# row_dict doesnt have metric as key. As it based on result from query on
# row_dict doesn't have metric as key. As it based on result from query on
# cve_severity table declaring row_dict[metric]
row_dict["metric"] = {}
# looping for result of query for metrics.
Expand Down Expand Up @@ -481,9 +498,10 @@ def __enter__(self):
Returns:
CVEScanner: The instance of the CVEScanner with an active database connection.
"""
self.connection = sqlite3.connect(self.dbname)
self.connection.row_factory = sqlite3.Row
self.cursor = self.connection.cursor()
if not self.no_scan:
self.connection = sqlite3.connect(self.dbname)
self.connection.row_factory = sqlite3.Row
self.cursor = self.connection.cursor()
return self

def __exit__(self, exc_type, exc_val, exc_tb):
Expand All @@ -498,5 +516,6 @@ def __exit__(self, exc_type, exc_val, exc_tb):
Returns:
None
"""
self.cursor.close()
self.connection.close()
if not self.no_scan and hasattr(self, "cursor") and hasattr(self, "connection"):
self.cursor.close()
self.connection.close()
5 changes: 4 additions & 1 deletion cve_bin_tool/output_engine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,7 @@ def output_pdf(

class OutputEngine:
"""
Class represention of OutputEngine
Class representation of OutputEngine
Attributes:
all_cve_data (dict[ProductInfo, CVEData])
scanned_dir (str)
Expand Down Expand Up @@ -693,6 +693,7 @@ def __init__(
vex_product_info: dict[str, str] = {},
offline: bool = False,
organized_arguements: dict = None,
no_scan: bool = False,
):
"""Constructor for OutputEngine class."""
self.logger = logger or LOGGER.getChild(self.__class__.__name__)
Expand Down Expand Up @@ -726,6 +727,7 @@ def __init__(
self.vex_type = vex_type
self.vex_product_info = vex_product_info
self.vex_filename = vex_filename
self.no_scan = no_scan

def output_cves(self, outfile, output_type="console"):
"""Output a list of CVEs
Expand Down Expand Up @@ -812,6 +814,7 @@ def output_cves(self, outfile, output_type="console"):
self.offline,
None,
outfile,
self.no_scan,
)

if isinstance(self.append, str):
Expand Down
Loading
Loading