Skip to content

Commit

Permalink
feat: adding EPSS to console table (#3224)
Browse files Browse the repository at this point in the history
  • Loading branch information
Rexbeast2 authored Aug 10, 2023
1 parent 338e0cf commit b7b2b91
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 22 deletions.
12 changes: 12 additions & 0 deletions cve_bin_tool/output_engine/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ def _output_console_nowrap(
# 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 = str(round(field[0] * 100, 4))
percentile = str(field[1])
cve_by_remarks[cve.remarks].append(
{
"vendor": product_info.vendor,
Expand All @@ -114,6 +120,8 @@ def _output_console_nowrap(
"severity": cve.severity,
"score": cve.score,
"cvss_version": cve.cvss_version,
"epss_propability": propability,
"epss_percentile": percentile,
}
)
path_elements = ", ".join(filter(None, cve_data["paths"]))
Expand Down Expand Up @@ -149,6 +157,8 @@ def _output_console_nowrap(
table.add_column("Source")
table.add_column("Severity")
table.add_column("Score (CVSS Version)")
table.add_column("EPSS propability")
table.add_column("EPSS percentile")
if affected_versions != 0:
table.add_column("Affected Versions")

Expand All @@ -168,6 +178,8 @@ def _output_console_nowrap(
Text.styled(cve_data["source"], color),
Text.styled(cve_data["severity"], color),
Text.styled(cvss_text, color),
Text.styled(cve_data["epss_propability"], color),
Text.styled(cve_data["epss_percentile"], color),
]
if affected_versions != 0:
cells.append(Text.styled(cve_data["affected_versions"], color))
Expand Down
91 changes: 69 additions & 22 deletions test/test_output_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_vector="C:H",
data_source="NVD",
last_modified="01-05-2019",
metric={
"EPSS": [0.00126, "0.46387"],
},
),
CVE(
"CVE-1234-1234",
Expand All @@ -112,6 +115,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_vector="CVSS2.0/C:H",
data_source="NVD",
last_modified="11-11-2021",
metric={
"EPSS": [0.01836, "0.79673"],
},
),
],
paths={""},
Expand All @@ -126,6 +132,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_vector="CVSS3.0/C:H/I:L/A:M",
data_source="NVD",
last_modified="12-12-2020",
metric={
"EPSS": [0.03895, "0.37350"],
},
)
],
paths={""},
Expand All @@ -140,6 +149,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_vector="C:H/I:L/A:M",
data_source="OSV",
last_modified="20-10-2012",
metric={
"EPSS": [0.0468, "0.34072"],
},
)
],
paths={""},
Expand Down Expand Up @@ -177,6 +189,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=3,
cvss_vector="CVSS3.0/C:H/I:L/A:M",
data_source="NVD",
metric={
"EPSS": [0.0468, "0.34072"],
},
)
],
paths={""},
Expand Down Expand Up @@ -206,6 +221,7 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=0,
cvss_vector="C:H",
data_source="NVD",
metric={},
),
CVE(
"CVE-9999-0001",
Expand All @@ -214,6 +230,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="C:H",
data_source="NVD",
metric={
"EPSS": [0.299, "0.25934"],
},
),
CVE(
"CVE-9999-0002",
Expand All @@ -222,6 +241,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="C:H",
data_source="NVD",
metric={
"EPSS": [0.0285, "0.94667"],
},
),
CVE(
"CVE-9999-0003",
Expand All @@ -230,6 +252,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="C:H",
data_source="NVD",
metric={
"EPSS": [0.0468, "0.34072"],
},
),
CVE(
"CVE-9999-0004",
Expand All @@ -238,6 +263,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="C:H",
data_source="NVD",
metric={
"EPSS": [0.35337, "0.72282"],
},
),
CVE(
"CVE-9999-0005",
Expand All @@ -246,6 +274,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="C:H",
data_source="NVD",
metric={
"EPSS": [0.15370, "0.21433"],
},
),
CVE(
"CVE-9999-0006",
Expand All @@ -254,6 +285,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="C:H",
data_source="NVD",
metric={
"EPSS": [0.0513, "0.77186"],
},
),
CVE(
"CVE-9999-0007",
Expand All @@ -262,6 +296,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="C:H",
data_source="NVD",
metric={
"EPSS": [0.08360, "0.53389"],
},
),
CVE(
"CVE-9999-0008",
Expand All @@ -270,6 +307,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="C:H",
data_source="NVD",
metric={
"EPSS": [0.36957, "0.83771"],
},
),
CVE(
"CVE-9999-9999",
Expand All @@ -278,6 +318,9 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="CVSS2.0/C:H",
data_source="NVD",
metric={
"EPSS": [0.012959, "0.67261"],
},
),
],
paths={""},
Expand Down Expand Up @@ -837,11 +880,11 @@ def test_output_console(self):
)

expected_output = (
"│ vendor0 │ product0 │ 1.0 │ CVE-1234-1234 │ NVD │ MEDIUM │ 4.2 (v2) │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-1234-1234 │ NVD │ LOW │ 1.2 (v2) │\n"
"│ vendor0 │ product0 │ 2.8.6 │ CVE-1234-1234 │ NVD │ LOW │ 2.5 (v3) │\n"
"│ vendor1 │ product1 │ 3.2.1.0 │ CVE-1234-1234 │ OSV │ HIGH │ 7.5 (v2) │\n"
"└─────────┴──────────┴─────────┴───────────────┴────────┴──────────┴──────────────────────┘\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-1234-1234 │ NVD │ MEDIUM │ 4.2 (v2) │ 0.126 │ 0.46387 \n"
"│ vendor0 │ product0 │ 1.0 │ CVE-1234-1234 │ NVD │ LOW │ 1.2 (v2) │ 1.836 │ 0.79673 \n"
"│ vendor0 │ product0 │ 2.8.6 │ CVE-1234-1234 │ NVD │ LOW │ 2.5 (v3) │ 3.895 │ 0.37350 \n"
"│ vendor1 │ product1 │ 3.2.1.0 │ CVE-1234-1234 │ OSV │ HIGH │ 7.5 (v2) │ 4.68 │ 0.34072 \n"
"└─────────┴──────────┴─────────┴───────────────┴────────┴──────────┴────────────────┴─────────────────┴────────────────┘\n"
)

self.mock_file.seek(0) # reset file position
Expand Down Expand Up @@ -870,21 +913,26 @@ def test_output_console_affected_versions(self):
)

expected_output = (
"│ vendor0 │ product0 │ 1.0 │ UNKNOWN │ NVD │ UNKNOWN │ 0 (v0) │ - │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0001 │ NVD │ MEDIUM │ 4.2 (v2) │ [0.9.0 - 1.2.0] │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0002 │ NVD │ MEDIUM │ 4.2 (v2) │ [0.9.0 - 1.2.0) │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0003 │ NVD │ MEDIUM │ 4.2 (v2) │ (0.9.0 - 1.2.0] │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0004 │ NVD │ MEDIUM │ 4.2 (v2) │ (0.9.0 - 1.2.0) │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0005 │ NVD │ MEDIUM │ 4.2 (v2) │ >= 0.9.0 │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0006 │ NVD │ MEDIUM │ 4.2 (v2) │ > 0.9.0 │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0007 │ NVD │ MEDIUM │ 4.2 (v2) │ <= 1.2.0 │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0008 │ NVD │ MEDIUM │ 4.2 (v2) │ < 1.2.0 │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-9999 │ NVD │ LOW │ 1.2 (v2) │ - │\n"
"└─────────┴──────────┴─────────┴───────────────┴────────┴──────────┴──────────────────────┴───────────────────┘\n"
"│ vendor0 │ product0 │ 1.0 │ UNKNOWN │ NVD │ UNKNOWN │ 0 (v0) │ - │ - │ - │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0… │ NVD │ MEDIUM │ 4.2 (v2) │ 29.9 │ 0.25934 │ [0.9.0 - │\n"
"│ │ │ │ │ │ │ │ │ │ 1.2.0] │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0… │ NVD │ MEDIUM │ 4.2 (v2) │ 2.85 │ 0.94667 │ [0.9.0 - │\n"
"│ │ │ │ │ │ │ │ │ │ 1.2.0) │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0… │ NVD │ MEDIUM │ 4.2 (v2) │ 4.68 │ 0.34072 │ (0.9.0 - │\n"
"│ │ │ │ │ │ │ │ │ │ 1.2.0] │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0… │ NVD │ MEDIUM │ 4.2 (v2) │ 35.337 │ 0.72282 │ (0.9.0 - │\n"
"│ │ │ │ │ │ │ │ │ │ 1.2.0) │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0… │ NVD │ MEDIUM │ 4.2 (v2) │ 15.37 │ 0.21433 │ >= 0.9.0 │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0… │ NVD │ MEDIUM │ 4.2 (v2) │ 5.13 │ 0.77186 │ > 0.9.0 │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0… │ NVD │ MEDIUM │ 4.2 (v2) │ 8.36 │ 0.53389 │ <= 1.2.0 │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-0… │ NVD │ MEDIUM │ 4.2 (v2) │ 36.957 │ 0.83771 │ < 1.2.0 │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-9999-9… │ NVD │ LOW │ 1.2 (v2) │ 1.2959 │ 0.67261 │ - │\n"
"└─────────┴──────────┴─────────┴─────────────┴────────┴──────────┴─────────────┴────────────┴─────────────┴────────────┘\n"
)

self.mock_file.seek(0) # reset file position
result = self.mock_file.read()
print(result)
self.assertIn(expected_output, result)

def test_output_console_outfile(self):
Expand All @@ -910,16 +958,15 @@ def test_output_console_outfile(self):
)

expected_output = (
"│ vendor0 │ product0 │ 1.0 │ CVE-1234-1234 │ NVD │ MEDIUM │ 4.2 (v2) │\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-1234-1234 │ NVD │ LOW │ 1.2 (v2) │\n"
"│ vendor0 │ product0 │ 2.8.6 │ CVE-1234-1234 │ NVD │ LOW │ 2.5 (v3) │\n"
"│ vendor1 │ product1 │ 3.2.1.0 │ CVE-1234-1234 │ OSV │ HIGH │ 7.5 (v2) │\n"
"└─────────┴──────────┴─────────┴───────────────┴────────┴──────────┴──────────────────────┘\n"
"│ vendor0 │ product0 │ 1.0 │ CVE-1234-1234 │ NVD │ MEDIUM │ 4.2 (v2) │ 0.126 │ 0.46387 \n"
"│ vendor0 │ product0 │ 1.0 │ CVE-1234-1234 │ NVD │ LOW │ 1.2 (v2) │ 1.836 │ 0.79673 \n"
"│ vendor0 │ product0 │ 2.8.6 │ CVE-1234-1234 │ NVD │ LOW │ 2.5 (v3) │ 3.895 │ 0.37350 \n"
"│ vendor1 │ product1 │ 3.2.1.0 │ CVE-1234-1234 │ OSV │ HIGH │ 7.5 (v2) │ 4.68 │ 0.34072 \n"
"└─────────┴──────────┴─────────┴───────────────┴────────┴──────────┴────────────────┴─────────────────┴────────────────┘\n"
)

with open(tmpf.name, encoding="utf-8") as f:
result = f.read()

self.assertIn(expected_output, result)
Path(tmpf.name).unlink() # deleting tempfile

Expand Down

0 comments on commit b7b2b91

Please sign in to comment.