Buildroot Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [Buildroot] [RFC PATCH 1/1] support/scripts/pkg-stats: add support for reporting stale CVE entries
@ 2025-04-23 15:29 Raphaël Mélotte via buildroot
  2025-05-18  8:54 ` Thomas Petazzoni via buildroot
  2025-06-04 17:15 ` Arnout Vandecappelle via buildroot
  0 siblings, 2 replies; 3+ messages in thread
From: Raphaël Mélotte via buildroot @ 2025-04-23 15:29 UTC (permalink / raw)
  To: buildroot; +Cc: Raphaël Mélotte, Sen Hastings

The NVD database contains some CPEs that are wrongly not associated
with any version number. They are for example sometimes associated
with very old CVEs.
Those CPEs are annoying, because they pollute our pkg-stat CVE results
with CVE entries which actually don't affect us.

The proper way to solve it is, and should remain, to fix the NVD
database by reporting these issues. Having to deal with a lot of
CVEs/CPEs, the NVD database is however slow to be updated.

To reduce the noise in our pkg-stats results in the meantime, one
possibility is to add <PKG_IGNORE_CVES> entries for those CVEs.  This
however comes with the downside that even once the NVD database gets
fixed, those ignored entries risk remaining in Buildroot forever
because they are undetected.

This commit tries to address this downside by checking for and
reporting CVEs that are ignored in Buildroot, but where the
NVD reports our package version as unaffected. Those CVEs will appear
in the 'CVEs Ignored' column as '(stale)', and the cell will be
colored the same way warnings are. This should allow us to detect and
remove those entries.

It can be tested for example by adding the following variable to the
apache package (for a CVE that was recently fixed in the NVD database):
APACHE_IGNORE_CVES = CVE-1999-0236

Signed-off-by: Raphaël Mélotte <raphael.melotte@mind.be>
---
 support/scripts/cve.py    |  4 +---
 support/scripts/pkg-stats | 36 ++++++++++++++++++++++++++++++++----
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/support/scripts/cve.py b/support/scripts/cve.py
index 5af6e0c43f..fe2e3f7712 100755
--- a/support/scripts/cve.py
+++ b/support/scripts/cve.py
@@ -190,13 +190,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 c134e1ec06..ac8472167e 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'  <div id="{data_field_id}" class="{" ".join(div_class)}">\n')
     for ignored_cve in pkg.ignored_cves:
-        f.write(f'    <a href="https://security-tracker.debian.org/tracker/{ignored_cve}">{ignored_cve}</a><br/>\n')
+        if ignored_cve in pkg.stale_cve_ignores:
+            f.write(f"""    <a href="https://security-tracker.debian.org/tracker/{ignored_cve}">{ignored_cve}"""
+                    """<i>(stale)</i></a><br/>\n""")
+        else:
+            f.write(f'    <a href="https://security-tracker.debian.org/tracker/{ignored_cve}">{ignored_cve}</a><br/>\n')
     f.write("  </div>\n")
 
     # CPE ID
@@ -1193,6 +1217,10 @@ def dump_html_stats(f, stats):
             stats["pkg-unsure-cves"])
     f.write('<div class="data">Total number of unsure CVEs affecting all packages</div><div class="data">%s</div>\n' %
             stats["total-unsure-cves"])
+    f.write('<div class="data">Packages with stale CVE ignores</div><div class="data">%s</div>\n' %
+            stats["pkg-stale-cve-ignores"])
+    f.write('<div class="data">Total number of stale CVE ignores affecting all packages</div><div class="data">%s</div>\n' %
+            stats["total-stale-cve-ignores"])
     f.write('<div class="data">Packages with CPE ID</div><div class="data">%s</div>\n' %
             stats["cpe-id"])
     f.write('<div class="data">Packages without CPE ID</div><div class="data">%s</div>\n' %
-- 
2.49.0

_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [Buildroot] [RFC PATCH 1/1] support/scripts/pkg-stats: add support for reporting stale CVE entries
  2025-04-23 15:29 [Buildroot] [RFC PATCH 1/1] support/scripts/pkg-stats: add support for reporting stale CVE entries Raphaël Mélotte via buildroot
@ 2025-05-18  8:54 ` Thomas Petazzoni via buildroot
  2025-06-04 17:15 ` Arnout Vandecappelle via buildroot
  1 sibling, 0 replies; 3+ messages in thread
From: Thomas Petazzoni via buildroot @ 2025-05-18  8:54 UTC (permalink / raw)
  To: Raphaël Mélotte via buildroot
  Cc: Raphaël Mélotte, Sen Hastings

On Wed, 23 Apr 2025 17:29:05 +0200
Raphaël Mélotte via buildroot <buildroot@buildroot.org> wrote:

> The NVD database contains some CPEs that are wrongly not associated
> with any version number. They are for example sometimes associated
> with very old CVEs.
> Those CPEs are annoying, because they pollute our pkg-stat CVE results
> with CVE entries which actually don't affect us.
> 
> The proper way to solve it is, and should remain, to fix the NVD
> database by reporting these issues. Having to deal with a lot of
> CVEs/CPEs, the NVD database is however slow to be updated.
> 
> To reduce the noise in our pkg-stats results in the meantime, one
> possibility is to add <PKG_IGNORE_CVES> entries for those CVEs.  This
> however comes with the downside that even once the NVD database gets
> fixed, those ignored entries risk remaining in Buildroot forever
> because they are undetected.
> 
> This commit tries to address this downside by checking for and
> reporting CVEs that are ignored in Buildroot, but where the
> NVD reports our package version as unaffected. Those CVEs will appear
> in the 'CVEs Ignored' column as '(stale)', and the cell will be
> colored the same way warnings are. This should allow us to detect and
> remove those entries.
> 
> It can be tested for example by adding the following variable to the
> apache package (for a CVE that was recently fixed in the NVD database):
> APACHE_IGNORE_CVES = CVE-1999-0236
> 
> Signed-off-by: Raphaël Mélotte <raphael.melotte@mind.be>
> ---
>  support/scripts/cve.py    |  4 +---
>  support/scripts/pkg-stats | 36 ++++++++++++++++++++++++++++++++----
>  2 files changed, 33 insertions(+), 7 deletions(-)

Great stuff, thanks a lot! Applied to master.

Thomas
-- 
Thomas Petazzoni, CTO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Buildroot] [RFC PATCH 1/1] support/scripts/pkg-stats: add support for reporting stale CVE entries
  2025-04-23 15:29 [Buildroot] [RFC PATCH 1/1] support/scripts/pkg-stats: add support for reporting stale CVE entries Raphaël Mélotte via buildroot
  2025-05-18  8:54 ` Thomas Petazzoni via buildroot
@ 2025-06-04 17:15 ` Arnout Vandecappelle via buildroot
  1 sibling, 0 replies; 3+ messages in thread
From: Arnout Vandecappelle via buildroot @ 2025-06-04 17:15 UTC (permalink / raw)
  To: Raphaël Mélotte, buildroot; +Cc: Sen Hastings



On 23/04/2025 17:29, Raphaël Mélotte via buildroot wrote:
> The NVD database contains some CPEs that are wrongly not associated
> with any version number. They are for example sometimes associated
> with very old CVEs.
> Those CPEs are annoying, because they pollute our pkg-stat CVE results
> with CVE entries which actually don't affect us.
> 
> The proper way to solve it is, and should remain, to fix the NVD
> database by reporting these issues. Having to deal with a lot of
> CVEs/CPEs, the NVD database is however slow to be updated.
> 
> To reduce the noise in our pkg-stats results in the meantime, one
> possibility is to add <PKG_IGNORE_CVES> entries for those CVEs.  This
> however comes with the downside that even once the NVD database gets
> fixed, those ignored entries risk remaining in Buildroot forever
> because they are undetected.
> 
> This commit tries to address this downside by checking for and
> reporting CVEs that are ignored in Buildroot, but where the
> NVD reports our package version as unaffected. Those CVEs will appear
> in the 'CVEs Ignored' column as '(stale)', and the cell will be
> colored the same way warnings are. This should allow us to detect and
> remove those entries.
> 
> It can be tested for example by adding the following variable to the
> apache package (for a CVE that was recently fixed in the NVD database):
> APACHE_IGNORE_CVES = CVE-1999-0236
> 
> Signed-off-by: Raphaël Mélotte <raphael.melotte@mind.be>

  Applied to 2025.02.x, thanks.

  Regards,
  Arnout

> ---
>   support/scripts/cve.py    |  4 +---
>   support/scripts/pkg-stats | 36 ++++++++++++++++++++++++++++++++----
>   2 files changed, 33 insertions(+), 7 deletions(-)
> 
> diff --git a/support/scripts/cve.py b/support/scripts/cve.py
> index 5af6e0c43f..fe2e3f7712 100755
> --- a/support/scripts/cve.py
> +++ b/support/scripts/cve.py
> @@ -190,13 +190,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 c134e1ec06..ac8472167e 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'  <div id="{data_field_id}" class="{" ".join(div_class)}">\n')
>       for ignored_cve in pkg.ignored_cves:
> -        f.write(f'    <a href="https://security-tracker.debian.org/tracker/{ignored_cve}">{ignored_cve}</a><br/>\n')
> +        if ignored_cve in pkg.stale_cve_ignores:
> +            f.write(f"""    <a href="https://security-tracker.debian.org/tracker/{ignored_cve}">{ignored_cve}"""
> +                    """<i>(stale)</i></a><br/>\n""")
> +        else:
> +            f.write(f'    <a href="https://security-tracker.debian.org/tracker/{ignored_cve}">{ignored_cve}</a><br/>\n')
>       f.write("  </div>\n")
>   
>       # CPE ID
> @@ -1193,6 +1217,10 @@ def dump_html_stats(f, stats):
>               stats["pkg-unsure-cves"])
>       f.write('<div class="data">Total number of unsure CVEs affecting all packages</div><div class="data">%s</div>\n' %
>               stats["total-unsure-cves"])
> +    f.write('<div class="data">Packages with stale CVE ignores</div><div class="data">%s</div>\n' %
> +            stats["pkg-stale-cve-ignores"])
> +    f.write('<div class="data">Total number of stale CVE ignores affecting all packages</div><div class="data">%s</div>\n' %
> +            stats["total-stale-cve-ignores"])
>       f.write('<div class="data">Packages with CPE ID</div><div class="data">%s</div>\n' %
>               stats["cpe-id"])
>       f.write('<div class="data">Packages without CPE ID</div><div class="data">%s</div>\n' %

_______________________________________________
buildroot mailing list
buildroot@buildroot.org
https://lists.buildroot.org/mailman/listinfo/buildroot

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2025-06-04 17:15 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-23 15:29 [Buildroot] [RFC PATCH 1/1] support/scripts/pkg-stats: add support for reporting stale CVE entries Raphaël Mélotte via buildroot
2025-05-18  8:54 ` Thomas Petazzoni via buildroot
2025-06-04 17:15 ` Arnout Vandecappelle via buildroot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox