Skip to content

Commit d98dfe3

Browse files
committed
Work on alias/CVE loop #1079
Reference: #1079 Signed-off-by: John M. Horan <johnmhoran@gmail.com>
1 parent 5cd4c36 commit d98dfe3

3 files changed

Lines changed: 11778 additions & 582 deletions

File tree

vulnerabilities/importer.py

Lines changed: 127 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,83 @@ def advisory_data(self) -> List[AdvisoryData]:
421421
)
422422
continue
423423

424+
# def get_data_from_xml_doc(
425+
# self, xml_doc: ET.ElementTree, pkg_metadata={}
426+
# ) -> Iterable[AdvisoryData]:
427+
# """
428+
# The orchestration method of the OvalDataSource. This method breaks an
429+
# OVAL xml ElementTree into a list of `Advisory`.
430+
431+
# Note: pkg_metadata is a mapping of Package URL data that MUST INCLUDE
432+
# "type" key.
433+
434+
# Example value of pkg_metadata:
435+
# {"type":"deb","qualifiers":{"distro":"buster"} }
436+
# """
437+
# oval_parsed_data = OvalParser(self.translations, xml_doc)
438+
# raw_data = oval_parsed_data.get_data()
439+
# oval_doc = oval_parsed_data.oval_document
440+
# timestamp = oval_doc.getGenerator().getTimestamp()
441+
442+
# print("\noval_parsed_data = {}\n".format(oval_parsed_data))
443+
# print("\nraw_data = {}\n".format(raw_data))
444+
445+
# # convert definition_data to Advisory objects
446+
# for definition_data in raw_data:
447+
# print("\ndefinition_data = {}\n".format(definition_data))
448+
# # These fields are definition level, i.e common for all elements
449+
# # connected/linked to an OvalDefinition
450+
451+
# # TODO: 2023-01-24 Tuesday 22:34:20. Is this where we'd loop through the list of CVEs/aliases?
452+
453+
# vuln_id = definition_data["vuln_id"]
454+
# description = definition_data["description"]
455+
456+
# severities = []
457+
# severity = definition_data.get("severity")
458+
# if severity:
459+
# severities.append(
460+
# VulnerabilitySeverity(system=severity_systems.GENERIC, value=severity)
461+
# )
462+
# references = [
463+
# Reference(url=url, severities=severities)
464+
# for url in definition_data["reference_urls"]
465+
# ]
466+
# affected_packages = []
467+
# print('\ndefinition_data["test_data"] = {}\n'.format(definition_data["test_data"]))
468+
# for test_data in definition_data["test_data"]:
469+
# print("\ntest_data['package_list'] = {}\n".format(test_data["package_list"]))
470+
# for package_name in test_data["package_list"]:
471+
# affected_version_range = test_data["version_ranges"]
472+
# vrc = RANGE_CLASS_BY_SCHEMES[pkg_metadata["type"]]
473+
# if affected_version_range:
474+
# try:
475+
# affected_version_range = vrc.from_native(affected_version_range)
476+
# except Exception as e:
477+
# logger.error(
478+
# f"Failed to parse version range {affected_version_range!r} "
479+
# f"for package {package_name!r}:\n{e}"
480+
# )
481+
# continue
482+
# if package_name:
483+
# affected_packages.append(
484+
# AffectedPackage(
485+
# package=self.create_purl(package_name, pkg_metadata),
486+
# affected_version_range=affected_version_range,
487+
# )
488+
# )
489+
# print("affected_packages = {}".format(affected_packages))
490+
# date_published = dateparser.parse(timestamp)
491+
# if not date_published.tzinfo:
492+
# date_published = date_published.replace(tzinfo=pytz.UTC)
493+
# yield AdvisoryData(
494+
# aliases=[vuln_id],
495+
# summary=description,
496+
# affected_packages=sorted(affected_packages),
497+
# references=sorted(references),
498+
# date_published=date_published,
499+
# )
500+
424501
def get_data_from_xml_doc(
425502
self, xml_doc: ET.ElementTree, pkg_metadata={}
426503
) -> Iterable[AdvisoryData]:
@@ -450,50 +527,54 @@ def get_data_from_xml_doc(
450527

451528
# TODO: 2023-01-24 Tuesday 22:34:20. Is this where we'd loop through the list of CVEs/aliases?
452529

453-
vuln_id = definition_data["vuln_id"]
454-
description = definition_data["description"]
455-
456-
severities = []
457-
severity = definition_data.get("severity")
458-
if severity:
459-
severities.append(
460-
VulnerabilitySeverity(system=severity_systems.GENERIC, value=severity)
461-
)
462-
references = [
463-
Reference(url=url, severities=severities)
464-
for url in definition_data["reference_urls"]
465-
]
466-
affected_packages = []
467-
print('\ndefinition_data["test_data"] = {}\n'.format(definition_data["test_data"]))
468-
for test_data in definition_data["test_data"]:
469-
print("\ntest_data['package_list'] = {}\n".format(test_data["package_list"]))
470-
for package_name in test_data["package_list"]:
471-
affected_version_range = test_data["version_ranges"]
472-
vrc = RANGE_CLASS_BY_SCHEMES[pkg_metadata["type"]]
473-
if affected_version_range:
474-
try:
475-
affected_version_range = vrc.from_native(affected_version_range)
476-
except Exception as e:
477-
logger.error(
478-
f"Failed to parse version range {affected_version_range!r} "
479-
f"for package {package_name!r}:\n{e}"
530+
vuln_id_list = definition_data["vuln_id"]
531+
532+
for vuln_id_item in vuln_id_list:
533+
# vuln_id = definition_data["vuln_id"]
534+
vuln_id = vuln_id_item
535+
description = definition_data["description"]
536+
537+
severities = []
538+
severity = definition_data.get("severity")
539+
if severity:
540+
severities.append(
541+
VulnerabilitySeverity(system=severity_systems.GENERIC, value=severity)
542+
)
543+
references = [
544+
Reference(url=url, severities=severities)
545+
for url in definition_data["reference_urls"]
546+
]
547+
affected_packages = []
548+
print('\ndefinition_data["test_data"] = {}\n'.format(definition_data["test_data"]))
549+
for test_data in definition_data["test_data"]:
550+
print("\ntest_data['package_list'] = {}\n".format(test_data["package_list"]))
551+
for package_name in test_data["package_list"]:
552+
affected_version_range = test_data["version_ranges"]
553+
vrc = RANGE_CLASS_BY_SCHEMES[pkg_metadata["type"]]
554+
if affected_version_range:
555+
try:
556+
affected_version_range = vrc.from_native(affected_version_range)
557+
except Exception as e:
558+
logger.error(
559+
f"Failed to parse version range {affected_version_range!r} "
560+
f"for package {package_name!r}:\n{e}"
561+
)
562+
continue
563+
if package_name:
564+
affected_packages.append(
565+
AffectedPackage(
566+
package=self.create_purl(package_name, pkg_metadata),
567+
affected_version_range=affected_version_range,
568+
)
480569
)
481-
continue
482-
if package_name:
483-
affected_packages.append(
484-
AffectedPackage(
485-
package=self.create_purl(package_name, pkg_metadata),
486-
affected_version_range=affected_version_range,
487-
)
488-
)
489-
print("affected_packages = {}".format(affected_packages))
490-
date_published = dateparser.parse(timestamp)
491-
if not date_published.tzinfo:
492-
date_published = date_published.replace(tzinfo=pytz.UTC)
493-
yield AdvisoryData(
494-
aliases=[vuln_id],
495-
summary=description,
496-
affected_packages=sorted(affected_packages),
497-
references=sorted(references),
498-
date_published=date_published,
499-
)
570+
print("affected_packages = {}".format(affected_packages))
571+
date_published = dateparser.parse(timestamp)
572+
if not date_published.tzinfo:
573+
date_published = date_published.replace(tzinfo=pytz.UTC)
574+
yield AdvisoryData(
575+
aliases=[vuln_id],
576+
summary=description,
577+
affected_packages=sorted(affected_packages),
578+
references=sorted(references),
579+
date_published=date_published,
580+
)

vulnerabilities/oval_parser.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ def get_data(self) -> List[Dict]:
3636
Return a list of OvalDefinition mappings.
3737
"""
3838
oval_data = []
39-
# print(len(self.all_definitions))
4039
print("\nlen(self.all_definitions) = {}\n".format(len(self.all_definitions)))
4140
for definition in self.all_definitions:
4241
# print(definition)
@@ -54,20 +53,28 @@ def get_data(self) -> List[Dict]:
5453

5554
definition_data["severity"] = self.get_severity_from_definition(definition)
5655
print("\nlen(matching_tests) = {}\n".format(len(matching_tests)))
56+
print("\nmatching_tests = {}\n".format(matching_tests))
5757
for test in matching_tests:
58+
print("\ntest = {}\n".format(test))
5859
test_obj, test_state = self.get_object_state_of_test(test)
5960
if not test_obj or not test_state:
6061
continue
6162
test_data = {"package_list": []}
62-
print(test_obj)
63+
print("\ntest_obj = {}\n".format(test_obj))
6364
test_data["package_list"].extend(self.get_pkgs_from_obj(test_obj))
64-
print(self.get_pkgs_from_obj(test_obj))
65+
print(
66+
"\nself.get_pkgs_from_obj(test_obj) = {}\n".format(
67+
self.get_pkgs_from_obj(test_obj)
68+
)
69+
)
6570
version_ranges = self.get_version_range_from_state(test_state)
6671
test_data["version_ranges"] = version_ranges
6772
definition_data["test_data"].append(test_data)
6873

6974
oval_data.append(definition_data)
7075

76+
# print('\ntest_data["package_list"] = {}\n'.format(test_data["package_list"]))
77+
7178
return oval_data
7279

7380
def get_tests_of_definition(self, definition: OvalDefinition) -> List[OvalTest]:
@@ -185,15 +192,27 @@ def get_severity_from_definition(definition: OvalDefinition) -> Set[str]:
185192

186193
@staticmethod
187194
def get_vuln_id_from_definition(definition):
188-
# SUSE and Ubuntu OVAL files will get cves via this loop
195+
# # SUSE and Ubuntu OVAL files will get cves via this loop
196+
# for child in definition.element.iter():
197+
# # if child.get("ref_id"):
198+
# # return child.get("ref_id")
199+
# # Must also check whether 'source' field exists and value is 'CVE'
200+
# # TODO: what if there are multiple elements that satisfy the condition?
201+
# # Add to list and report as separate AdvisoryData() objects?
202+
# if child.get("ref_id") and child.get("source"):
203+
# if child.get("source") == "CVE":
204+
# return child.get("ref_id")
205+
# # Debian OVAL files will get cves via this
206+
# return definition.getMetadata().getTitle()
207+
# ========================================================
208+
cve_list = []
189209
for child in definition.element.iter():
190-
# if child.get("ref_id"):
191-
# return child.get("ref_id")
192-
# Must also check whether 'source' field exists and value is 'CVE'
193-
# TODO: what if there are multiple elements that satisfy the condition?
194-
# Add to list and report as separate AdvisoryData() objects?
195210
if child.get("ref_id") and child.get("source"):
196211
if child.get("source") == "CVE":
197-
return child.get("ref_id")
212+
cve_list.append(child.get("ref_id"))
213+
198214
# Debian OVAL files will get cves via this
199-
return definition.getMetadata().getTitle()
215+
if len(cve_list) == 0:
216+
cve_list.append(definition.getMetadata().getTitle())
217+
218+
return cve_list

0 commit comments

Comments
 (0)