Skip to content

Commit a8d9eeb

Browse files
feat: Add mapping of vulnerable libraries to components (Fixed #1657) (#1658)
1 parent 5b7a93d commit a8d9eeb

File tree

3 files changed

+113
-9
lines changed

3 files changed

+113
-9
lines changed

cve_bin_tool/output_engine/__init__.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from .util import (
2121
add_extension_if_not,
2222
format_output,
23+
format_path,
2324
generate_filename,
2425
get_cve_summary,
2526
intermediate_output,
@@ -299,7 +300,64 @@ def output_pdf(
299300
pdfdoc.showtable(
300301
"Productlist", widths=[3 * cm, 3 * cm, 2 * cm, 4 * cm, 5 * cm]
301302
)
302-
pdfdoc.paragraph("* vendors guessed by the tool") if star_warn else None
303+
pdfdoc.paragraph("* vendors guessed by the tool") if star_warn else None
304+
305+
pdfdoc.heading(1, "List of Vulnerabilities mapped to Components")
306+
pdfdoc.paragraph(
307+
"The following vulnerabilities are reported against the identified components which contain the reported libraries."
308+
)
309+
pdfdoc.createtable(
310+
"Applicationlist",
311+
["Vendor", "Product", "Version", "Root", "Filename"],
312+
pdfdoc.tblStyle,
313+
[10, 10, None, None, None],
314+
)
315+
row = 1
316+
star_warn = False
317+
application_elements = []
318+
for product_info, cve_data in all_cve_data.items():
319+
for cve in cve_data["cves"]:
320+
if cve.cve_number != "UNKNOWN":
321+
if "*" in product_info.vendor:
322+
star_warn = True
323+
324+
path_elements = ", ".join(cve_data["paths"])
325+
for path_element in path_elements.split(","):
326+
path_root = format_path(cve_data["paths"])
327+
path_entry = {
328+
"vendor": product_info.vendor,
329+
"product": product_info.product,
330+
"version": product_info.version,
331+
"root": path_root[0],
332+
"filename": path_root[1],
333+
}
334+
if path_entry not in application_elements:
335+
application_elements.append(path_entry)
336+
pdfdoc.addrow(
337+
"Applicationlist",
338+
path_entry,
339+
[
340+
(
341+
"TEXTCOLOR",
342+
(0, row),
343+
(2, row),
344+
pdfdoc.black,
345+
),
346+
("FONT", (0, row), (2, row), "Helvetica"),
347+
(
348+
"TEXTCOLOR",
349+
(3, row),
350+
(4, row),
351+
severity_colour[cve.severity.upper()],
352+
),
353+
("FONT", (3, row), (4, row), "Helvetica-Bold"),
354+
],
355+
)
356+
row += 1
357+
358+
pdfdoc.showtable(
359+
"Applicationlist", widths=[3 * cm, 3 * cm, 2 * cm, 4 * cm, 3 * cm]
360+
)
303361

304362
pdfdoc.pagebreak()
305363
pdfdoc.paragraph("END OF DOCUMENT.")

cve_bin_tool/output_engine/console.py

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
# Copyright (C) 2021 Intel Corporation
22
# SPDX-License-Identifier: GPL-3.0-or-later
33

4-
from __future__ import annotations
5-
64
import textwrap
75
from collections import defaultdict
86
from datetime import datetime
9-
from typing import Any, DefaultDict
7+
from typing import Any, DefaultDict, Dict
108

119
from rich.console import Console
1210
from rich.markdown import Markdown
@@ -20,7 +18,7 @@
2018
from ..theme import cve_theme
2119
from ..util import ProductInfo, VersionInfo
2220
from ..version import VERSION
23-
from .util import get_cve_summary
21+
from .util import format_path, get_cve_summary
2422

2523

2624
def format_version_range(version_info: VersionInfo) -> str:
@@ -80,9 +78,9 @@ def output_console(*args: Any):
8078

8179

8280
def _output_console_nowrap(
83-
all_cve_data: dict[ProductInfo, CVEData],
84-
all_cve_version_info: dict[str, VersionInfo],
85-
time_of_last_update: datetime | str,
81+
all_cve_data: Dict[ProductInfo, CVEData],
82+
all_cve_version_info: Dict[str, VersionInfo],
83+
time_of_last_update: datetime,
8684
affected_versions: int,
8785
exploits: bool = False,
8886
console: Console = Console(theme=cve_theme),
@@ -138,7 +136,8 @@ def _output_console_nowrap(
138136
console.print(table)
139137

140138
cve_by_remarks: DefaultDict[Remarks, list[dict[str, str]]] = defaultdict(list)
141-
# group cve_data by its remarks
139+
cve_by_paths: DefaultDict[Remarks, list[dict[str, str]]] = defaultdict(list)
140+
# group cve_data by its remarks and separately by paths
142141
for product_info, cve_data in all_cve_data.items():
143142
for cve in cve_data["cves"]:
144143
cve_by_remarks[cve.remarks].append(
@@ -152,6 +151,16 @@ def _output_console_nowrap(
152151
"cvss_version": cve.cvss_version,
153152
}
154153
)
154+
path_elements = ", ".join(cve_data["paths"])
155+
for path_element in path_elements.split(","):
156+
path_entry = {
157+
"vendor": product_info.vendor,
158+
"product": product_info.product,
159+
"version": product_info.version,
160+
"paths": path_element,
161+
}
162+
if path_entry not in cve_by_paths[cve.remarks]:
163+
cve_by_paths[cve.remarks].append(path_entry)
155164
if affected_versions != 0:
156165
try:
157166
version_info = all_cve_version_info[cve.cve_number]
@@ -203,3 +212,32 @@ def _output_console_nowrap(
203212
if "*" in cve_data["vendor"]:
204213
console.print("* vendors guessed by the tool")
205214
break
215+
216+
# Show table of vulnerable products mapped to filename paths
217+
for remarks in sorted(cve_by_paths):
218+
color = "yellow"
219+
console.print(
220+
Panel(f"[{color}] {remarks.name} CVEs [/{color}]", expand=False)
221+
)
222+
# Table instance
223+
table = Table()
224+
225+
# Add Head Columns to the Table
226+
table.add_column("Vendor")
227+
table.add_column("Product")
228+
table.add_column("Version")
229+
table.add_column("Root")
230+
table.add_column("Filename")
231+
color = "green"
232+
for cve_data in cve_by_paths[remarks]:
233+
path_root = format_path(cve_data["paths"])
234+
cells = [
235+
Text.styled(cve_data["vendor"], color),
236+
Text.styled(cve_data["product"], color),
237+
Text.styled(cve_data["version"], color),
238+
Text.styled(path_root[0], color),
239+
Text.styled(path_root[1], color),
240+
]
241+
table.add_row(*cells)
242+
# Print the table to the console
243+
console.print(table)

cve_bin_tool/output_engine/util.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,11 @@ def group_cve_by_remark(
211211
}
212212
)
213213
return cve_by_remarks
214+
215+
216+
def format_path(path_element: str) -> List[str]:
217+
"""Extract filenames from path element"""
218+
path = path_element.split(" contains ")
219+
if len(path) > 1:
220+
return [os.path.basename(path[0]), os.path.basename(path[1])]
221+
return [os.path.basename(path[0]), " - "]

0 commit comments

Comments
 (0)