def yaml_file_to_advisory(yaml_path): impacted_packages = [] resolved_packages = [] references = [] data = load_yaml(yaml_path) vuln_id = data["vulnerability_id"] summary = "\n".join([note["text"] for note in data["notes"]]) for entry in data.get("artifacts", []): package = PackageURL.from_string(entry["id"]) if entry["affected"]: impacted_packages.append(package) else: resolved_packages.append(package) for fix in data.get("fixes", []): for commit in fix["commits"]: references.append( Reference(url=f"{commit['repository']}/{commit['id']}")) return Advisory( vulnerability_id=vuln_id, summary=summary, affected_packages=nearest_patched_package(impacted_packages, resolved_packages), references=references, )
def to_advisories(xml_response: str) -> Set[Advisory]: advisories = [] pkg_name = "openssl" pkg_type = "generic" root = ET.fromstring(xml_response) for element in root: if element.tag == "issue": cve_id = "" summary = "" safe_pkg_versions = [] vuln_pkg_versions = [] ref_urls = [] for info in element: if info.tag == "cve": if info.attrib.get("name"): cve_id = "CVE-" + info.attrib.get("name") else: continue if info.tag == "affects": # Vulnerable package versions vuln_pkg_versions.append(info.attrib.get("version")) if info.tag == "fixed": # Fixed package versions safe_pkg_versions.append(info.attrib.get("version")) if info: commit_hash = info[0].attrib["hash"] ref_urls.append( Reference( url= "https://github.com/openssl/openssl/commit/" + commit_hash)) if info.tag == "description": # Description summary = re.sub(r"\s+", " ", info.text).strip() safe_purls = [ PackageURL(name=pkg_name, type=pkg_type, version=version) for version in safe_pkg_versions ] vuln_purls = [ PackageURL(name=pkg_name, type=pkg_type, version=version) for version in vuln_pkg_versions ] advisory = Advisory( vulnerability_id=cve_id, summary=summary, affected_packages=nearest_patched_package( vuln_purls, safe_purls), references=ref_urls, ) advisories.append(advisory) return advisories
def _parse(self, pkg_name: str, records: Mapping[str, Any]) -> List[Advisory]: advisories = [] for cve_id, record in records.items(): impacted_purls, resolved_purls = [], [] if not cve_id.startswith("CVE"): continue # vulnerabilities starting with something else may not be public yet # see for instance https://web.archive.org/web/20201215213725/https://security-tracker.debian.org/tracker/TEMP-0000000-A2EB44 # nopep8 # TODO: this would need to be revisited though to ensure we are not missing out on anything # nopep8 for release_name, release_record in record["releases"].items(): if not release_record.get("repositories", {}).get(release_name): continue purl = PackageURL( name=pkg_name, type="deb", namespace="debian", version=release_record["repositories"][release_name], qualifiers={"distro": release_name}, ) if release_record.get("status", "") == "resolved": resolved_purls.append(purl) else: impacted_purls.append(purl) if "fixed_version" in release_record: resolved_purls.append( PackageURL( name=pkg_name, type="deb", namespace="debian", version=release_record["fixed_version"], qualifiers={"distro": release_name}, )) references = [] debianbug = record.get("debianbug") if debianbug: bug_url = f"https://bugs.debian.org/cgi-bin/bugreport.cgi?bug={debianbug}" references.append( Reference(url=bug_url, reference_id=debianbug)) # print(nearest_patched_package(impacted_purls, resolved_purls)) advisories.append( Advisory( vulnerability_id=cve_id, affected_packages=nearest_patched_package( impacted_purls, resolved_purls), summary=record.get("description", ""), references=references, )) return advisories
def to_advisories(self, apache_tomcat_advisory_html): advisories = [] page_soup = BeautifulSoup(apache_tomcat_advisory_html, features="lxml") pageh3s = page_soup.find_all("h3") vuln_headings = [ i for i in pageh3s if "Fixed in Apache Tomcat" in i.text ] for data in vuln_headings: fixed_version = data.text.split( "Fixed in Apache Tomcat")[-1].strip() details_div = data.find_next_sibling() for anchor_tag in details_div.find_all("a"): if "cve.mitre.org" not in anchor_tag["href"]: continue cve_id = re.search(r"CVE-\d*-\d*", anchor_tag.text).group() references = [] affected_packages = [] paragraph = anchor_tag.find_parent() while paragraph and "Affects:" not in paragraph.text: for ref in paragraph.find_all("a"): references.append(Reference(url=ref["href"])) paragraph = paragraph.find_next_sibling() if not paragraph: # At the end of details_div continue for version_range in parse_version_ranges(paragraph.text): affected_packages.extend([ PackageURL(type="maven", namespace="apache", name="tomcat", version=version) for version in self.version_api.get("org.apache.tomcat:tomcat") if MavenVersion(version) in version_range ]) fixed_package = [ PackageURL(type="maven", namespace="apache", name="tomcat", version=fixed_version) ] advisories.append( Advisory( summary="", affected_packages=nearest_patched_package( affected_packages, fixed_package), vulnerability_id=cve_id, references=references, )) return advisories
def _parse(self, record) -> List[Advisory]: advisories = [] for cve_id in record["issues"]: affected_packages = [] for name in record["packages"]: impacted_purls, resolved_purls = [], [] impacted_purls.append( PackageURL( name=name, type="pacman", namespace="archlinux", version=record["affected"], ) ) if record["fixed"]: resolved_purls.append( PackageURL( name=name, type="pacman", namespace="archlinux", version=record["fixed"], ) ) affected_packages.extend(nearest_patched_package(impacted_purls, resolved_purls)) references = [] references.append( Reference( reference_id=record["name"], url="https://security.archlinux.org/{}".format(record["name"]), severities=[ VulnerabilitySeverity( system=scoring_systems["avgs"], value=record["severity"] ) ], ) ) for ref in record["advisories"]: references.append( Reference( reference_id=ref, url="https://security.archlinux.org/{}".format(ref), ) ) advisories.append( Advisory( vulnerability_id=cve_id, summary="", affected_packages=affected_packages, references=references, ) ) return advisories
def process_file(self, path) -> List[Advisory]: record = load_yaml(path) package_name = record.get("gem") if not package_name: return if "cve" in record: cve_id = "CVE-{}".format(record["cve"]) else: return safe_version_ranges = record.get("patched_versions", []) # this case happens when the advisory contain only 'patched_versions' field # and it has value None(i.e it is empty :( ). if not safe_version_ranges: safe_version_ranges = [] safe_version_ranges += record.get("unaffected_versions", []) safe_version_ranges = [i for i in safe_version_ranges if i] if not getattr(self, "pkg_manager_api", None): self.pkg_manager_api = RubyVersionAPI() all_vers = self.pkg_manager_api.get(package_name) safe_versions, affected_versions = self.categorize_versions( all_vers, safe_version_ranges) impacted_purls = [ PackageURL( name=package_name, type="gem", version=version, ) for version in affected_versions ] resolved_purls = [ PackageURL( name=package_name, type="gem", version=version, ) for version in safe_versions ] references = [] if record.get("url"): references.append(Reference(url=record.get("url"))) return Advisory( summary=record.get("description", ""), affected_packages=nearest_patched_package(impacted_purls, resolved_purls), references=references, vulnerability_id=cve_id, )
def to_advisories(self, data): advisories = [] soup = BeautifulSoup(data, features="lxml") vuln_list = soup.select("li p") # Example value of `vuln_list` : # ['Excessive CPU usage in HTTP/2 with small window updates', # <br/>, # 'Severity: medium', # <br/>, # <a href="http://mailman.nginx.org/pipermail/nginx-announce/2019/000249.html">Advisory</a>, # nopep8 # <br/>, # <a href="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9511">CVE-2019-9511</a>, # <br/>, # 'Not vulnerable: 1.17.3+, 1.16.1+', # <br/>, # 'Vulnerable: 1.9.5-1.17.2'] for vuln_info in vuln_list: references = [] for index, child in enumerate(vuln_info.children): if index == 0: # type of this child is bs4.element.NavigableString. # Hence cast it into standard string summary = str(child) continue # hasattr(child, "attrs") == False for bs4.element.NavigableString if hasattr(child, "attrs") and child.attrs.get("href"): link = child.attrs["href"] references.append(Reference(url=link)) if "cve.mitre.org" in link: cve_id = child.text continue if "Not vulnerable" in child: fixed_packages = self.extract_fixed_pkgs(child) continue if "Vulnerable" in child: vulnerable_packages = self.extract_vuln_pkgs(child) continue advisories.append( Advisory( vulnerability_id=cve_id, summary=summary, affected_packages=nearest_patched_package(vulnerable_packages, fixed_packages), ) ) return advisories
def to_advisory(self, advisory_page): advisories = [] advisory_page = BeautifulSoup(advisory_page, features="lxml") cve_section_beginnings = advisory_page.find_all("h2") for cve_section_beginning in cve_section_beginnings: cve_id = cve_section_beginning.text.split("\n")[0] cve_description_paragraph = cve_section_beginning.find_next_sibling( "p") cve_data_table = cve_section_beginning.find_next_sibling("table") cve_data_table_rows = cve_data_table.find_all("tr") affected_versions_row = cve_data_table_rows[0] fixed_versions_row = cve_data_table_rows[1] affected_version_ranges = to_version_ranges( affected_versions_row.find_all("td")[1].text) fixed_version_ranges = to_version_ranges( fixed_versions_row.find_all("td")[1].text) fixed_packages = [ PackageURL(type="apache", name="kafka", version=version) for version in self.version_api.get("apache/kafka") if any([ MavenVersion(version) in version_range for version_range in fixed_version_ranges ]) ] affected_packages = [ PackageURL(type="apache", name="kafka", version=version) for version in self.version_api.get("apache/kafka") if any([ MavenVersion(version) in version_range for version_range in affected_version_ranges ]) ] advisories.append( Advisory( vulnerability_id=cve_id, summary=cve_description_paragraph.text, affected_packages=nearest_patched_package( affected_packages, fixed_packages), references=[ Reference(url=ASF_PAGE_URL), Reference( url= f"https://cve.mitre.org/cgi-bin/cvename.cgi?name={cve_id}", reference_id=cve_id, ), ], )) return advisories
def updated_advisories(self) -> Set[Advisory]: advisories = [] for package_name in self._api_response: if package_name == "$meta" or package_name == "cumin": # This is the first entry in the data feed. It contains metadata of the feed. # Skip it. The 'cumin' entry is wrong continue try: validate_schema(self._api_response[package_name]) except Exception as e: logger.error(e) continue all_package_versions = self.versions.get(package_name) if not len(all_package_versions): # PyPi does not have data about this package, we skip these continue for advisory in self._api_response[package_name]: if advisory["cve"]: # Check on advisory["cve"] instead of using `get` because it can have null value cve_ids = re.findall(r"CVE-\d+-\d+", advisory["cve"]) else: continue impacted_purls, resolved_purls = categorize_versions( package_name, all_package_versions, advisory["specs"] ) reference = [Reference(reference_id=advisory["id"])] for cve_id in cve_ids: advisories.append( Advisory( vulnerability_id=cve_id, summary=advisory["advisory"], references=reference, affected_packages=nearest_patched_package( impacted_purls, resolved_purls ), ) ) return advisories
def process_file(self, path): yaml_file = load_yaml(path) pkg_name = yaml_file["package"] safe_pkg_versions = [] vuln_pkg_versions = [] if not yaml_file.get("patched_versions"): yaml_file["patched_versions"] = [] if not yaml_file.get("unaffected_versions"): yaml_file["unaffected_versions"] = [] safe_pkg_versions, vuln_pkg_versions = self.get_versions_for_pkg_from_range_list( yaml_file["patched_versions"] + yaml_file["unaffected_versions"], pkg_name, ) if yaml_file.get("cve"): cve_id = "CVE-" + yaml_file["cve"] else: cve_id = "" safe_purls = [] vuln_purls = [] safe_purls = [ PackageURL(name=pkg_name, type="hex", version=version) for version in safe_pkg_versions ] vuln_purls = [ PackageURL(name=pkg_name, type="hex", version=version) for version in vuln_pkg_versions ] references = [ Reference( reference_id=yaml_file["id"], ), Reference( url=yaml_file["link"], ), ] return Advisory( summary=yaml_file["description"], affected_packages=nearest_patched_package(vuln_purls, safe_purls), vulnerability_id=cve_id, references=references, )
def process_file(self, file): xml_data = {} xml_root = ET.parse(file).getroot() glsa = "GLSA-" + xml_root.attrib["id"] vuln_reference = [ Reference( reference_id=glsa, url="https://security.gentoo.org/glsa/{}".format( xml_root.attrib["id"]), ) ] for child in xml_root: if child.tag == "references": xml_data["cves"] = self.cves_from_reference(child) if child.tag == "synopsis": xml_data["description"] = child.text if child.tag == "affected": ( xml_data["affected_purls"], xml_data["unaffected_purls"], ) = self.affected_and_safe_purls(child) xml_data["unaffected_purls"] = list( xml_data["unaffected_purls"]) xml_data["affected_purls"] = list(xml_data["affected_purls"]) advisory_list = [] # It is very inefficient, to create new Advisory for each CVE # this way, but there seems no alternative. for cve in xml_data["cves"]: advisory = Advisory( vulnerability_id=cve, summary=xml_data["description"], affected_packages=nearest_patched_package( xml_data["affected_purls"], xml_data["unaffected_purls"]), references=vuln_reference, ) advisory_list.append(advisory) return advisory_list
def process_file(self, file) -> List[Advisory]: record = load_json(file) advisories = [] package_name = record["module_name"].strip() all_versions = self.versions.get(package_name) aff_range = record.get("vulnerable_versions") if not aff_range: aff_range = "" fixed_range = record.get("patched_versions") if not fixed_range: fixed_range = "" if aff_range == "*" or fixed_range == "*": return [] impacted_versions, resolved_versions = categorize_versions( all_versions, aff_range, fixed_range ) impacted_purls = _versions_to_purls(package_name, impacted_versions) resolved_purls = _versions_to_purls(package_name, resolved_versions) vuln_reference = [ Reference( url=NPM_URL.format(f'/-/npm/v1/advisories/{record["id"]}'), reference_id=record["id"], ) ] for cve_id in record.get("cves") or [""]: advisories.append( Advisory( summary=record.get("overview", ""), vulnerability_id=cve_id, affected_packages=nearest_patched_package(impacted_purls, resolved_purls), references=vuln_reference, ) ) return advisories
def _load_advisory(self, path: str) -> Optional[Advisory]: record = get_advisory_data(path) advisory = record.get("advisory", {}) crate_name = advisory["package"] references = [] if advisory.get("url"): references.append(Reference(url=advisory["url"])) all_versions = self.crates_api.get(crate_name) # FIXME: Avoid wildcard version ranges for now. # See https://github.com/RustSec/advisory-db/discussions/831 affected_ranges = [ VersionSpecifier.from_scheme_version_spec_string("semver", r) for r in chain.from_iterable( record.get("affected", {}).get("functions", {}).values()) if r != "*" ] unaffected_ranges = [ VersionSpecifier.from_scheme_version_spec_string("semver", r) for r in record.get("versions", {}).get("unaffected", []) if r != "*" ] resolved_ranges = [ VersionSpecifier.from_scheme_version_spec_string("semver", r) for r in record.get("versions", {}).get("patched", []) if r != "*" ] unaffected, affected = categorize_versions(all_versions, unaffected_ranges, affected_ranges, resolved_ranges) impacted_purls = [ PackageURL(type="cargo", name=crate_name, version=v) for v in affected ] resolved_purls = [ PackageURL(type="cargo", name=crate_name, version=v) for v in unaffected ] cve_id = None if "aliases" in advisory: for alias in advisory["aliases"]: if alias.startswith("CVE-"): cve_id = alias break references.append( Reference( reference_id=advisory["id"], url="https://rustsec.org/advisories/{}.html".format( advisory["id"]), )) return Advisory( summary=advisory.get("description", ""), affected_packages=nearest_patched_package(impacted_purls, resolved_purls), vulnerability_id=cve_id, references=references, )
def process_response(self) -> List[Advisory]: adv_list = [] for ecosystem in self.advisories: self.set_version_api(ecosystem) pkg_type = self.version_api.package_type for resp_page in self.advisories[ecosystem]: for adv in resp_page["data"]["securityVulnerabilities"][ "edges"]: name = adv["node"]["package"]["name"] if self.process_name(ecosystem, name): ns, pkg_name = self.process_name(ecosystem, name) aff_range = adv["node"]["vulnerableVersionRange"] aff_vers, unaff_vers = self.categorize_versions( self.version_api.package_type, aff_range, self.version_api.get(name)) affected_purls = [ PackageURL(name=pkg_name, namespace=ns, version=version, type=pkg_type) for version in aff_vers ] unaffected_purls = [ PackageURL(name=pkg_name, namespace=ns, version=version, type=pkg_type) for version in unaff_vers ] else: affected_purls = [] unaffected_purls = [] cve_ids = set() references = self.extract_references( adv["node"]["advisory"]["references"]) vuln_desc = adv["node"]["advisory"]["summary"] for identifier in adv["node"]["advisory"]["identifiers"]: # collect CVEs if identifier["type"] == "CVE": cve_ids.add(identifier["value"]) # attach the GHSA with severity score if identifier["type"] == "GHSA": for ref in references: if ref.reference_id == identifier["value"]: ref.severities = [ VulnerabilitySeverity( system=scoring_systems[ "cvssv3.1_qr"], value=adv["node"]["advisory"] ["severity"], ) ] # Each Node has only one GHSA, hence exit after attaching # score to this GHSA break for cve_id in cve_ids: adv_list.append( Advisory( vulnerability_id=cve_id, summary=vuln_desc, affected_packages=nearest_patched_package( affected_purls, unaffected_purls), references=references, )) return adv_list
def get_data_from_xml_doc(self, xml_doc: ET.ElementTree, pkg_metadata={}) -> List[Advisory]: """ The orchestration method of the OvalDataSource. This method breaks an OVAL xml ElementTree into a list of `Advisory`. Note: pkg_metadata is a mapping of Package URL data that MUST INCLUDE "type" key. Example value of pkg_metadata: {"type":"deb","qualifiers":{"distro":"buster"} } """ all_adv = [] oval_doc = OvalParser(self.translations, xml_doc) raw_data = oval_doc.get_data() all_pkgs = self._collect_pkgs(raw_data) self.set_api(all_pkgs) # convert definition_data to Advisory objects for definition_data in raw_data: # These fields are definition level, i.e common for all elements # connected/linked to an OvalDefinition vuln_id = definition_data["vuln_id"] description = definition_data["description"] references = [Reference(url=url) for url in definition_data["reference_urls"]] affected_packages = [] for test_data in definition_data["test_data"]: for package_name in test_data["package_list"]: if package_name and len(package_name) >= 50: continue affected_version_range = test_data["version_ranges"] or set() version_class = version_class_by_package_type[pkg_metadata["type"]] version_scheme = version_class.scheme affected_version_range = VersionSpecifier.from_scheme_version_spec_string( version_scheme, affected_version_range ) all_versions = self.pkg_manager_api.get(package_name) # FIXME: what is this 50 DB limit? that's too small for versions # FIXME: we should not drop data this way # This filter is for filtering out long versions. # 50 is limit because that's what db permits atm. all_versions = [version for version in all_versions if len(version) < 50] if not all_versions: continue affected_purls = [] safe_purls = [] for version in all_versions: purl = self.create_purl( pkg_name=package_name, pkg_version=version, pkg_data=pkg_metadata, ) if version_class(version) in affected_version_range: affected_purls.append(purl) else: safe_purls.append(purl) affected_packages.extend( nearest_patched_package(affected_purls, safe_purls), ) all_adv.append( Advisory( summary=description, affected_packages=affected_packages, vulnerability_id=vuln_id, references=references, ) ) return all_adv
def process_file(self, path): advisories = [] data = self.get_data_from_md(path) releases = [] if data.get("releases"): for release in data["releases"]: # If it is of form "All versions prior to x" if "All releases" in release: release = release.strip() release = release.split(" ") releases.append("<" + release[4]) # If it is of form "a to b" elif "to" in release: release = release.strip() release = release.split(" ") lbound = ">=" + release[0] ubound = "<=" + release[2] releases.append(lbound + "," + ubound) # If it is a single release elif is_release(release): releases.append(release) data["release_ranges"] = releases if not data.get("cves"): data["cves"] = [""] for cve_id in data["cves"]: if not cve_id.startswith("CVE"): cve_id = "" safe_pkg_versions = [] vuln_pkg_versions = [] if not data.get("release_ranges"): data["release_ranges"] = [] safe_pkg_versions, vuln_pkg_versions = self.get_pkg_versions_from_ranges( data["release_ranges"]) affected_packages = [] safe_purls_golang = [ PackageURL(type="golang", name="istio", version=version) for version in safe_pkg_versions ] vuln_purls_golang = [ PackageURL(type="golang", name="istio", version=version) for version in vuln_pkg_versions ] affected_packages.extend( nearest_patched_package(vuln_purls_golang, safe_purls_golang)) safe_purls_github = [ PackageURL(type="github", name="istio", version=version) for version in safe_pkg_versions ] vuln_purls_github = [ PackageURL(type="github", name="istio", version=version) for version in vuln_pkg_versions ] affected_packages.extend( nearest_patched_package(vuln_purls_github, safe_purls_github)) advisories.append( Advisory( vulnerability_id=cve_id, summary=data["description"], affected_packages=affected_packages, )) return advisories
def process_file(self, path): advisories = [] data = self.get_data_from_md(path) releases = [] if data.get("releases"): for release in data["releases"]: # If it is of form "All releases prior to x" if "All releases prior" in release: release = release.strip() release = release.split(" ") releases.append("<" + release[4]) # Eg. 'All releases 1.5 and later' elif "All releases" in release and "and later" in release: release = release.split()[2].strip() releases.append(f">={release}") elif "to" in release: release = release.strip() release = release.split(" ") lbound = ">=" + release[0] ubound = "<=" + release[2] releases.append(lbound + "," + ubound) # If it is a single release elif is_release(release): releases.append(release) data["release_ranges"] = releases if not data.get("cves"): data["cves"] = [""] for cve_id in data["cves"]: if not cve_id.startswith("CVE"): cve_id = "" safe_pkg_versions = [] vuln_pkg_versions = [] if not data.get("release_ranges"): data["release_ranges"] = [] safe_pkg_versions, vuln_pkg_versions = self.get_pkg_versions_from_ranges( data["release_ranges"]) affected_packages = [] safe_purls_golang = [ PackageURL(type="golang", name="istio", version=version) for version in safe_pkg_versions ] vuln_purls_golang = [ PackageURL(type="golang", name="istio", version=version) for version in vuln_pkg_versions ] affected_packages.extend( nearest_patched_package(vuln_purls_golang, safe_purls_golang)) safe_purls_github = [ PackageURL(type="github", name="istio", version=version) for version in safe_pkg_versions ] vuln_purls_github = [ PackageURL(type="github", name="istio", version=version) for version in vuln_pkg_versions ] affected_packages.extend( nearest_patched_package(vuln_purls_github, safe_purls_github)) advisories.append( Advisory( vulnerability_id=cve_id, summary=data["description"], affected_packages=affected_packages, references=[ Reference( reference_id=data["title"], url= f"https://istio.io/latest/news/security/{data['title']}/", ) ], )) return advisories
def to_advisory(advisory_data): affected_purls = [] if advisory_data.get("affected_packages"): for rpm in advisory_data["affected_packages"]: purl = rpm_to_purl(rpm) if purl: affected_purls.append(purl) references = [] bugzilla = advisory_data.get("bugzilla") if bugzilla: url = "https://bugzilla.redhat.com/show_bug.cgi?id={}".format(bugzilla) bugzilla_data = requests_session.get( f"https://bugzilla.redhat.com/rest/bug/{bugzilla}").json() if (bugzilla_data.get("bugs") and len(bugzilla_data["bugs"]) and bugzilla_data["bugs"][0].get("severity")): bugzilla_severity_val = bugzilla_data["bugs"][0]["severity"] bugzilla_severity = VulnerabilitySeverity( system=scoring_systems["rhbs"], value=bugzilla_severity_val, ) references.append( Reference( severities=[bugzilla_severity], url=url, reference_id=bugzilla, )) for rh_adv in advisory_data["advisories"]: # RH provides 3 types of advisories RHSA, RHBA, RHEA. Only RHSA's contain severity score. # See https://access.redhat.com/articles/2130961 for more details. if "RHSA" in rh_adv.upper(): rhsa_data = requests_session.get( f"https://access.redhat.com/hydra/rest/securitydata/cvrf/{rh_adv}.json" ).json() # nopep8 rhsa_aggregate_severities = [] if rhsa_data.get("cvrfdoc"): # not all RHSA errata have a corresponding CVRF document value = rhsa_data["cvrfdoc"]["aggregate_severity"] rhsa_aggregate_severities.append( VulnerabilitySeverity( system=scoring_systems["rhas"], value=value, )) references.append( Reference( severities=rhsa_aggregate_severities, url="https://access.redhat.com/errata/{}".format(rh_adv), reference_id=rh_adv, )) else: references.append( Reference(severities=[], url=url, reference_id=rh_adv)) redhat_scores = [] cvssv3_score = advisory_data.get("cvss3_score") if cvssv3_score: redhat_scores.append( VulnerabilitySeverity( system=scoring_systems["cvssv3"], value=cvssv3_score, )) cvssv3_vector = advisory_data.get("cvss3_scoring_vector") if cvssv3_vector: redhat_scores.append( VulnerabilitySeverity( system=scoring_systems["cvssv3_vector"], value=cvssv3_vector, )) references.append( Reference(severities=redhat_scores, url=advisory_data["resource_url"])) return Advisory( vulnerability_id=advisory_data["CVE"], summary=advisory_data["bugzilla_description"], affected_packages=nearest_patched_package(affected_purls, []), references=references, )
def to_advisory(self, data): cve = data["CVE_data_meta"]["ID"] descriptions = data["description"]["description_data"] description = None for desc in descriptions: if desc["lang"] == "eng": description = desc.get("value") break severities = [] impacts = data.get("impact", []) for impact in impacts: value = impact.get("other") if value: severities.append( VulnerabilitySeverity( system=scoring_systems["apache_httpd"], value=value, ) ) break reference = Reference( reference_id=cve, url=urllib.parse.urljoin(self.base_url, f"{cve}.json"), severities=severities, ) versions_data = [] for vendor in data["affects"]["vendor"]["vendor_data"]: for products in vendor["product"]["product_data"]: for version_data in products["version"]["version_data"]: versions_data.append(version_data) fixed_version_ranges, affected_version_ranges = self.to_version_ranges(versions_data) affected_packages = [] fixed_packages = [] for version_range in fixed_version_ranges: fixed_packages.extend( [ PackageURL(type="apache", name="httpd", version=version) for version in self.version_api.get("apache/httpd") if MavenVersion(version) in version_range ] ) for version_range in affected_version_ranges: affected_packages.extend( [ PackageURL(type="apache", name="httpd", version=version) for version in self.version_api.get("apache/httpd") if MavenVersion(version) in version_range ] ) return Advisory( vulnerability_id=cve, summary=description, affected_packages=nearest_patched_package(affected_packages, fixed_packages), references=[reference], )