| 76 | return packages |
| 77 | |
| 78 | def _load_advisory(self, path: str) -> Optional[AdvisoryData]: |
| 79 | record = get_advisory_data(path) |
| 80 | advisory = record.get("advisory", {}) |
| 81 | crate_name = advisory["package"] |
| 82 | references = [] |
| 83 | if advisory.get("url"): |
| 84 | references.append(Reference(url=advisory["url"])) |
| 85 | |
| 86 | publish_date = parse(advisory["date"]).replace(tzinfo=pytz.UTC) |
| 87 | all_versions = self.crates_api.get(crate_name, publish_date).valid_versions |
| 88 | |
| 89 | # FIXME: Avoid wildcard version ranges for now. |
| 90 | # See https://github.com/RustSec/advisory-db/discussions/831 |
| 91 | affected_ranges = [ |
| 92 | VersionRange.from_scheme_version_spec_string("semver", r) |
| 93 | for r in chain.from_iterable(record.get("affected", {}).get("functions", {}).values()) |
| 94 | if r != "*" |
| 95 | ] |
| 96 | |
| 97 | unaffected_ranges = [ |
| 98 | VersionRange.from_scheme_version_spec_string("semver", r) |
| 99 | for r in record.get("versions", {}).get("unaffected", []) |
| 100 | if r != "*" |
| 101 | ] |
| 102 | resolved_ranges = [ |
| 103 | VersionRange.from_scheme_version_spec_string("semver", r) |
| 104 | for r in record.get("versions", {}).get("patched", []) |
| 105 | if r != "*" |
| 106 | ] |
| 107 | |
| 108 | unaffected, affected = categorize_versions( |
| 109 | all_versions, unaffected_ranges, affected_ranges, resolved_ranges |
| 110 | ) |
| 111 | |
| 112 | impacted_purls = [PackageURL(type="cargo", name=crate_name, version=v) for v in affected] |
| 113 | resolved_purls = [PackageURL(type="cargo", name=crate_name, version=v) for v in unaffected] |
| 114 | |
| 115 | cve_id = None |
| 116 | if "aliases" in advisory: |
| 117 | for alias in advisory["aliases"]: |
| 118 | if alias.startswith("CVE-"): |
| 119 | cve_id = alias |
| 120 | break |
| 121 | |
| 122 | references.append( |
| 123 | Reference( |
| 124 | reference_id=advisory["id"], |
| 125 | url="https://rustsec.org/advisories/{}.html".format(advisory["id"]), |
| 126 | ) |
| 127 | ) |
| 128 | |
| 129 | return AdvisoryData( |
| 130 | summary=advisory.get("description", ""), |
| 131 | affected_packages=nearest_patched_package(impacted_purls, resolved_purls), |
| 132 | vulnerability_id=cve_id, |
| 133 | references=references, |
| 134 | ) |
| 135 | |