Skip to content

Commit 9fc22be

Browse files
authored
Merge branch 'main' into thunderbird
2 parents 8a869cc + 2fe8ffc commit 9fc22be

File tree

9 files changed

+106
-59
lines changed

9 files changed

+106
-59
lines changed

cve_bin_tool/input_engine.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -115,24 +115,30 @@ def strip_remark(detail) -> str:
115115
ref = affect["ref"]
116116
version = None
117117
vendor = None
118+
# Expected ref format is urn:cbt:{bom_version}/{vendor}#{product}-{version}
118119
if "#" in ref:
119120
# Extract product information after # delimiter
120121
p = ref.split("#")[1]
121122
# Last element is version, rest is product which may include -
122123
elements = p.rsplit("-", 1)
123124
product = elements[0]
124125
version = elements[1]
125-
# Now find vendor
126-
vendor_package_pair = self.cvedb.get_vendor_product_pairs(
127-
product
128-
)
129-
if vendor_package_pair != []:
130-
# FIXME https://github.com/intel/cve-bin-tool/issues/2320
131-
vendor = vendor_package_pair[
132-
len(vendor_package_pair) - 1
133-
]["vendor"]
126+
# Note that cbt (cve-bin-tool) and cdx (cyclonedx)
127+
# namespaces are different
128+
129+
vendor_match = None
130+
if re.match("urn:cbt", ref):
131+
# cbt looks like "urn:cbt:1/gnu#glibc-2.33"
132+
# vendor is between / and #
133+
vendor_match = re.match("urn:cbt:[^/]*/([^#]*)#", ref)
134+
# cdx looks like "urn:cdx:NOTKNOWN/1#libjpeg-turbo-2.0.1"
135+
# There is no vendor so we fall through
136+
137+
if vendor_match is not None:
138+
vendor = vendor_match.group(1)
134139
else:
135140
vendor = "UNKNOWN"
141+
136142
if version is not None and self.validate_product(product):
137143
product_info = ProductInfo(
138144
vendor.strip(), product.strip(), version.strip()

cve_bin_tool/output_engine/__init__.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,13 @@ def generate_vex(self, all_cve_data: dict[ProductInfo, CVEData], filename: str):
644644
Remarks.Mitigated: [],
645645
Remarks.Ignored: [],
646646
}
647+
# URLs for vulnerability detail
648+
source_url = {
649+
"GAD": "https://nvd.nist.gov/vuln/detail/",
650+
"NVD": "https://nvd.nist.gov/vuln/detail/",
651+
"OSV": "https://osv.dev/list?ecosystem=&q=",
652+
"RSD": "https://nvd.nist.gov/vuln/detail/",
653+
}
647654
# Generate VEX file
648655
vex_output = {"bomFormat": "CycloneDX", "specVersion": "1.4", "version": 1}
649656
# Extra info considered useful
@@ -661,11 +668,13 @@ def generate_vex(self, all_cve_data: dict[ProductInfo, CVEData], filename: str):
661668
for cve in cve_data["cves"]:
662669
# Create vulnerability entry. Contains id, scoring, analysis and affected component
663670
vulnerability = dict()
664-
vulnerability["id"] = cve.cve_number
671+
id = cve.cve_number
672+
vulnerability["id"] = id
665673
vulnerability["source"] = {
666-
"name": "NVD",
667-
"url": "https://nvd.nist.gov/vuln/detail/" + cve.cve_number,
674+
"name": cve.data_source,
675+
"url": source_url[cve.data_source] + id,
668676
}
677+
# Assume CVSS vulnerability scores are in accordance with NVD guidance
669678
if cve.cvss_version == 3:
670679
url = f"v3-calculator?name={cve.cve_number}&vector={cve.cvss_vector}&version=3.1"
671680
else:
@@ -683,29 +692,29 @@ def generate_vex(self, all_cve_data: dict[ProductInfo, CVEData], filename: str):
683692
}
684693
]
685694
vulnerability["ratings"] = ratings
686-
vulnerability["cwes"] = []
687695
vulnerability["description"] = cve.description
688696
vulnerability["recommendation"] = ""
689697
vulnerability["advisories"] = []
690698
vulnerability["created"] = "NOT_KNOWN"
691699
vulnerability["published"] = "NOT_KNOWN"
692-
vulnerability["updated"] = "NOT_KNOWN"
700+
vulnerability["updated"] = cve.last_modified
693701
detail = (
694702
cve.remarks.name + ": " + cve.comments
695703
if cve.comments
696704
else cve.remarks.name
697705
)
706+
698707
analysis = {
699708
"state": analysis_state[cve.remarks],
700709
"response": response_state[cve.remarks],
701710
"detail": detail,
702711
}
703712
vulnerability["analysis"] = analysis
704-
bom_urn = "NOTKNOWN"
705713
bom_version = 1
714+
# cve-bin-tool specific reference string to include vendor information
706715
vulnerability["affects"] = [
707716
{
708-
"ref": f"urn:cdx:{bom_urn}/{bom_version}#{product_info.product}-{product_info.version}",
717+
"ref": f"urn:cbt:{bom_version}/{product_info.vendor}#{product_info.product}-{product_info.version}",
709718
}
710719
]
711720
vuln_entry.append(vulnerability)

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ requests
1616
urllib3>=1.26.5 # dependency of requests added explictly to avoid CVEs
1717
gsutil
1818
cvss
19-
packaging
20-
importlib_resources; python_version < "3.9"
19+
packaging<22.0
20+
importlib_resources; python_version < "3.9"

test/test_input_engine.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,34 @@ class TestInputEngine:
6464
},
6565
}
6666
VEX_TRIAGE_DATA = {
67-
ProductInfo("libjpeg-turbo", "libjpeg-turbo", "2.0.1"): {
67+
ProductInfo("d.r.commander", "libjpeg-turbo", "2.0.1"): {
68+
"CVE-2018-19664": {
69+
"comments": "High priority need to resolve fast",
70+
"remarks": Remarks.Confirmed,
71+
"severity": "CRITICAL",
72+
},
73+
"paths": {""},
74+
},
75+
ProductInfo("gnu", "glibc", "2.33"): {
76+
"CVE-2021-1234": {
77+
"comments": "",
78+
"remarks": Remarks.Unexplored,
79+
"severity": "HIGH",
80+
},
81+
"paths": {""},
82+
},
83+
}
84+
# cyclonedx currently doesn't have vendors
85+
VEX_TRIAGE_DATA_CYCLONEDX = {
86+
ProductInfo("UNKNOWN", "libjpeg-turbo", "2.0.1"): {
6887
"CVE-2018-19664": {
6988
"comments": "High priority need to resolve fast",
7089
"remarks": Remarks.Confirmed,
7190
"severity": "CRITICAL",
7291
},
7392
"paths": {""},
7493
},
75-
ProductInfo("gentoo", "glibc", "2.33"): {
94+
ProductInfo("UNKNOWN", "glibc", "2.33"): {
7695
"CVE-2021-1234": {
7796
"comments": "",
7897
"remarks": Remarks.Unexplored,
@@ -148,7 +167,7 @@ def test_valid_file(self, filepath, parsed_data):
148167
"filepath, parsed_data",
149168
(
150169
(str(VEX_PATH / "test_triage.vex"), VEX_TRIAGE_DATA),
151-
(str(VEX_PATH / "test_triage_cyclonedx.vex"), VEX_TRIAGE_DATA),
170+
(str(VEX_PATH / "test_triage_cyclonedx.vex"), VEX_TRIAGE_DATA_CYCLONEDX),
152171
(str(VEX_PATH / "bad.vex"), defaultdict(dict)),
153172
),
154173
)

test/test_output_engine.py

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ class TestOutputEngine(unittest.TestCase):
102102
cvss_version=2,
103103
cvss_vector="C:H",
104104
data_source="NVD",
105+
last_modified="01-05-2019",
105106
),
106107
CVE(
107108
"CVE-1234-1234",
@@ -110,6 +111,7 @@ class TestOutputEngine(unittest.TestCase):
110111
cvss_version=2,
111112
cvss_vector="CVSS2.0/C:H",
112113
data_source="NVD",
114+
last_modified="11-11-2021",
113115
),
114116
],
115117
paths={""},
@@ -123,6 +125,7 @@ class TestOutputEngine(unittest.TestCase):
123125
cvss_version=3,
124126
cvss_vector="CVSS3.0/C:H/I:L/A:M",
125127
data_source="NVD",
128+
last_modified="12-12-2020",
126129
)
127130
],
128131
paths={""},
@@ -135,7 +138,8 @@ class TestOutputEngine(unittest.TestCase):
135138
score=7.5,
136139
cvss_version=2,
137140
cvss_vector="C:H/I:L/A:M",
138-
data_source="NVD",
141+
data_source="OSV",
142+
last_modified="20-10-2012",
139143
)
140144
],
141145
paths={""},
@@ -340,7 +344,7 @@ class TestOutputEngine(unittest.TestCase):
340344
"product": "product1",
341345
"version": "3.2.1.0",
342346
"cve_number": "CVE-1234-1234",
343-
"source": "NVD",
347+
"source": "OSV",
344348
"severity": "HIGH",
345349
"score": "7.5",
346350
"cvss_version": "2",
@@ -610,6 +614,9 @@ class TestOutputEngine(unittest.TestCase):
610614
"vulnerabilities": [
611615
{
612616
"id": "CVE-1234-1234",
617+
"created": "NOT_KNOWN",
618+
"published": "NOT_KNOWN",
619+
"recommendation": "",
613620
"source": {
614621
"name": "NVD",
615622
"url": "https://nvd.nist.gov/vuln/detail/CVE-1234-1234",
@@ -626,22 +633,21 @@ class TestOutputEngine(unittest.TestCase):
626633
"vector": "C:H",
627634
}
628635
],
629-
"cwes": [],
630636
"description": "",
631-
"recommendation": "",
632637
"advisories": [],
633-
"created": "NOT_KNOWN",
634-
"published": "NOT_KNOWN",
635-
"updated": "NOT_KNOWN",
638+
"updated": "01-05-2019",
636639
"analysis": {
637640
"state": "in_triage",
638641
"response": [],
639642
"detail": "NewFound",
640643
},
641-
"affects": [{"ref": "urn:cdx:NOTKNOWN/1#product0-1.0"}],
644+
"affects": [{"ref": "urn:cbt:1/vendor0#product0-1.0"}],
642645
},
643646
{
644647
"id": "CVE-1234-1234",
648+
"created": "NOT_KNOWN",
649+
"published": "NOT_KNOWN",
650+
"recommendation": "",
645651
"source": {
646652
"name": "NVD",
647653
"url": "https://nvd.nist.gov/vuln/detail/CVE-1234-1234",
@@ -658,22 +664,21 @@ class TestOutputEngine(unittest.TestCase):
658664
"vector": "CVSS2.0/C:H",
659665
}
660666
],
661-
"cwes": [],
662667
"description": "",
663-
"recommendation": "",
664668
"advisories": [],
665-
"created": "NOT_KNOWN",
666-
"published": "NOT_KNOWN",
667-
"updated": "NOT_KNOWN",
669+
"updated": "11-11-2021",
668670
"analysis": {
669671
"state": "in_triage",
670672
"response": [],
671673
"detail": "NewFound",
672674
},
673-
"affects": [{"ref": "urn:cdx:NOTKNOWN/1#product0-1.0"}],
675+
"affects": [{"ref": "urn:cbt:1/vendor0#product0-1.0"}],
674676
},
675677
{
676678
"id": "CVE-1234-1234",
679+
"created": "NOT_KNOWN",
680+
"published": "NOT_KNOWN",
681+
"recommendation": "",
677682
"source": {
678683
"name": "NVD",
679684
"url": "https://nvd.nist.gov/vuln/detail/CVE-1234-1234",
@@ -690,25 +695,24 @@ class TestOutputEngine(unittest.TestCase):
690695
"vector": "CVSS3.0/C:H/I:L/A:M",
691696
}
692697
],
693-
"cwes": [],
694698
"description": "",
695-
"recommendation": "",
696699
"advisories": [],
697-
"created": "NOT_KNOWN",
698-
"published": "NOT_KNOWN",
699-
"updated": "NOT_KNOWN",
700+
"updated": "12-12-2020",
700701
"analysis": {
701702
"state": "in_triage",
702703
"response": [],
703704
"detail": "NewFound",
704705
},
705-
"affects": [{"ref": "urn:cdx:NOTKNOWN/1#product0-2.8.6"}],
706+
"affects": [{"ref": "urn:cbt:1/vendor0#product0-2.8.6"}],
706707
},
707708
{
708709
"id": "CVE-1234-1234",
710+
"created": "NOT_KNOWN",
711+
"published": "NOT_KNOWN",
712+
"recommendation": "",
709713
"source": {
710-
"name": "NVD",
711-
"url": "https://nvd.nist.gov/vuln/detail/CVE-1234-1234",
714+
"name": "OSV",
715+
"url": "https://osv.dev/list?ecosystem=&q=CVE-1234-1234",
712716
},
713717
"ratings": [
714718
{
@@ -722,19 +726,15 @@ class TestOutputEngine(unittest.TestCase):
722726
"vector": "C:H/I:L/A:M",
723727
}
724728
],
725-
"cwes": [],
726729
"description": "",
727-
"recommendation": "",
728730
"advisories": [],
729-
"created": "NOT_KNOWN",
730-
"published": "NOT_KNOWN",
731-
"updated": "NOT_KNOWN",
731+
"updated": "20-10-2012",
732732
"analysis": {
733733
"state": "in_triage",
734734
"response": [],
735735
"detail": "NewFound",
736736
},
737-
"affects": [{"ref": "urn:cdx:NOTKNOWN/1#product1-3.2.1.0"}],
737+
"affects": [{"ref": "urn:cbt:1/vendor1#product1-3.2.1.0"}],
738738
},
739739
],
740740
}
@@ -781,6 +781,7 @@ def test_output_csv(self):
781781

782782
def test_output_vex(self):
783783
"""Test creating VEX formatted file"""
784+
self.maxDiff = None
784785
self.output_engine.generate_vex(self.MOCK_OUTPUT, "test.vex")
785786
with open("test.vex") as f:
786787
vex_json = json.load(f)
@@ -839,7 +840,7 @@ def test_output_console(self):
839840
"│ vendor0 │ product0 │ 1.0 │ CVE-1234-1234 │ NVD │ MEDIUM │ 4.2 (v2) │\n"
840841
"│ vendor0 │ product0 │ 1.0 │ CVE-1234-1234 │ NVD │ LOW │ 1.2 (v2) │\n"
841842
"│ vendor0 │ product0 │ 2.8.6 │ CVE-1234-1234 │ NVD │ LOW │ 2.5 (v3) │\n"
842-
"│ vendor1 │ product1 │ 3.2.1.0 │ CVE-1234-1234 │ NVD │ HIGH │ 7.5 (v2) │\n"
843+
"│ vendor1 │ product1 │ 3.2.1.0 │ CVE-1234-1234 │ OSV │ HIGH │ 7.5 (v2) │\n"
843844
"└─────────┴──────────┴─────────┴───────────────┴────────┴──────────┴──────────────────────┘\n"
844845
)
845846

@@ -912,7 +913,7 @@ def test_output_console_outfile(self):
912913
"│ vendor0 │ product0 │ 1.0 │ CVE-1234-1234 │ NVD │ MEDIUM │ 4.2 (v2) │\n"
913914
"│ vendor0 │ product0 │ 1.0 │ CVE-1234-1234 │ NVD │ LOW │ 1.2 (v2) │\n"
914915
"│ vendor0 │ product0 │ 2.8.6 │ CVE-1234-1234 │ NVD │ LOW │ 2.5 (v3) │\n"
915-
"│ vendor1 │ product1 │ 3.2.1.0 │ CVE-1234-1234 │ NVD │ HIGH │ 7.5 (v2) │\n"
916+
"│ vendor1 │ product1 │ 3.2.1.0 │ CVE-1234-1234 │ OSV │ HIGH │ 7.5 (v2) │\n"
916917
"└─────────┴──────────┴─────────┴───────────────┴────────┴──────────┴──────────────────────┘\n"
917918
)
918919

test/test_triage.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ def test_triage():
3434

3535
with open(OUTPUT_JSON) as f:
3636
output_json = json.load(f)
37-
# At least 2 CVEs as number of CVEs could change
38-
assert len(output_json) >= 2
37+
# At least 1 CVEs as number of CVEs could change
38+
assert len(output_json) >= 1
3939

4040
# Check output
4141
for output in output_json:

test/vex/test_triage.vex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
},
3737
"affects": [
3838
{
39-
"ref": "urn:cdx:NOTKNOWN/1#libjpeg-turbo-2.0.1"
39+
"ref": "urn:cbt:1/d.r.commander#libjpeg-turbo-2.0.1"
4040
}
4141
]
4242
},
@@ -73,7 +73,7 @@
7373
},
7474
"affects": [
7575
{
76-
"ref": "urn:cdx:NOTKNOWN/1#glibc-2.33"
76+
"ref": "urn:cbt:1/gnu#glibc-2.33"
7777
}
7878
]
7979
},

0 commit comments

Comments
 (0)