@@ -247,27 +247,80 @@ def format_data_api2(self, all_cve_entries):
247
247
continue
248
248
249
249
# Multiple ways of including CVSS metrics.
250
- cve_cvss = cve_item
251
- if "metrics" in cve_item :
250
+ # Newer data uses "impact" -- we may wish to delete the old below
251
+
252
+ # sometimes (frequently?) the impact is empty
253
+ if "impact" in cve_item :
254
+ if "baseMetricV3" in cve_item ["impact" ]:
255
+ cve ["CVSS_version" ] = 3
256
+ if "cvssV3" in cve_item ["impact" ]["baseMetricV3" ]:
257
+ # grab either the data or some default values
258
+ cve ["severity" ] = cve_item ["impact" ]["baseMetricV3" ][
259
+ "cvssV3"
260
+ ].get ("baseSeverity" , "UNKNOWN" )
261
+ cve ["score" ] = cve_item ["impact" ]["baseMetricV3" ]["cvssV3" ].get (
262
+ "baseScore" , 0
263
+ )
264
+ cve ["CVSS_vector" ] = cve_item ["impact" ]["baseMetricV3" ][
265
+ "cvssV3"
266
+ ].get ("vectorString" , "" )
267
+
268
+ # severity is in a different spot in v2 versus v3
269
+ elif "baseMetricV2" in cve_item ["impact" ]:
270
+ cve ["CVSS_version" ] = 2
271
+ cve ["severity" ] = cve_item ["impact" ]["baseMetricV4" ].get (
272
+ "severity" , "UNKNOWN"
273
+ )
274
+ if "cvssV2" in cve_item ["impact" ]["baseMetricV2" ]:
275
+ cve ["score" ] = cve_item ["impact" ]["baseMetricV2" ]["cvssV2" ].get (
276
+ "baseScore" , 0
277
+ )
278
+ cve ["CVSS_vector" ] = cve_item ["impact" ]["baseMetricV2" ][
279
+ "cvssV2"
280
+ ].get ("vectorString" , "" )
281
+
282
+ # Old data used "metrics" -- This section may need to be deleted
283
+ elif "metrics" in cve_item :
252
284
cve_cvss = cve_item ["metrics" ]
253
- # Get CVSSv3 or CVSSv2 score
254
- cvss_available = True
255
- if "cvssMetricV31" in cve_cvss :
256
- cvss_data = cve_cvss ["cvssMetricV31" ][0 ]["cvssData" ]
257
- cve ["CVSS_version" ] = 3
258
- elif "cvssMetricV30" in cve_cvss :
259
- cvss_data = cve_cvss ["cvssMetricV30" ][0 ]["cvssData" ]
260
- cve ["CVSS_version" ] = 3
261
- elif "cvssMetricV2" in cve_cvss :
262
- cvss_data = cve_cvss ["cvssMetricV2" ][0 ]["cvssData" ]
263
- cve ["CVSS_version" ] = 2
264
- else :
265
- LOGGER .debug (f"Unknown CVSS metrics field { cve_item ['id' ]} " )
266
- cvss_available = False
267
- if cvss_available :
268
- cve ["severity" ] = cvss_data .get ("baseSeverity" , "UNKNOWN" )
269
- cve ["score" ] = cvss_data .get ("baseScore" , 0 )
270
- cve ["CVSS_vector" ] = cvss_data .get ("vectorString" , "" )
285
+
286
+ # Get CVSSv3 or CVSSv2 score
287
+ cvss_available = True
288
+ if "cvssMetricV31" in cve_cvss :
289
+ cvss_data = cve_cvss ["cvssMetricV31" ][0 ]["cvssData" ]
290
+ cve ["CVSS_version" ] = 3
291
+ elif "cvssMetricV30" in cve_cvss :
292
+ cvss_data = cve_cvss ["cvssMetricV30" ][0 ]["cvssData" ]
293
+ cve ["CVSS_version" ] = 3
294
+ elif "cvssMetricV2" in cve_cvss :
295
+ cvss_data = cve_cvss ["cvssMetricV2" ][0 ]["cvssData" ]
296
+ cve ["CVSS_version" ] = 2
297
+ else :
298
+ cvss_available = False
299
+ if cvss_available :
300
+ cve ["severity" ] = cvss_data .get ("baseSeverity" , "UNKNOWN" )
301
+ cve ["score" ] = cvss_data .get ("baseScore" , 0 )
302
+ cve ["CVSS_vector" ] = cvss_data .get ("vectorString" , "" )
303
+ # End old metrics section
304
+
305
+ # do some basic input validation checks
306
+ # severity should be alphanumeric
307
+ if not cve ["severity" ].isalnum ():
308
+ self .logger .debug (
309
+ f"Severity for { cve ['id' ]} is invalid: { cve ['severity' ]} "
310
+ )
311
+ cve ["severity" ] = re .sub (r"[\W]" , "" , cve ["severity" ])
312
+
313
+ # score should be numeric
314
+ try :
315
+ cve ["score" ] = float (cve ["score" ])
316
+ except ValueError :
317
+ self .logger .debug (f"Score for { cve ['id' ]} is invalid: { cve ['score' ]} " )
318
+ cve ["score" ] = "invalid"
319
+
320
+ # CVSS_vector will be validated/normalized when cvss library is used but
321
+ # we can at least do a character filter here
322
+ # we expect letters (mostly but not always uppercase), numbers, : and /
323
+ cve ["CVSS_vector" ] = re .sub ("[^A-Za-z0-9:/]" , "" , cve ["CVSS_vector" ])
271
324
272
325
cve_data .append (cve )
273
326
0 commit comments