In April 2026, NIST changed how the National Vulnerability Database handles new CVEs. It now prioritizes enrichment (CPE product lists, NVD severity scores) for CVEs in CISA's KEV catalog, software used in the federal government, and critical software as defined by Executive Order 14028. Everything else is still listed, but at the lowest priority.
We wanted to see what that looks like six months later. We pulled every CVE published between 1 September and 15 October 2026 from the NVD API on 18 October and counted the status of each. Of 23,469 non-rejected records, 5,915 are Analyzed and 6,119 have CPE configuration data.
How we counted
We queried the NVD CVE API 2.0 on 18 October 2026 between 08:09 and 08:15 UTC, with a publication date filter. Sleep between pages and retry any HTTP 429.
for i in $(seq 0 2000 22000); do
curl -sS -o "p_$i.json" "https://services.nvd.nist.gov/rest/json/cves/2.0?\
pubStartDate=2026-09-01T00:00:00.000Z&pubEndDate=2026-10-15T23:59:59.999Z\
&resultsPerPage=2000&startIndex=$i"
sleep 8
done
import json, glob, collections
cves = {}
for p in glob.glob("p_*.json"):
for v in json.load(open(p))["vulnerabilities"]:
cves[v["cve"]["id"]] = v["cve"]
live = [c for c in cves.values() if c["vulnStatus"] != "Rejected"]
N = len(live)
def nvd_score(c):
return any(m.get("source") == "nvd@nist.gov"
for ms in c.get("metrics", {}).values() for m in ms)
def any_score(c):
return any(c.get("metrics", {}).values())
def has_cpe(c):
return bool(c.get("configurations"))
for s, k in collections.Counter(c["vulnStatus"] for c in live).most_common():
print(s, k, round(100 * k / N, 1))
print("CPE configurations:", sum(map(has_cpe, live)))
print("CVSS from NVD itself:", sum(map(nvd_score, live)))
print("no CVSS or SSVC metric from anyone:", sum(not any_score(c) for c in live))
for lo, hi in [("01", "09"), ("10", "19"), ("20", "30")]:
for m in ("2026-09", "2026-10"):
part = [c for c in live if f"{m}-{lo}" <= c["published"][:10] <= f"{m}-{hi}"]
if part:
print(m, lo, hi, len(part),
round(100 * sum(c["vulnStatus"] == "Analyzed" for c in part) / len(part), 1),
round(100 * sum(map(has_cpe, part)) / len(part), 1))
"CPE configurations" means the record has a non-empty configurations array, the product applicability data most scanners match on. "CVSS from NVD itself" means at least one metric with source equal to nvd@nist.gov.
What's affected
Status of the 23,469 non-rejected CVEs published 1 September to 15 October 2026, as of 18 October:
| NVD status | CVEs | Share |
|---|---|---|
| Deferred | 9,571 | 40.8% |
| Analyzed | 5,915 | 25.2% |
| Awaiting Analysis | 4,636 | 19.8% |
| Received | 2,258 | 9.6% |
| Undergoing Analysis | 915 | 3.9% |
| Modified | 174 | 0.7% |
Other counts across the same set:
| Measure | CVEs |
|---|---|
| Has CPE configuration data | 6,119 |
| Has a CVSS metric from NVD itself | 1,134 |
| Has no CVSS or SSVC metric from any source | 1,618 |
Most records still carry a score from somewhere. The CNA or CISA's ADP container usually supplies CVSS or SSVC, which fits NIST's April statement that it will "no longer routinely provide a separate severity score" when the CNA already has.
Older records in the window are better covered, as you'd expect:
| Published | CVEs | Analyzed | Has CPE |
|---|---|---|---|
| 1 to 9 Sep | 4,395 | 50.9% | 52.8% |
| 10 to 19 Sep | 6,039 | 21.7% | 22.7% |
| 20 to 30 Sep | 4,502 | 19.5% | 20.2% |
| 1 to 9 Oct | 3,540 | 23.4% | 24.1% |
| 10 to 15 Oct | 4,993 | 13.3% | 13.3% |
Status depends heavily on who published the CVE. A second pass maps each record's source to a name (the src_*.json files come from the NVD Source API, see sources) and checks the KEV CVEs:
import json, glob, collections
cves = {v["cve"]["id"]: v["cve"] for p in glob.glob("p_*.json")
for v in json.load(open(p))["vulnerabilities"]}
name = {i: s["name"] for p in glob.glob("src_*.json")
for s in json.load(open(p))["sources"] for i in s.get("sourceIdentifiers", [])}
live = [c for c in cves.values() if c["vulnStatus"] != "Rejected"]
by = collections.defaultdict(collections.Counter)
for c in live:
by[name.get(c["sourceIdentifier"], c["sourceIdentifier"])][c["vulnStatus"]] += 1
for n in sorted(by, key=lambda n: -sum(by[n].values()))[:10]:
print(n, sum(by[n].values()), dict(by[n]))
kev = [v["cveID"] for v in json.load(open("kev.json"))["vulnerabilities"]
if "2026-09-01" <= v["dateAdded"] <= "2026-10-16"]
print(collections.Counter(cves[c]["vulnStatus"] for c in kev if c in cves))
| Source | CVEs | Analyzed | Deferred | Other statuses |
|---|---|---|---|---|
| VulnCheck | 2,893 | 205 | 2,151 | 537 |
| Microsoft Corporation | 2,447 | 1,477 | 0 | 970 |
| kernel.org | 2,383 | 20 | 0 | 2,363 (2,258 Received) |
| GitHub, Inc. | 2,218 | 352 | 1,251 | 615 |
| VulDB | 1,286 | 17 | 1,254 | 15 |
| Patchstack | 1,040 | 0 | 1,040 | 0 |
| WPScan | 829 | 0 | 829 | 0 |
| Chrome | 772 | 715 | 0 | 57 |
| MITRE | 724 | 78 | 486 | 160 |
| Wordfence | 716 | 0 | 716 | 0 |
The prioritization is visible. 38 of the KEV CVEs added between 1 September and 16 October were also published in this window. 37 are Analyzed with CPE data, and the 38th, CVE-2026-21589, has since been rejected.
How to check if you're exposed
The exposure is any tool that matches vulnerabilities to your software using NVD CPE data alone. For a CVE with no CPE configuration, that tool has nothing to match on and reports nothing. Test it with your own findings list:
python3 -I -c '
import json, glob
mine = set(open("my_cves.txt").read().split())
for p in glob.glob("p_*.json"):
for v in json.load(open(p))["vulnerabilities"]:
c = v["cve"]
if c["id"] in mine and not c.get("configurations"):
print(c["id"], c["vulnStatus"])
'
Then do the reverse test. Take a library you know is affected by a recent GitHub CNA CVE, and check whether your scanner flags it. If it doesn't, find out which data source it relies on.
What to do now
- Ask your vendors where their matching data comes from. CPE-only matching misses most new CVEs in this window. Package advisories (GHSA, OSV) carry package names and version ranges instead.
- Use the CNA's own data. The CVE record from the CNA often has affected versions and a CVSS score even when NVD has not enriched it.
- Don't read "Deferred" as "not important." WordPress plugin CNAs had every record deferred. If you run WordPress, those still apply to you.
- Request enrichment when it matters. NIST says users can email nvd at nist.gov to request enrichment of a lowest priority CVE.
- Track the kernel separately. 2,258 kernel.org records sat at Received. Patch by kernel version, not by waiting for CPE data.
Why it matters
NVD's change was announced and the reasons were stated plainly. The effect on downstream tooling is the part teams haven't caught up with. Most CVEs published in this window have no NVD product data, and the gap is widest for the newest records.
That doesn't make NVD less useful for KEV CVEs, which were all enriched here. It means a vulnerability program built on one data source will see a shrinking slice of new CVEs.
Try it yourself
Generate or import an SBOM for one service and compare two lists: findings matched by package identifier and findings matched by CPE. The difference is the coverage you'd lose with CPE alone. The demo below shows importing an SBOM and analyzing it against package advisories.
Click through it at your own pace, or open it full screen.
Quick check
How many CVEs published from 1 September to 15 October 2026 had NVD CPE data on 18 October?
6,119 of 23,469 non-rejected records.
Were KEV CVEs from this window enriched?
Yes. All 37 non-rejected KEV CVEs published in the window were Analyzed and had CPE data.
Which status did most kernel.org CVEs have?
Received: 2,258 of 2,383.