Skip to content

Commit

Permalink
fix: Using vex as triage file loses vendor field (Fixes #2320) (#2329)
Browse files Browse the repository at this point in the history
* Fixes #2320

Co-authored-by: Terri Oda <terri.oda@intel.com>
  • Loading branch information
anthonyharrison and terriko authored Dec 14, 2022
1 parent f55bf33 commit 2fe8ffc
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 55 deletions.
24 changes: 15 additions & 9 deletions cve_bin_tool/input_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,24 +115,30 @@ def strip_remark(detail) -> str:
ref = affect["ref"]
version = None
vendor = None
# Expected ref format is urn:cbt:{bom_version}/{vendor}#{product}-{version}
if "#" in ref:
# Extract product information after # delimiter
p = ref.split("#")[1]
# Last element is version, rest is product which may include -
elements = p.rsplit("-", 1)
product = elements[0]
version = elements[1]
# Now find vendor
vendor_package_pair = self.cvedb.get_vendor_product_pairs(
product
)
if vendor_package_pair != []:
# FIXME https://github.com/intel/cve-bin-tool/issues/2320
vendor = vendor_package_pair[
len(vendor_package_pair) - 1
]["vendor"]
# Note that cbt (cve-bin-tool) and cdx (cyclonedx)
# namespaces are different

vendor_match = None
if re.match("urn:cbt", ref):
# cbt looks like "urn:cbt:1/gnu#glibc-2.33"
# vendor is between / and #
vendor_match = re.match("urn:cbt:[^/]*/([^#]*)#", ref)
# cdx looks like "urn:cdx:NOTKNOWN/1#libjpeg-turbo-2.0.1"
# There is no vendor so we fall through

if vendor_match is not None:
vendor = vendor_match.group(1)
else:
vendor = "UNKNOWN"

if version is not None and self.validate_product(product):
product_info = ProductInfo(
vendor.strip(), product.strip(), version.strip()
Expand Down
23 changes: 16 additions & 7 deletions cve_bin_tool/output_engine/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,13 @@ def generate_vex(self, all_cve_data: dict[ProductInfo, CVEData], filename: str):
Remarks.Mitigated: [],
Remarks.Ignored: [],
}
# URLs for vulnerability detail
source_url = {
"GAD": "https://nvd.nist.gov/vuln/detail/",
"NVD": "https://nvd.nist.gov/vuln/detail/",
"OSV": "https://osv.dev/list?ecosystem=&q=",
"RSD": "https://nvd.nist.gov/vuln/detail/",
}
# Generate VEX file
vex_output = {"bomFormat": "CycloneDX", "specVersion": "1.4", "version": 1}
# Extra info considered useful
Expand All @@ -661,11 +668,13 @@ def generate_vex(self, all_cve_data: dict[ProductInfo, CVEData], filename: str):
for cve in cve_data["cves"]:
# Create vulnerability entry. Contains id, scoring, analysis and affected component
vulnerability = dict()
vulnerability["id"] = cve.cve_number
id = cve.cve_number
vulnerability["id"] = id
vulnerability["source"] = {
"name": "NVD",
"url": "https://nvd.nist.gov/vuln/detail/" + cve.cve_number,
"name": cve.data_source,
"url": source_url[cve.data_source] + id,
}
# Assume CVSS vulnerability scores are in accordance with NVD guidance
if cve.cvss_version == 3:
url = f"v3-calculator?name={cve.cve_number}&vector={cve.cvss_vector}&version=3.1"
else:
Expand All @@ -683,29 +692,29 @@ def generate_vex(self, all_cve_data: dict[ProductInfo, CVEData], filename: str):
}
]
vulnerability["ratings"] = ratings
vulnerability["cwes"] = []
vulnerability["description"] = cve.description
vulnerability["recommendation"] = ""
vulnerability["advisories"] = []
vulnerability["created"] = "NOT_KNOWN"
vulnerability["published"] = "NOT_KNOWN"
vulnerability["updated"] = "NOT_KNOWN"
vulnerability["updated"] = cve.last_modified
detail = (
cve.remarks.name + ": " + cve.comments
if cve.comments
else cve.remarks.name
)

analysis = {
"state": analysis_state[cve.remarks],
"response": response_state[cve.remarks],
"detail": detail,
}
vulnerability["analysis"] = analysis
bom_urn = "NOTKNOWN"
bom_version = 1
# cve-bin-tool specific reference string to include vendor information
vulnerability["affects"] = [
{
"ref": f"urn:cdx:{bom_urn}/{bom_version}#{product_info.product}-{product_info.version}",
"ref": f"urn:cbt:{bom_version}/{product_info.vendor}#{product_info.product}-{product_info.version}",
}
]
vuln_entry.append(vulnerability)
Expand Down
25 changes: 22 additions & 3 deletions test/test_input_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,34 @@ class TestInputEngine:
},
}
VEX_TRIAGE_DATA = {
ProductInfo("libjpeg-turbo", "libjpeg-turbo", "2.0.1"): {
ProductInfo("d.r.commander", "libjpeg-turbo", "2.0.1"): {
"CVE-2018-19664": {
"comments": "High priority need to resolve fast",
"remarks": Remarks.Confirmed,
"severity": "CRITICAL",
},
"paths": {""},
},
ProductInfo("gnu", "glibc", "2.33"): {
"CVE-2021-1234": {
"comments": "",
"remarks": Remarks.Unexplored,
"severity": "HIGH",
},
"paths": {""},
},
}
# cyclonedx currently doesn't have vendors
VEX_TRIAGE_DATA_CYCLONEDX = {
ProductInfo("UNKNOWN", "libjpeg-turbo", "2.0.1"): {
"CVE-2018-19664": {
"comments": "High priority need to resolve fast",
"remarks": Remarks.Confirmed,
"severity": "CRITICAL",
},
"paths": {""},
},
ProductInfo("gentoo", "glibc", "2.33"): {
ProductInfo("UNKNOWN", "glibc", "2.33"): {
"CVE-2021-1234": {
"comments": "",
"remarks": Remarks.Unexplored,
Expand Down Expand Up @@ -148,7 +167,7 @@ def test_valid_file(self, filepath, parsed_data):
"filepath, parsed_data",
(
(str(VEX_PATH / "test_triage.vex"), VEX_TRIAGE_DATA),
(str(VEX_PATH / "test_triage_cyclonedx.vex"), VEX_TRIAGE_DATA),
(str(VEX_PATH / "test_triage_cyclonedx.vex"), VEX_TRIAGE_DATA_CYCLONEDX),
(str(VEX_PATH / "bad.vex"), defaultdict(dict)),
),
)
Expand Down
61 changes: 31 additions & 30 deletions test/test_output_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="C:H",
data_source="NVD",
last_modified="01-05-2019",
),
CVE(
"CVE-1234-1234",
Expand All @@ -110,6 +111,7 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=2,
cvss_vector="CVSS2.0/C:H",
data_source="NVD",
last_modified="11-11-2021",
),
],
paths={""},
Expand All @@ -123,6 +125,7 @@ class TestOutputEngine(unittest.TestCase):
cvss_version=3,
cvss_vector="CVSS3.0/C:H/I:L/A:M",
data_source="NVD",
last_modified="12-12-2020",
)
],
paths={""},
Expand All @@ -135,7 +138,8 @@ class TestOutputEngine(unittest.TestCase):
score=7.5,
cvss_version=2,
cvss_vector="C:H/I:L/A:M",
data_source="NVD",
data_source="OSV",
last_modified="20-10-2012",
)
],
paths={""},
Expand Down Expand Up @@ -340,7 +344,7 @@ class TestOutputEngine(unittest.TestCase):
"product": "product1",
"version": "3.2.1.0",
"cve_number": "CVE-1234-1234",
"source": "NVD",
"source": "OSV",
"severity": "HIGH",
"score": "7.5",
"cvss_version": "2",
Expand Down Expand Up @@ -610,6 +614,9 @@ class TestOutputEngine(unittest.TestCase):
"vulnerabilities": [
{
"id": "CVE-1234-1234",
"created": "NOT_KNOWN",
"published": "NOT_KNOWN",
"recommendation": "",
"source": {
"name": "NVD",
"url": "https://nvd.nist.gov/vuln/detail/CVE-1234-1234",
Expand All @@ -626,22 +633,21 @@ class TestOutputEngine(unittest.TestCase):
"vector": "C:H",
}
],
"cwes": [],
"description": "",
"recommendation": "",
"advisories": [],
"created": "NOT_KNOWN",
"published": "NOT_KNOWN",
"updated": "NOT_KNOWN",
"updated": "01-05-2019",
"analysis": {
"state": "in_triage",
"response": [],
"detail": "NewFound",
},
"affects": [{"ref": "urn:cdx:NOTKNOWN/1#product0-1.0"}],
"affects": [{"ref": "urn:cbt:1/vendor0#product0-1.0"}],
},
{
"id": "CVE-1234-1234",
"created": "NOT_KNOWN",
"published": "NOT_KNOWN",
"recommendation": "",
"source": {
"name": "NVD",
"url": "https://nvd.nist.gov/vuln/detail/CVE-1234-1234",
Expand All @@ -658,22 +664,21 @@ class TestOutputEngine(unittest.TestCase):
"vector": "CVSS2.0/C:H",
}
],
"cwes": [],
"description": "",
"recommendation": "",
"advisories": [],
"created": "NOT_KNOWN",
"published": "NOT_KNOWN",
"updated": "NOT_KNOWN",
"updated": "11-11-2021",
"analysis": {
"state": "in_triage",
"response": [],
"detail": "NewFound",
},
"affects": [{"ref": "urn:cdx:NOTKNOWN/1#product0-1.0"}],
"affects": [{"ref": "urn:cbt:1/vendor0#product0-1.0"}],
},
{
"id": "CVE-1234-1234",
"created": "NOT_KNOWN",
"published": "NOT_KNOWN",
"recommendation": "",
"source": {
"name": "NVD",
"url": "https://nvd.nist.gov/vuln/detail/CVE-1234-1234",
Expand All @@ -690,25 +695,24 @@ class TestOutputEngine(unittest.TestCase):
"vector": "CVSS3.0/C:H/I:L/A:M",
}
],
"cwes": [],
"description": "",
"recommendation": "",
"advisories": [],
"created": "NOT_KNOWN",
"published": "NOT_KNOWN",
"updated": "NOT_KNOWN",
"updated": "12-12-2020",
"analysis": {
"state": "in_triage",
"response": [],
"detail": "NewFound",
},
"affects": [{"ref": "urn:cdx:NOTKNOWN/1#product0-2.8.6"}],
"affects": [{"ref": "urn:cbt:1/vendor0#product0-2.8.6"}],
},
{
"id": "CVE-1234-1234",
"created": "NOT_KNOWN",
"published": "NOT_KNOWN",
"recommendation": "",
"source": {
"name": "NVD",
"url": "https://nvd.nist.gov/vuln/detail/CVE-1234-1234",
"name": "OSV",
"url": "https://osv.dev/list?ecosystem=&q=CVE-1234-1234",
},
"ratings": [
{
Expand All @@ -722,19 +726,15 @@ class TestOutputEngine(unittest.TestCase):
"vector": "C:H/I:L/A:M",
}
],
"cwes": [],
"description": "",
"recommendation": "",
"advisories": [],
"created": "NOT_KNOWN",
"published": "NOT_KNOWN",
"updated": "NOT_KNOWN",
"updated": "20-10-2012",
"analysis": {
"state": "in_triage",
"response": [],
"detail": "NewFound",
},
"affects": [{"ref": "urn:cdx:NOTKNOWN/1#product1-3.2.1.0"}],
"affects": [{"ref": "urn:cbt:1/vendor1#product1-3.2.1.0"}],
},
],
}
Expand Down Expand Up @@ -781,6 +781,7 @@ def test_output_csv(self):

def test_output_vex(self):
"""Test creating VEX formatted file"""
self.maxDiff = None
self.output_engine.generate_vex(self.MOCK_OUTPUT, "test.vex")
with open("test.vex") as f:
vex_json = json.load(f)
Expand Down Expand Up @@ -839,7 +840,7 @@ def test_output_console(self):
"│ 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 │ NVD │ HIGH │ 7.5 (v2) │\n"
"│ vendor1 │ product1 │ 3.2.1.0 │ CVE-1234-1234 │ OSV │ HIGH │ 7.5 (v2) │\n"
"└─────────┴──────────┴─────────┴───────────────┴────────┴──────────┴──────────────────────┘\n"
)

Expand Down Expand Up @@ -912,7 +913,7 @@ def test_output_console_outfile(self):
"│ 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 │ NVD │ HIGH │ 7.5 (v2) │\n"
"│ vendor1 │ product1 │ 3.2.1.0 │ CVE-1234-1234 │ OSV │ HIGH │ 7.5 (v2) │\n"
"└─────────┴──────────┴─────────┴───────────────┴────────┴──────────┴──────────────────────┘\n"
)

Expand Down
4 changes: 2 additions & 2 deletions test/vex/test_triage.vex
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
},
"affects": [
{
"ref": "urn:cdx:NOTKNOWN/1#libjpeg-turbo-2.0.1"
"ref": "urn:cbt:1/d.r.commander#libjpeg-turbo-2.0.1"
}
]
},
Expand Down Expand Up @@ -73,7 +73,7 @@
},
"affects": [
{
"ref": "urn:cdx:NOTKNOWN/1#glibc-2.33"
"ref": "urn:cbt:1/gnu#glibc-2.33"
}
]
},
Expand Down
14 changes: 13 additions & 1 deletion test/vex/test_triage_triage_input.vex
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,18 @@
"name": "NVD",
"url": "https://nvd.nist.gov/vuln/detail/GMS-2016-69"
},
"ratings": [
{
"source": {
"name": "NVD",
"url": "https://nvd.nist.gov/vuln-metrics/cvss/v2-calculator?name=GMS-2016-69&vector=unknown&version=2.0"
},
"score": "unknown",
"severity": "unknown",
"method": "CVSSv2",
"vector": "unknown"
}
],
"cwes": [],
"description": "If an attacker can trick an unsuspecting user into viewing a specially crafted plot on a site that uses plotly.js, then the attacker could potentially retrieve authentication tokens and perform actions on behalf of the user.",
"recommendation": "",
Expand All @@ -24,7 +36,7 @@
},
"affects": [
{
"ref": "urn:cdx:NOTKNOWN/1#plotly.js-2.13.2"
"ref": "urn:cbt:1/plotly#plotly.js-2.13.2"
}
]
}
Expand Down
Loading

0 comments on commit 2fe8ffc

Please sign in to comment.