Buildroot Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [Buildroot] [PATCH 1/3] support/scripts/pkg-stats: remove checking the CPE database
@ 2024-02-07 15:35 Arnout Vandecappelle via buildroot
  2024-02-07 15:35 ` [Buildroot] [PATCH 2/3] support/scripts/cve.py: switch from NVD to FKIE for the JSON files Arnout Vandecappelle via buildroot
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Arnout Vandecappelle via buildroot @ 2024-02-07 15:35 UTC (permalink / raw)
  To: buildroot

We currently check the CPE database to see if the CPE ID we use
(including the version) is already in the database.

However, the version part of the CPE ID is not actually used for CVE
matching. Instead, the CVEs have a range of versions associated with
them and we match against those ranges.

In addition, NVD is moving to a new API for accessing the CPE database.
It will not longer be possible to simply download all the CPE IDs, and
due to rate limiting, the download will have to be done in several
queries.

Since all of this is anyway of limited use, drop the CPE database lookup
entirely. Instead, as long as a CPE ID is defined in a package, it is
considered OK, without any checks.

Signed-off-by: Arnout Vandecappelle <arnout@mind.be>
---
 support/scripts/pkg-stats | 50 ++-------------------------------------
 1 file changed, 2 insertions(+), 48 deletions(-)

diff --git a/support/scripts/pkg-stats b/support/scripts/pkg-stats
index 05f0cd9e4a..caef159afe 100755
--- a/support/scripts/pkg-stats
+++ b/support/scripts/pkg-stats
@@ -40,7 +40,6 @@ from getdeveloperlib import parse_developers  # noqa: E402
 
 INFRA_RE = re.compile(r"\$\(eval \$\(([a-z-]*)-package\)\)")
 URL_RE = re.compile(r"\s*https?://\S*\s*$")
-CPEDB_URL = "https://static.nvd.nist.gov/feeds/xml/cpe/dictionary/official-cpe-dictionary_v2.3.xml.gz"
 
 RM_API_STATUS_ERROR = 1
 RM_API_STATUS_FOUND_BY_DISTRO = 2
@@ -282,8 +281,7 @@ class Package:
 
         if var in self.all_cpeids:
             self.cpeid = self.all_cpeids[var]
-            # Set a preliminary status, it might be overridden by check_package_cpes()
-            self.status['cpe'] = ("warning", "not checked against CPE dictionary")
+            self.status['cpe'] = ("ok", "(not checked against CPE dictionary)")
         else:
             self.status['cpe'] = ("error", "no verified CPE identifier")
 
@@ -674,47 +672,6 @@ def check_package_cves(nvd_path, packages):
                 pkg.status['cve'] = ("ok", "not affected by CVEs")
 
 
-def check_package_cpes(nvd_path, packages):
-    class CpeXmlParser:
-        cpes = []
-
-        def start(self, tag, attrib):
-            if tag == "{http://scap.nist.gov/schema/cpe-extension/2.3}cpe23-item":
-                self.cpes.append(attrib['name'])
-
-        def close(self):
-            return self.cpes
-
-    print("CPE: Setting up NIST dictionary")
-    if not os.path.exists(os.path.join(nvd_path, "cpe")):
-        os.makedirs(os.path.join(nvd_path, "cpe"))
-
-    cpe_dict_local = os.path.join(nvd_path, "cpe", os.path.basename(CPEDB_URL))
-    if not os.path.exists(cpe_dict_local) or os.stat(cpe_dict_local).st_mtime < time.time() - 86400:
-        print("CPE: Fetching xml manifest from [" + CPEDB_URL + "]")
-        cpe_dict = requests.get(CPEDB_URL)
-        open(cpe_dict_local, "wb").write(cpe_dict.content)
-
-    print("CPE: Unzipping xml manifest...")
-    nist_cpe_file = gzip.GzipFile(fileobj=open(cpe_dict_local, 'rb'))
-
-    parser = xml.etree.ElementTree.XMLParser(target=CpeXmlParser())
-    while True:
-        c = nist_cpe_file.read(1024*1024)
-        if not c:
-            break
-        parser.feed(c)
-    cpes = parser.close()
-
-    for p in packages:
-        if not p.cpeid:
-            continue
-        if p.cpeid in cpes:
-            p.status['cpe'] = ("ok", "verified CPE identifier")
-        else:
-            p.status['cpe'] = ("error", "CPE version unknown in CPE database")
-
-
 def calculate_stats(packages):
     stats = defaultdict(int)
     stats['packages'] = len(packages)
@@ -1309,7 +1266,7 @@ def parse_args():
     parser.add_argument('--nvd-path', dest='nvd_path',
                         help='Path to the local NVD database', type=resolvepath)
     parser.add_argument('--disable', type=list_str,
-                        help='Features to disable, comma-separated (cve, upstream, url, cpe, warning)',
+                        help='Features to disable, comma-separated (cve, upstream, url, warning)',
                         default=[])
     args = parser.parse_args()
     if not args.html and not args.json:
@@ -1372,9 +1329,6 @@ def __main__():
     if "cve" not in args.disable and args.nvd_path:
         print("Checking packages CVEs")
         check_package_cves(args.nvd_path, packages)
-    if "cpe" not in args.disable and args.nvd_path:
-        print("Checking packages CPEs")
-        check_package_cpes(args.nvd_path, packages)
     print("Calculate stats")
     stats = calculate_stats(packages)
     if args.html:
-- 
2.43.0

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

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

* [Buildroot] [PATCH 2/3] support/scripts/cve.py: switch from NVD to FKIE for the JSON files
  2024-02-07 15:35 [Buildroot] [PATCH 1/3] support/scripts/pkg-stats: remove checking the CPE database Arnout Vandecappelle via buildroot
@ 2024-02-07 15:35 ` Arnout Vandecappelle via buildroot
  2024-02-07 15:35 ` [Buildroot] [PATCH 3/3] support/scripts/cve.py: start in 1999 Arnout Vandecappelle via buildroot
  2024-02-07 16:41 ` [Buildroot] [PATCH 1/3] support/scripts/pkg-stats: remove checking the CPE database Thomas Petazzoni via buildroot
  2 siblings, 0 replies; 4+ messages in thread
From: Arnout Vandecappelle via buildroot @ 2024-02-07 15:35 UTC (permalink / raw)
  To: buildroot; +Cc: Daniel Lang

NVD will deprecate the v1.1 API which allows us to download the full
database as individual JSON files. Instead, there's a horribly crappy
API that is extremely slow and subject to race conditions.

Fortunately, there is a project, Fraunhofer FKIE - Cyber Analysis and
Defense [1], that goes through the effort of adapting to this new API
and regenerating the convenient JSON files. The JSON files and meta
files are re-generated daily.

Instead of implementing the NVD v2 API, we decided to just use the JSON
files generatd by fkie-cad. That saves us the effort of solving the race
conditions, devising a cache mechanism that works, handling the frequent
gateway timeouts on the NVD servers, dealing with the rate limiting, and
keeping up with changes in the API.

Switch to this repository on github as NVD_BASE_URL. The file name is
also slightly different (CVE-20XX.json instead of nvdcve-1.1-20XX.json).

The fkie-cad repository compresses with xz instead of gz. Therefore:
 - rename the filename variables to _xz instead of _gz;
 - use xz as a subprocess because there is no xz decompressor in Python
   stdlib.

[1] https://www.fkie.fraunhofer.de/en/departments/cad.html

Cc: Daniel Lang <dalang@gmx.at>
Signed-off-by: Arnout Vandecappelle <arnout@mind.be>
---
Even better would be to clone the
https://github.com/fkie-cad/nvd-json-data-feeds repository so we can
cache with simple "git pull". I leave that as an exercise to the reader
:-)
---
 support/scripts/cve.py | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)

diff --git a/support/scripts/cve.py b/support/scripts/cve.py
index 7cd6fce4d8..46c384955c 100755
--- a/support/scripts/cve.py
+++ b/support/scripts/cve.py
@@ -22,7 +22,7 @@ import os
 import requests  # URL checking
 import distutils.version
 import time
-import gzip
+import subprocess
 import sys
 import operator
 
@@ -41,8 +41,7 @@ except ImportError:
 sys.path.append('utils/')
 
 NVD_START_YEAR = 2002
-NVD_JSON_VERSION = "1.1"
-NVD_BASE_URL = "https://nvd.nist.gov/feeds/json/cve/" + NVD_JSON_VERSION
+NVD_BASE_URL = "https://github.com/fkie-cad/nvd-json-data-feeds/releases/latest/download"
 
 ops = {
     '>=': operator.ge,
@@ -83,15 +82,15 @@ class CVE:
 
     @staticmethod
     def download_nvd_year(nvd_path, year):
-        metaf = "nvdcve-%s-%s.meta" % (NVD_JSON_VERSION, year)
+        metaf = "CVE-%s.meta" % year
         path_metaf = os.path.join(nvd_path, metaf)
-        jsonf_gz = "nvdcve-%s-%s.json.gz" % (NVD_JSON_VERSION, year)
-        path_jsonf_gz = os.path.join(nvd_path, jsonf_gz)
+        jsonf_xz = "CVE-%s.json.xz" % year
+        path_jsonf_xz = os.path.join(nvd_path, jsonf_xz)
 
         # If the database file is less than a day old, we assume the NVD data
         # locally available is recent enough.
-        if os.path.exists(path_jsonf_gz) and os.stat(path_jsonf_gz).st_mtime >= time.time() - 86400:
-            return path_jsonf_gz
+        if os.path.exists(path_jsonf_xz) and os.stat(path_jsonf_xz).st_mtime >= time.time() - 86400:
+            return path_jsonf_xz
 
         # If not, we download the meta file
         url = "%s/%s" % (NVD_BASE_URL, metaf)
@@ -104,19 +103,19 @@ class CVE:
         # we need to re-download the database.
         # If the database does not exist locally, we need to redownload it in
         # any case.
-        if os.path.exists(path_metaf) and os.path.exists(path_jsonf_gz):
+        if os.path.exists(path_metaf) and os.path.exists(path_jsonf_xz):
             meta_known = open(path_metaf, "r").read()
             if page_meta.text == meta_known:
-                return path_jsonf_gz
+                return path_jsonf_xz
 
         # Grab the compressed JSON NVD, and write files to disk
-        url = "%s/%s" % (NVD_BASE_URL, jsonf_gz)
+        url = "%s/%s" % (NVD_BASE_URL, jsonf_xz)
         print("Getting %s" % url)
         page_json = requests.get(url)
         page_json.raise_for_status()
-        open(path_jsonf_gz, "wb").write(page_json.content)
+        open(path_jsonf_xz, "wb").write(page_json.content)
         open(path_metaf, "w").write(page_meta.text)
-        return path_jsonf_gz
+        return path_jsonf_xz
 
     @classmethod
     def read_nvd_dir(cls, nvd_dir):
@@ -128,7 +127,8 @@ class CVE:
         for year in range(NVD_START_YEAR, datetime.datetime.now().year + 1):
             filename = CVE.download_nvd_year(nvd_dir, year)
             try:
-                content = ijson.items(gzip.GzipFile(filename), 'CVE_Items.item')
+                uncompressed = subprocess.check_output(["xz", "-d", "-c", filename])
+                content = ijson.items(uncompressed, 'CVE_Items.item')
             except:  # noqa: E722
                 print("ERROR: cannot read %s. Please remove the file then rerun this script" % filename)
                 raise
-- 
2.43.0

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

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

* [Buildroot] [PATCH 3/3] support/scripts/cve.py: start in 1999
  2024-02-07 15:35 [Buildroot] [PATCH 1/3] support/scripts/pkg-stats: remove checking the CPE database Arnout Vandecappelle via buildroot
  2024-02-07 15:35 ` [Buildroot] [PATCH 2/3] support/scripts/cve.py: switch from NVD to FKIE for the JSON files Arnout Vandecappelle via buildroot
@ 2024-02-07 15:35 ` Arnout Vandecappelle via buildroot
  2024-02-07 16:41 ` [Buildroot] [PATCH 1/3] support/scripts/pkg-stats: remove checking the CPE database Thomas Petazzoni via buildroot
  2 siblings, 0 replies; 4+ messages in thread
From: Arnout Vandecappelle via buildroot @ 2024-02-07 15:35 UTC (permalink / raw)
  To: buildroot

When the CVE lookup was added in commit
4a157be9efac8ba8888e4972f42eda213077152c, the starting year of the JSON
files was set to 2002. However, there are also CVEs from 1999, 2000 and
2001. It is not clear why these were skipped back then.

Set the start year to 1999 to capture these old CVEs too.

Signed-off-by: Arnout Vandecappelle <arnout@mind.be>
---
 support/scripts/cve.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/support/scripts/cve.py b/support/scripts/cve.py
index 46c384955c..f12a8048cd 100755
--- a/support/scripts/cve.py
+++ b/support/scripts/cve.py
@@ -40,7 +40,7 @@ except ImportError:
 
 sys.path.append('utils/')
 
-NVD_START_YEAR = 2002
+NVD_START_YEAR = 1999
 NVD_BASE_URL = "https://github.com/fkie-cad/nvd-json-data-feeds/releases/latest/download"
 
 ops = {
-- 
2.43.0

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

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

* Re: [Buildroot] [PATCH 1/3] support/scripts/pkg-stats: remove checking the CPE database
  2024-02-07 15:35 [Buildroot] [PATCH 1/3] support/scripts/pkg-stats: remove checking the CPE database Arnout Vandecappelle via buildroot
  2024-02-07 15:35 ` [Buildroot] [PATCH 2/3] support/scripts/cve.py: switch from NVD to FKIE for the JSON files Arnout Vandecappelle via buildroot
  2024-02-07 15:35 ` [Buildroot] [PATCH 3/3] support/scripts/cve.py: start in 1999 Arnout Vandecappelle via buildroot
@ 2024-02-07 16:41 ` Thomas Petazzoni via buildroot
  2 siblings, 0 replies; 4+ messages in thread
From: Thomas Petazzoni via buildroot @ 2024-02-07 16:41 UTC (permalink / raw)
  To: Arnout Vandecappelle via buildroot

On Wed,  7 Feb 2024 16:35:17 +0100
Arnout Vandecappelle via buildroot <buildroot@buildroot.org> wrote:

> We currently check the CPE database to see if the CPE ID we use
> (including the version) is already in the database.
> 
> However, the version part of the CPE ID is not actually used for CVE
> matching. Instead, the CVEs have a range of versions associated with
> them and we match against those ranges.
> 
> In addition, NVD is moving to a new API for accessing the CPE database.
> It will not longer be possible to simply download all the CPE IDs, and
> due to rate limiting, the download will have to be done in several
> queries.
> 
> Since all of this is anyway of limited use, drop the CPE database lookup
> entirely. Instead, as long as a CPE ID is defined in a package, it is
> considered OK, without any checks.
> 
> Signed-off-by: Arnout Vandecappelle <arnout@mind.be>
> ---
>  support/scripts/pkg-stats | 50 ++-------------------------------------
>  1 file changed, 2 insertions(+), 48 deletions(-)

Series applied, thanks! There were only a few flake8 warnings on PATCH
1/3 due to Python imports that were no longer needed.

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] 4+ messages in thread

end of thread, other threads:[~2024-02-07 16:42 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-07 15:35 [Buildroot] [PATCH 1/3] support/scripts/pkg-stats: remove checking the CPE database Arnout Vandecappelle via buildroot
2024-02-07 15:35 ` [Buildroot] [PATCH 2/3] support/scripts/cve.py: switch from NVD to FKIE for the JSON files Arnout Vandecappelle via buildroot
2024-02-07 15:35 ` [Buildroot] [PATCH 3/3] support/scripts/cve.py: start in 1999 Arnout Vandecappelle via buildroot
2024-02-07 16:41 ` [Buildroot] [PATCH 1/3] support/scripts/pkg-stats: remove checking the CPE database Thomas Petazzoni via buildroot

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