Skip to content

Commit b8a3931

Browse files
committed
Update NVD Importer v2 to use 2.0 API schema
Signed-off-by: ziad hany <[email protected]>
1 parent 5ea1f08 commit b8a3931

File tree

2 files changed

+24
-19
lines changed

2 files changed

+24
-19
lines changed

vulnerabilities/pipelines/nvd_importer.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import json
1212
import logging
1313
from datetime import date
14+
from datetime import timezone
1415
from traceback import format_exc as traceback_format_exc
1516
from typing import Iterable
1617

@@ -140,7 +141,7 @@ def to_advisories(cls, vulnerabilities, skip_hardware=True):
140141
Skip hardware
141142
"""
142143
for cve_item in CveItem.from_cve_data(
143-
vulnerabilities=vulnerabilities, skip_hardware=skip_hardware
144+
cve_data=vulnerabilities, skip_hardware=skip_hardware
144145
):
145146
yield cve_item.to_advisory()
146147

@@ -316,7 +317,9 @@ def to_advisory(self):
316317
aliases=[self.cve_id],
317318
summary=self.summary,
318319
references=self.references,
319-
date_published=dateparser.parse(self.cve_item["cve"].get("published")),
320+
date_published=dateparser.parse(self.cve_item["cve"].get("published")).replace(
321+
tzinfo=timezone.utc
322+
),
320323
weaknesses=self.weaknesses,
321324
url=f"https://nvd.nist.gov/vuln/detail/{self.cve_id}",
322325
)

vulnerabilities/pipelines/v2_importers/nvd_importer.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import json
1212
import logging
1313
from datetime import date
14+
from datetime import timezone
1415
from traceback import format_exc as traceback_format_exc
1516
from typing import Iterable
1617

@@ -93,7 +94,7 @@ def advisories_count(self):
9394
return advisory_count
9495

9596
def collect_advisories(self) -> Iterable[AdvisoryData]:
96-
for _year, cve_data in fetch_cve_data_1_1(logger=self.log):
97+
for _year, cve_data in fetch_cve_data_2_0(logger=self.log):
9798
yield from to_advisories(cve_data=cve_data)
9899

99100

@@ -111,15 +112,15 @@ def fetch(url, logger=None):
111112
return json.loads(data)
112113

113114

114-
def fetch_cve_data_1_1(starting_year=2025, logger=None):
115+
def fetch_cve_data_2_0(starting_year=2002, logger=None):
115116
"""
116117
Yield tuples of (year, lists of CVE mappings) from the NVD, one for each
117118
year since ``starting_year`` defaulting to 2002.
118119
"""
119120
current_year = date.today().year
120121
# NVD json feeds start from 2002.
121122
for year in range(starting_year, current_year + 1):
122-
download_url = f"https://nvd.nist.gov/feeds/json/cve/1.1/nvdcve-1.1-{year}.json.gz"
123+
download_url = f"https://nvd.nist.gov/feeds/json/cve/2.0/nvdcve-2.0-{year}.json.gz"
123124
yield year, fetch(url=download_url, logger=logger)
124125

125126

@@ -151,7 +152,7 @@ def from_cve_data(cls, cve_data, skip_hardware=True):
151152
"""
152153
Yield CVE items mapping from a cve_data list of CVE mappings from the NVD.
153154
"""
154-
for cve_item in cve_data.get("CVE_Items") or []:
155+
for cve_item in cve_data.get("vulnerabilities") or []:
155156
if not cve_item:
156157
continue
157158
if not isinstance(cve_item, dict):
@@ -163,7 +164,7 @@ def from_cve_data(cls, cve_data, skip_hardware=True):
163164

164165
@property
165166
def cve_id(self):
166-
return self.cve_item["cve"]["CVE_data_meta"]["ID"]
167+
return self.cve_item["cve"]["id"]
167168

168169
@property
169170
def summary(self):
@@ -175,8 +176,8 @@ def summary(self):
175176
# In the remaining 1% cases this returns the longest summary.
176177
# FIXME: we should retun the full description WITH the summry as the first line instead
177178
summaries = []
178-
for desc in get_item(self.cve_item, "cve", "description", "description_data") or []:
179-
if desc.get("value"):
179+
for desc in get_item(self.cve_item, "cve", "descriptions") or []:
180+
if desc.get("value") and desc.get("lang") == "en":
180181
summaries.append(desc["value"])
181182
return max(summaries, key=len) if summaries else None
182183

@@ -187,11 +188,12 @@ def cpes(self):
187188
"""
188189
# FIXME: we completely ignore the configurations here
189190
cpes = []
190-
for node in get_item(self.cve_item, "configurations", "nodes") or []:
191-
for cpe_data in node.get("cpe_match") or []:
192-
cpe23_uri = cpe_data.get("cpe23Uri")
193-
if cpe23_uri and cpe23_uri not in cpes:
194-
cpes.append(cpe23_uri)
191+
for nodes in get_item(self.cve_item, "cve", "configurations") or []:
192+
for node in nodes.get("nodes") or []:
193+
for cpe_data in node.get("cpeMatch") or []:
194+
cpe23_uri = cpe_data.get("criteria")
195+
if cpe23_uri and cpe23_uri not in cpes:
196+
cpes.append(cpe23_uri)
195197
return cpes
196198

197199
@property
@@ -250,7 +252,7 @@ def reference_urls(self):
250252
# FIXME: we should also collect additional data from the references such as tags and ids
251253

252254
urls = []
253-
for reference in get_item(self.cve_item, "cve", "references", "reference_data") or []:
255+
for reference in get_item(self.cve_item, "cve", "references") or []:
254256
ref_url = reference.get("url")
255257
if ref_url and ref_url.startswith(("http", "ftp")) and ref_url not in urls:
256258
urls.append(ref_url)
@@ -300,9 +302,7 @@ def weaknesses(self):
300302
Return a list of CWE IDs like: [119, 189]
301303
"""
302304
weaknesses = []
303-
for weaknesses_item in (
304-
get_item(self.cve_item, "cve", "problemtype", "problemtype_data") or []
305-
):
305+
for weaknesses_item in get_item(self.cve_item, "cve", "weaknesses") or []:
306306
weaknesses_description = weaknesses_item.get("description") or []
307307
for weaknesses_value in weaknesses_description:
308308
cwe_id = (
@@ -322,7 +322,9 @@ def to_advisory(self):
322322
aliases=[],
323323
summary=self.summary,
324324
references_v2=self.references,
325-
date_published=dateparser.parse(self.cve_item.get("publishedDate")),
325+
date_published=dateparser.parse(self.cve_item["cve"].get("published")).replace(
326+
tzinfo=timezone.utc
327+
),
326328
weaknesses=self.weaknesses,
327329
severities=self.severities,
328330
url=f"https://nvd.nist.gov/vuln/detail/{self.cve_id}",

0 commit comments

Comments
 (0)