summaryrefslogtreecommitdiff
path: root/poky/meta/recipes-core/meta/cve-update-nvd2-native.bb
diff options
context:
space:
mode:
Diffstat (limited to 'poky/meta/recipes-core/meta/cve-update-nvd2-native.bb')
-rw-r--r--poky/meta/recipes-core/meta/cve-update-nvd2-native.bb66
1 files changed, 37 insertions, 29 deletions
diff --git a/poky/meta/recipes-core/meta/cve-update-nvd2-native.bb b/poky/meta/recipes-core/meta/cve-update-nvd2-native.bb
index 2b585983ac..2f7dad7e82 100644
--- a/poky/meta/recipes-core/meta/cve-update-nvd2-native.bb
+++ b/poky/meta/recipes-core/meta/cve-update-nvd2-native.bb
@@ -17,6 +17,10 @@ deltask do_populate_sysroot
NVDCVE_URL ?= "https://services.nvd.nist.gov/rest/json/cves/2.0"
+# If you have a NVD API key (https://nvd.nist.gov/developers/request-an-api-key)
+# then setting this to get higher rate limits.
+NVDCVE_API_KEY ?= ""
+
# CVE database update interval, in seconds. By default: once a day (24*60*60).
# Use 0 to force the update
# Use a negative value to skip the update
@@ -119,18 +123,16 @@ def nvd_request_next(url, api_key, args):
import urllib.parse
import gzip
import http
+ import time
- headers = {}
+ request = urllib.request.Request(url + "?" + urllib.parse.urlencode(args))
if api_key:
- headers['apiKey'] = api_key
-
- data = urllib.parse.urlencode(args)
-
- full_request = url + '?' + data
+ request.add_header("apiKey", api_key)
+ bb.note("Requesting %s" % request.full_url)
- for attempt in range(3):
+ for attempt in range(5):
try:
- r = urllib.request.urlopen(full_request)
+ r = urllib.request.urlopen(request)
if (r.headers['content-encoding'] == 'gzip'):
buf = r.read()
@@ -140,13 +142,9 @@ def nvd_request_next(url, api_key, args):
r.close()
- except UnicodeDecodeError:
- # Received garbage, retry
- bb.debug(2, "CVE database: received malformed data, retrying (request: %s)" %(full_request))
- pass
- except http.client.IncompleteRead:
- # Read incomplete, let's try again
- bb.debug(2, "CVE database: received incomplete data, retrying (request: %s)" %(full_request))
+ except Exception as e:
+ bb.note("CVE database: received error (%s), retrying" % (e))
+ time.sleep(6)
pass
else:
return raw_data
@@ -172,11 +170,11 @@ def update_db_file(db_tmp_file, d, database_time):
# The maximum range for time is 120 days
# Force a complete update if our range is longer
if (database_time != 0):
- database_date = datetime.datetime.combine(datetime.date.fromtimestamp(database_time), datetime.time())
- today_date = datetime.datetime.combine(datetime.date.today(), datetime.time())
+ database_date = datetime.datetime.fromtimestamp(database_time, tz=datetime.timezone.utc)
+ today_date = datetime.datetime.now(tz=datetime.timezone.utc)
delta = today_date - database_date
if delta.days < 120:
- bb.debug(2, "CVE database: performing partial update")
+ bb.note("CVE database: performing partial update")
req_args['lastModStartDate'] = database_date.isoformat()
req_args['lastModEndDate'] = today_date.isoformat()
else:
@@ -184,12 +182,14 @@ def update_db_file(db_tmp_file, d, database_time):
with bb.progress.ProgressHandler(d) as ph, open(os.path.join(d.getVar("TMPDIR"), 'cve_check'), 'a') as cve_f:
- bb.debug(2, "Updating entries")
+ bb.note("Updating entries")
index = 0
url = d.getVar("NVDCVE_URL")
+ api_key = d.getVar("NVDCVE_API_KEY") or None
+
while True:
req_args['startIndex'] = index
- raw_data = nvd_request_next(url, None, req_args)
+ raw_data = nvd_request_next(url, api_key, req_args)
if raw_data is None:
# We haven't managed to download data
return False
@@ -199,7 +199,7 @@ def update_db_file(db_tmp_file, d, database_time):
index = data["startIndex"]
total = data["totalResults"]
per_page = data["resultsPerPage"]
-
+ bb.note("Got %d entries" % per_page)
for cve in data["vulnerabilities"]:
update_db(conn, cve)
@@ -312,22 +312,30 @@ def update_db(conn, elt):
cvssv2 = elt['cve']['metrics']['cvssMetricV2'][0]['cvssData']['baseScore']
except KeyError:
cvssv2 = 0.0
+ cvssv3 = None
try:
- accessVector = accessVector or elt['impact']['baseMetricV3']['cvssV3']['attackVector']
- cvssv3 = elt['impact']['baseMetricV3']['cvssV3']['baseScore']
+ accessVector = accessVector or elt['cve']['metrics']['cvssMetricV30'][0]['cvssData']['attackVector']
+ cvssv3 = elt['cve']['metrics']['cvssMetricV30'][0]['cvssData']['baseScore']
except KeyError:
- accessVector = accessVector or "UNKNOWN"
- cvssv3 = 0.0
+ pass
+ try:
+ accessVector = accessVector or elt['cve']['metrics']['cvssMetricV31'][0]['cvssData']['attackVector']
+ cvssv3 = cvssv3 or elt['cve']['metrics']['cvssMetricV31'][0]['cvssData']['baseScore']
+ except KeyError:
+ pass
+ accessVector = accessVector or "UNKNOWN"
+ cvssv3 = cvssv3 or 0.0
conn.execute("insert or replace into NVD values (?, ?, ?, ?, ?, ?)",
[cveId, cveDesc, cvssv2, cvssv3, date, accessVector]).close()
try:
- configurations = elt['cve']['configurations'][0]['nodes']
- for config in configurations:
- parse_node_and_insert(conn, config, cveId)
+ for config in elt['cve']['configurations']:
+ # This is suboptimal as it doesn't handle AND/OR and negate, but is better than nothing
+ for node in config["nodes"]:
+ parse_node_and_insert(conn, node, cveId)
except KeyError:
- bb.debug(2, "Entry without a configuration")
+ bb.note("CVE %s has no configurations" % cveId)
do_fetch[nostamp] = "1"