Skip to content

Commit

Permalink
feat: include EPSS metrics in output PDF (#3213)
Browse files Browse the repository at this point in the history
* feat: output PDF

* feat: adding test case

* fix: removing bug
  • Loading branch information
Rexbeast2 authored Aug 14, 2023
1 parent 2757e66 commit a098ef0
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 1 deletion.
68 changes: 68 additions & 0 deletions cve_bin_tool/output_engine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,74 @@ def output_pdf(
"Applicationlist", widths=[3 * cm, 3 * cm, 2 * cm, 4 * cm, 3 * cm]
)

pdfdoc.heading(1, "List of Vulnerabilities with different metric")
pdfdoc.paragraph(
"The table given below gives CVE found with there score on different metrics."
)
cve_by_metrics: defaultdict[Remarks, list[dict[str, str]]] = defaultdict(
list
)
col_headings = [
"CVE Number",
"CVSS_version",
"CVSS_score",
"EPSS_propability",
"EPSS_percentile",
]
# group cve_data by its remarks and separately by paths
for product_info, cve_data in all_cve_data.items():
for cve in cve_data["cves"]:
propability = "-"
percentile = "-"
for metric, field in cve.metric.items():
if metric == "EPSS":
propability = round(field[0] * 100, 4)
percentile = field[1]

cve_by_metrics[cve.remarks].append(
{
"cve_number": cve.cve_number,
"cvss_version": str(cve.cvss_version),
"cvss_score": str(cve.score),
"epss_propability": str(propability),
"epss_percentile": str(percentile),
"severity": cve.severity,
}
)

for remarks in sorted(cve_by_metrics):
pdfdoc.createtable(
"cvemetric",
col_headings,
pdfdoc.tblStyle,
)
row = 1
for cve in cve_by_metrics[remarks]:
entry = [
cve["cve_number"],
cve["cvss_version"],
str(cve["cvss_score"]),
str(cve["epss_propability"]),
str(cve["epss_percentile"]),
]
pdfdoc.addrow(
"cvemetric",
entry,
[
(
"TEXTCOLOR",
(0, row),
(4, row),
severity_colour[cve["severity"].split("-")[0].upper()],
),
("FONT", (0, row), (4, row), "Helvetica-Bold"),
],
)
row += 1
pdfdoc.showtable(
"cvemetric", widths=[4 * cm, 4 * cm, 3 * cm, 4 * cm, 4 * cm]
)

# List of scanned products with no identified vulnerabilities
if all_product_data is not None:
pdfdoc.heading(1, "No Identified Vulnerabilities")
Expand Down
52 changes: 51 additions & 1 deletion test/test_output_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="C:H",
data_source="NVD",
metric={
"EPSS": [0.6932, "0.2938"],
},
),
CVE(
"CVE-1234-1234",
Expand All @@ -184,6 +187,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="CVSS2.0/C:H",
data_source="NVD",
metric={
"EPSS": [0.06084, "0.7936"],
},
),
],
paths={""},
Expand All @@ -198,7 +204,7 @@ class TestOutputEngine(unittest.TestCase):
cvss_vector="CVSS3.0/C:H/I:L/A:M",
data_source="NVD",
metric={
"EPSS": [0.0468, "0.34072"],
"EPSS": [0.1646, "0.3955"],
},
)
],
Expand All @@ -213,6 +219,7 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="C:H/I:L/A:M",
data_source="NVD",
metric={"EPSS": [0.2059, "0.09260"]},
)
],
paths={""},
Expand Down Expand Up @@ -665,6 +672,37 @@ class TestOutputEngine(unittest.TestCase):
"Page 2"
)

PDF_OUTPUT_2 = (
"4. List of Vulnerabilities with different metric"
"The table given below gives CVE found with there score on different metrics."
"CVE Number"
"CVSS_version"
"CVSS_score"
"EPSS_propability"
"EPSS_percentile"
"CVE-1234-1234"
"2"
"4.2"
"69.32"
"0.2938"
"CVE-1234-1234"
"2"
"1.2"
"6.084"
"0.7936"
"CVE-1234-1234"
"3"
"2.5"
"16.46"
"0.3955"
"CVE-1234-1234"
"2"
"7.5"
"20.59"
"0.09260"
"Page 3"
)

VEX_FORMATTED_OUTPUT = [
{
"bomFormat": "CycloneDX",
Expand Down Expand Up @@ -864,6 +902,7 @@ def test_output_pdf(self):
# Only interested in section 3 of the report which contains table of CVEs. This is on the second page
page = pdf[1]
# Find start of section 3 header

section2_start = page.find("3. List of Identified Vulnerabilities")
self.assertEqual(
page[section2_start:]
Expand All @@ -874,6 +913,17 @@ def test_output_pdf(self):
self.PDF_OUTPUT.replace(" ", ""),
)

page = pdf[2]
section2_start = page.find("4. List of Vulnerabilities with different metric")
self.assertEqual(
page[section2_start:]
.replace(" ", "")
.replace("\r", "")
.replace("\n", "")
.strip(),
self.PDF_OUTPUT_2.replace(" ", ""),
)

def test_output_console(self):
"""Test Formatting Output as console"""

Expand Down

0 comments on commit a098ef0

Please sign in to comment.