diff --git a/vulnerabilities/utils.py b/vulnerabilities/utils.py index f90d42401..71cbe8389 100644 --- a/vulnerabilities/utils.py +++ b/vulnerabilities/utils.py @@ -49,6 +49,26 @@ find_all_cve = cve_regex.findall cwe_regex = r"CWE-\d+" + +def extract_cve_ids(text): + """ + Extract deduplicated, normalized CVE identifiers from unstructured text. + + Returns a sorted list of unique CVE IDs found in the text, normalized to + uppercase. Handles CVE IDs embedded in URLs, surrounded by punctuation, + or appearing multiple times. + + >>> extract_cve_ids("Fixed CVE-2023-1234 and cve-2023-5678.") + ['CVE-2023-1234', 'CVE-2023-5678'] + >>> extract_cve_ids("See https://nvd.nist.gov/vuln/detail/CVE-2021-44228") + ['CVE-2021-44228'] + >>> extract_cve_ids("No vulnerabilities here.") + [] + """ + if not text: + return [] + return sorted(set(cve.upper() for cve in find_all_cve(text))) + commit_regex = re.compile(r"\b[0-9a-f]{5,40}\b", re.IGNORECASE) is_commit = commit_regex.fullmatch diff --git a/vulntotal/vulntotal_cli.py b/vulntotal/vulntotal_cli.py index d60ceeb85..2063dab24 100755 --- a/vulntotal/vulntotal_cli.py +++ b/vulntotal/vulntotal_cli.py @@ -17,8 +17,7 @@ import click -# TODO: use saneyaml -import yaml +import saneyaml from fetchcode import package_versions from packageurl import PackageURL from texttable import Texttable @@ -313,7 +312,7 @@ def noop(self, *args, **kw): pass -yaml.emitter.Emitter.process_tag = noop +saneyaml.emitter.Emitter.process_tag = noop def write_yaml_output(purl, datasources, yaml_output, no_threading, no_group, no_compare): @@ -327,7 +326,7 @@ def write_yaml_output(purl, datasources, yaml_output, no_threading, no_group, no serialize_version_range(grouped_by_cve, no_compare) results.update(grouped_by_cve) - return yaml.dump(results, yaml_output, default_flow_style=False, indent=2, sort_keys=False) + return saneyaml.dump(results, yaml_output, default_flow_style=False, indent=2, sort_keys=False) def serialize_version_range(grouped_by_cve, no_compare):