I counted the CVEs published each month, straight from the CVE Program's own list. Then I marked the first month above 750, then above each doubled level. Each crossing came faster than the last: 12 years, 7 years, 2 years, then 5 months.

Animated bar chart titled Security flaws published each month, and how long each doubling took. One thin bar per month of CVE records, from 1999 to October 22, 2026, draws in from left to right. A ceiling line marks the current level and bends each time a month breaks through. The gaps appear on the right: 12 years, 7 years, 2 years, 5 months. The last frame shows September 2026 at 14,934, more than all of 2017 at 14,642, a dotted line for October on pace for 18,400, and a question mark beside 24,000.

September 2026 alone had 14,934 new CVEs. All of 2017 had 14,642. Below is the script that produces these numbers, in standard-library Python.

What gets counted

  • The source is the cvelistV5 release cve_2026-10-23_0400Z (release). Its asset 2026-10-23_all_CVEs_at_midnight.zip.zip holds 413,350 records.
  • Each PUBLISHED record counts in the month of cveMetadata.datePublished. That's when the record entered the CVE list (record format).
  • The 18,630 REJECTED records are left out.
  • 2026 runs through October 22. Four records from early on October 23 are left out.

So this measures publication volume. It doesn't count new bugs. A record published today can describe a flaw found years ago.

The ladder

Level First month above it CVEs that month Time since the last level
750 February 2005 821 Start
1,500 April 2017 1,568 12 years 2 months
3,000 March 2024 3,299 6 years 11 months
6,000 March 2026 6,236 2 years
12,000 August 2026 12,260 5 months

"Above" means strictly above. The gaps are between calendar months, with no interpolated crossing day.

The script

The asset is a zip with one zip inside, cves.zip. The script extracts that inner zip, about 710 MB, to a temporary folder. Then it reads every record.

# count_cves.py: published CVE records per month, from a cvelistV5 release asset. # Usage: python3 count_cves.py ASSET.zip.zip [CUTOFF] import collections import json import sys import tempfile import zipfile asset = sys.argv[1] cutoff = sys.argv[2] if len(sys.argv) > 2 else "9999" # e.g. 2026-10-23 skips that day on  per_month = collections.Counter() with tempfile.TemporaryDirectory() as tmp: # The asset is a zip with one zip inside. Extract the inner one first.  with zipfile.ZipFile(asset) as outer: inner = outer.extract(outer.namelist()[0], tmp) with zipfile.ZipFile(inner) as records: for name in records.namelist(): if not name.rsplit("/", 1)[-1].startswith("CVE-"): continue # folders, delta.json and deltaLog.json  meta = json.loads(records.read(name))["cveMetadata"] # ISO timestamps sort as text, so a string comparison works.  if meta["state"] == "PUBLISHED" and meta["datePublished"] < cutoff: per_month[meta["datePublished"][:7]] += 1 for month, count in sorted(per_month.items()): print(month, count) # The doubling ladder: the first month above each level, starting at 750. level = 750 for month, count in sorted(per_month.items()): while count > level: print(f"Above {level:,}: {month} ({count:,})") level *= 2 

Pass a cutoff date to leave out the snapshot day's own records:

python3 count_cves.py 2026-10-23_all_CVEs_at_midnight.zip.zip 2026-10-23 > counts.txt grep '^2026-09 ' counts.txt # 2026-09 14934 awk '/^2026/ {s += $2} END {print s}' counts.txt # 85838 tail -5 counts.txt 

The last five lines are the ladder:

Above 750: 2005-02 (821) Above 1,500: 2017-04 (1,568) Above 3,000: 2024-03 (3,299) Above 6,000: 2026-03 (6,236) Above 12,000: 2026-08 (12,260) 

Without the cutoff, October shows 13,040 instead of 13,036. The extra four are the October 23 records.

NVD keeps its own database. Its CVE API gives a quick cross-check for one month:

curl -s 'https://services.nvd.nist.gov/rest/json/cves/2.0?pubStartDate=2026-09-01T00:00:00.000&pubEndDate=2026-09-30T23:59:59.999&noRejected&resultsPerPage=1' \ | python3 -c 'import json, sys; print(json.load(sys.stdin)["totalResults"])' 

On October 23 it returned 14,933 for September (query). In three months checked, NVD differed from the CVE list by zero to two records. Count all non-rejected records there, not just enriched ones.

Pin the snapshot when you compare numbers. Records get rejected later. The CVE Program has also corrected historical dates (README). So a later snapshot will differ a little.

How solid the pattern is

It depends on the starting level. I picked 750. Here are the gaps from other starts, same data:

Start Gaps between first crossings
500 12y 6m, 3y 10m, 5y 10m, 2y 2m (16,000 not reached yet)
750 12y 2m, 6y 11m, 2y, 5m
800 13y 2m, 5y 11m, 2y 2m, 4m
900 10y 9m, 5y 9m, 2y 2m, 3m
1,000 3y 10m, 5y 10m, 2y 2m (16,000 not reached yet)

800 and 900 give roughly the same shape, with different timings. 500 and 1,000 break it: the climb that ends in 2018 is shorter than the one after it.

The date field matters too. Group the same records by dateReserved instead. The gaps become 11y 9m, 4y 2m, 4y 3m, then 1y 5m. The third step is no faster than the second.

A smoother check agrees on the direction. Twelve-month rolling totals first passed 5,000 in July 2005. Then 10,000 in June 2017, 20,000 in December 2021, 40,000 in January 2025 and 80,000 in September 2026. The gaps were 11.9, 4.5, 3.1 and 1.7 years.

So the ladder describes this list, counted this way. It's not a law. It doesn't say when 24,000 comes.

Why the count is rising

In June, FIRST raised its 2026 forecast to about 66,000 CVEs (FIRST). Its February median had been 59,427. It named AI-assisted discovery, changes in reporting, and CNAs working through backlogs. A CNA is an organization allowed to assign CVE IDs.

My count passed 66,000 on September 16. By October 22 it was at 85,838. October 1–22 added 13,036 CVEs. Keeping that daily average would put October near 18,400. That's an extrapolation.

AI is part of why. Google's threat intelligence team (GTIG) says AI is measurably changing how fast vulnerabilities are found (GTIG). Half its likely AI-found vulnerabilities could allow remote code execution. That compares with 26% in its non-AI group. That covers January to August 2026, and the AI label is GTIG's own heuristic.

Some of the rise is bookkeeping. Kernel.org became a CNA in February 2024 (CVE Program). Its policy leans toward assigning a CVE to fixes that could be security-relevant. That happens automatically once the fix reaches a stable tree (kernel.org). Not every commit gets one. GTIG counted about 5,000 CVEs from January to August whose descriptions mention the Linux kernel.

Backlogs come in bursts. When old findings get published together, the month spikes. That spike isn't new bugs.

This count can't say how much of the rise each cause explains.

What to patch first

Since April 15, NIST's NVD enriches three groups first (NIST). Those are CVEs in CISA's KEV catalog, software the federal government uses, and critical software under Executive Order 14028. They're categories, not a severity cutoff. Other CVEs stay listed, as "Lowest Priority - not scheduled for immediate enrichment." You can still request enrichment.

Only about 1 in 431 of this year's CVEs had been seen exploited by August. That's GTIG's figure: 0.23% of 2026 disclosures, January to August, by the exploitation it observed. It isn't a lifetime probability.

This part is my opinion. Finding bugs got cheap. Fixing them didn't. Patching everything is no longer a plan. That's no reason to skip routine updates. It's a reason to decide what comes first.

The public guidance supports an order like this:

  1. Start with what you actually run. A CVE in a package you don't deploy isn't on your list.
  2. Known exploitation first. CISA's KEV catalog lists vulnerabilities known to be exploited in the wild. Its JSON feed had 1,754 entries on October 21. It isn't complete.
  3. EPSS for likelihood. FIRST's EPSS gives a probability from 0 to 1. It estimates observed exploitation in the wild over the next 30 days. Version 5 has run since June 15, 2026 (FIRST). Scores update daily. A score isn't the chance your system gets breached. A percentile isn't the probability. A low score never overrules known exploitation.
  4. SSVC for context. CISA's SSVC is a decision tree. It weighs exploitation, technical impact, automatability, mission prevalence and public well-being. It ends in Track, Track*, Attend or Act. Even Track means fixing within your normal update cycle.
  5. CVSS severity as one input. FIRST's CVSS v4.0 FAQ says base scores describe technical severity. They shouldn't set patch priority on their own.

The maintained article is on argbe.tech. It has the yearly totals since 1999, the chart as a video and every source.