diff --git a/support/scripts/cve.py b/support/scripts/cve.py index 18fda8e1a1..1cbe24c02d 100755 --- a/support/scripts/cve.py +++ b/support/scripts/cve.py @@ -184,13 +184,11 @@ class CVE: """The set of CPE products referred by this CVE definition""" return set(cpe_product(p['id']) for p in self.each_cpe()) - def affects(self, name, version, cve_ignore_list, cpeid=None): + def affects(self, name, version, cpeid=None): """ True if the Buildroot Package object passed as argument is affected by this CVE. """ - if self.identifier in cve_ignore_list: - return self.CVE_DOESNT_AFFECT pkg_version = distutils.version.LooseVersion(version) if not hasattr(pkg_version, "version"): diff --git a/support/scripts/pkg-stats b/support/scripts/pkg-stats index 46b12cd992..a0a46aa8cb 100755 --- a/support/scripts/pkg-stats +++ b/support/scripts/pkg-stats @@ -122,6 +122,7 @@ class Package: self.cves = list() self.ignored_cves = list() self.unsure_cves = list() + self.stale_cve_ignores = list() self.latest_version = {'status': RM_API_STATUS_ERROR, 'version': None, 'id': None} self.status = {} @@ -638,7 +639,18 @@ def check_package_cve_affects(cve, cpe_product_pkgs): if product not in cpe_product_pkgs: continue for pkg in cpe_product_pkgs[product]: - cve_status = cve.affects(pkg.name, pkg.current_version, pkg.ignored_cves, pkg.cpeid) + cve_status = cve.affects(pkg.name, pkg.current_version, pkg.cpeid) + + if cve.identifier in pkg.ignored_cves: + if cve_status == cve.CVE_DOESNT_AFFECT: + # We have an ignore entry for a CVE which is + # already reported as 'not affected'. This might + # happen for example when the NVD database doesn't + # initially include version numbers for a CPE, and + # later fixes it. Store it so that we can report + # it. + pkg.stale_cve_ignores.append(cve.identifier) + cve_status = cve.CVE_DOESNT_AFFECT if cve_status == cve.CVE_AFFECTS: pkg.cves.append(cve.identifier) elif cve_status == cve.CVE_UNKNOWN: @@ -670,6 +682,8 @@ def check_package_cves(nvd_path, packages): if 'cve' not in pkg.status: if pkg.cves or pkg.unsure_cves: pkg.status['cve'] = ("error", "affected by CVEs") + elif pkg.stale_cve_ignores: + pkg.status['cve'] = ("warning", "has stale CVE ignores") else: pkg.status['cve'] = ("ok", "not affected by CVEs") @@ -712,10 +726,13 @@ def calculate_stats(packages): stats["patches"] += pkg.patch_count stats["total-cves"] += len(pkg.cves) stats["total-unsure-cves"] += len(pkg.unsure_cves) + stats["total-stale-cve-ignores"] += len(pkg.stale_cve_ignores) if len(pkg.cves) != 0: stats["pkg-cves"] += 1 if len(pkg.unsure_cves) != 0: stats["pkg-unsure-cves"] += 1 + if len(pkg.stale_cve_ignores) != 0: + stats["pkg-stale-cve-ignores"] += 1 if pkg.cpeid: stats["cpe-id"] += 1 else: @@ -867,7 +884,7 @@ function expandField(fieldId){ .wrong, .lotsofpatches, .invalid_url, .version-needs-update, .cpe-nok, .cve-nok { background: #ff9a69; } - .somepatches, .somewarnings, .missing_url, .version-unknown, .cpe-unknown, .cve-unknown { + .somepatches, .somewarnings, .missing_url, .version-unknown, .cpe-unknown, .cve-unknown, .cve-stale { background: #ffd870; } .cve_ignored, .version-error { @@ -1080,10 +1097,17 @@ def dump_html_pkg(f, pkg): div_class = ["centered data ignored_cves"] div_class.append(f'_{pkg_css_class}') if pkg.ignored_cves: - div_class.append("cve_ignored") + if pkg.stale_cve_ignores: + div_class.append("cve-stale") + else: + div_class.append("cve_ignored") f.write(f'