Skip to content

Latest commit

 

History

204 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

What CVEs keep teaching us

Refreshed daily from upstream cvelistV5 — pull this page tomorrow and the rankings will have moved.

108,132 CVEs across 673 distinct CWEs since 2024.

What mistake do engineers keep making most often since 2024?

Top 10 CWE by CVE count.

Rank CWE Name CVEs Avg score
1 79 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') 16,489 6.16
2 89 Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') 7,414 7.44
3 862 Missing Authorization 5,830 5.92
4 74 Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection') 4,114 7.02
5 352 Cross-Site Request Forgery (CSRF) 3,183 5.79
6 22 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal') 3,027 7.17
7 94 Improper Control of Generation of Code ('Code Injection') 2,604 6.72
8 78 Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') 2,288 8.08
9 416 Use After Free 2,223 7.65
10 20 Improper Input Validation 2,137 6.97

When that mistake is made, how bad is it since 2024?

Top 10 CWE by average CVSS score. Min 10 CVEs to suppress single-CWE outliers.

Rank CWE Name CVEs Avg score Max
1 506 Embedded Malicious Code 44 9.09 10.0
2 95 Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection') 119 8.50 10.0
3 288 Authentication Bypass Using an Alternate Path or Channel 430 8.32 10.0
4 502 Deserialization of Untrusted Data 1,616 8.31 10.0
5 565 Reliance on Cookies without Validation and Integrity Checking 16 8.29 9.8
6 917 Improper Neutralization of Special Elements used in an Expression Language Statement ('Expression Language Injection') 29 8.21 10.0
7 29 Path Traversal: '..filename' 48 8.15 9.9
8 120 Buffer Copy without Checking Size of Input ('Classic Buffer Overflow') 1,077 8.12 10.0
9 306 Missing Authentication for Critical Function 1,104 8.11 10.0
10 121 Stack-based Buffer Overflow 1,700 8.11 10.0

How fast is CVE growing?

Per-year CVE volume and severity.

Year CVEs Scored Avg score Max score
2026 (YTD as of 2026-08-18) 44,761 42,273 7.06 10.0
2025 43,372 41,943 6.79 10.0
2024 38,433 37,034 6.81 10.0
2023 30,602 24,722 6.73 10.0
2022 26,428 17,452 6.79 10.0
2021 22,591 10,823 6.83 10.0
2020 19,386 6,821 6.83 10.0
2019 16,094 3,525 6.84 10.0
2018 16,188 2,291 6.92 10.0
2017 14,762 1,375 7.18 10.0
2016 9,367 408 7.10 10.0
2015 8,111 250 6.25 10.0
2014 8,427 290 6.62 10.0
2013 6,221 154 7.44 10.0
2012 5,488 147 7.82 10.0
2011 4,646 96 7.54 10.0
2010 5,074 95 7.74 10.0
2009 4,921 65 8.01 10.0
2008 7,005 41 7.31 9.8
2007 6,458 38 8.00 9.8
2006 6,995 42 7.94 9.8
2005 4,627 21 6.23 9.8
2004 2,644 11 7.33 9.8
2003 1,504 6 5.73 7.5
2002 2,357 11 7.43 9.8
2001 1,537 5 7.54 9.8
2000 1,236 0 0.0
1999 1,540 24 7.62 9.8
Total 360,775 189,963 6.86 10.0

Reports

The two tables above are sliced from the seven derived reports in report/ (sibling of data/) — see report/README.md for methodology, the SINCE_DATE cutoff, and how the top-10 markdown is sliced from the top-100 TSV.

Per-year CVE stats

File Format Window
report/cve.report.md Markdown table all years
report/cve.report.tsv TSV all years

CWE rankings — top 100 TSVs (one per axis × window)

File Axis Window
report/cwe.top100.by-cve-count.report.tsv CVE count all years
report/cwe.top100.by-cve-score.report.tsv avg score all years
report/cwe.top100.by-cve-count.since-2024.report.tsv CVE count since 2024
report/cwe.top100.by-cve-score.since-2024.report.tsv avg score since 2024

CWE rankings — markdown (top 10 per axis, since 2024)

File Format
report/cwe.report.md Markdown, two top-10 tables — the top-10 markdown is sliced from the two since-2024 TSVs above

About x-cmd/cve

This repo is the producer: it reads CVEProject/cvelistV5, extracts a slim 9-column TSV per year, xz-compresses it, and publishes the artifacts as GitHub Release assets (https://github.com/x-cmd/cve/releases/download/data/<name>.xz). The consumer is the x cve shell module, which downloads on demand and never touches the upstream tree at runtime. Companion module x cwe browses the CWE catalog.

How users get CVE data (the 4 commands)

# 1. Browse — list / fzf over every cached CVE, newest first.
x cve
x cve fz

# 2. Look up a single CVE by id (or YYYY-NNNN shorthand).
x cve info CVE-2024-0001
x cve info 2024-0001            # same thing, no prefix needed

# 3. Pull the FULL upstream JSON record from CVEProject/cvelistV5:
#    affected products, references, timeline, ADP containers, etc.
x cve detail CVE-2024-0001

# 4. Enrich with Shodan's CVE database — EPSS, KEV listing,
#    exploit writeups, vendor advisories aggregated into one record:
x shodan cve CVE-2024-0001
#    (https://x-cmd.com/mod/shodan/cve)

x cve and x shodan cve chain cleanly:

x cve fz | x shodan cve -      # preview every CVE in shodan
x shodan cve CVE-2024-0001     # equivalent, no pipe needed

No API keys, no sudo, no background services — x cve is a thin shell module backed by the per-year TSVs this repo publishes daily.

Repository layout

.
├── .x-cmd/
│   ├── tsv.py              # full rebuild from a local cvelistV5 clone
│   ├── cwe.py              # MITRE CWE catalog mirror → data/cwe.tsv + .slim.tsv
│   ├── cwe_report.py       # aggregate data/cve-*.tsv ∩ data/cwe.slim.tsv → report/cwe.report.{tsv,md}
│   ├── report.py           # per-year stats → report/cve.report.{tsv,md}
│   └── _cve_index.py       # shared parse / IO helpers
├── data/                   # regenerated on every CI run — NOT in git
│   ├── cve-YYYY.tsv        # one TSV per year (rows in DESCENDING cve-id order)
│   ├── index.tsv           # year \t rows \t file
│   └── cve.tsv.state.json  # per-file mtimes (for tsv.py incremental)
└── report/                 # regenerated on every CI run — committed to main
    ├── README.md           # docks the seven files + methodology
    ├── cve.report.{tsv,md} # per-year stats
    ├── cwe.top100.by-cve-count.report.tsv               # all years, by count
    ├── cwe.top100.by-cve-score.report.tsv               # all years, by score
    ├── cwe.top100.by-cve-count.since-2024.report.tsv   # since 2024, by count
    ├── cwe.top100.by-cve-score.since-2024.report.tsv   # since 2024, by score
    └── cwe.report.md       # since 2024, top-10 markdown (sliced from the TSVs)
├── README.cn.md            # Chinese version of README.md (auto-updated)
└── .github/workflows/
    └── release.yml         # every 4h: tsv.py --rebuild → reports → xz → upload

data/ is regenerated from scratch on every CI run, so the working tree on main stays small.

Row order — newest first

Every cve-YYYY.tsv is written with rows in descending cve-id order:

CVE-2026-99999
CVE-2026-99998
CVE-2026-99997
...
CVE-2026-00002
CVE-2026-00001
CVE-2025-99999
...
CVE-1999-00001

The x cve consumer walks year files in reverse (ls -r) and each file is already in reverse order, so a plain cat produces "newest CVE at the top of the stream". No tac, no second pass over the data, no surprises.

Why store in reverse? x cve ls and x cve fz users care about latest CVEs first — the freshly issued ones, today's score-bombs. The producer's save_year_files sorts each bucket with sort(reverse=True) so the on-disk order matches the display order.

TSV columns (9)

# Column Meaning
1 cve Full CVE id, e.g. CVE-2024-0001.
2 year Year segment parsed from the id.
3 no Numeric segment parsed from the id.
4 vp <vendor>/<product>;... from containers.cna.affected[], ;-joined.
5 ghsa GitHub Security Advisory id(s) in references, ;-joined. Empty if absent.
6 score Highest CVSS base score (v4.0 → v3.1 → v3.0 → v2.0, first hit wins).
7 patched 1 if containers.cna.solutions[] is non-empty, else 0.
8 cwe CWE number(s) (prefix-stripped) joined with ;. Empty if absent.
9 desc English description, first sentence only (≤240 chars).

Field 9 is truncated to the first sentence — Linux CNA routinely pastes full kernel slab dumps (kilobytes of fp=0x... hex) into the description field. Truncating keeps per-year files at ~1-9 MB each and makes x cve fz lists scannable.

Scripts

All scripts are dependency-free (Python 3.8+ stdlib). Run from the repo root:

# Full rebuild from a local cvelistV5 clone (~2 minutes for ~350k records)
python3 .x-cmd/tsv.py

# Force re-parse every file (ignore mtime state)
python3 .x-cmd/tsv.py --rebuild

# Fetch MITRE CWE catalog → data/cwe.tsv (full 21 columns) +
# data/cwe.slim.tsv (id+name only, used for joins).
python3 .x-cmd/cwe.py

# Aggregate cross-reference: how many CVEs reference each CWE,
# mean + max score. Reads data/cve-*.tsv + data/cwe.slim.tsv.
python3 .x-cmd/cwe_report.py

CWE data — what we publish vs what we derive

The four report/cwe.*.report.tsv files are listed in the Reports section above. Below are the two upstream CWE catalog files this repo derives from MITRE:

File Shape Source Purpose
data/cwe.tsv 21-column TSV (~3 MB), all MITRE fields Verbatim mirror of MITRE 2000.csv x-cwe module + any consumer that wants the full CWE catalog without hitting MITRE directly
data/cwe.slim.tsv 2-column TSV (~50 KB), CWE-ID + Name only Derived from data/cwe.tsv Joined against data/cve-*.tsv for cwe_report.py
File Shape Source Purpose
data/cwe.tsv 21-column TSV (~3 MB), all MITRE fields preserved Verbatim mirror of MITRE 2000.csv (header row, spaces in column names replaced with _) x-cwe module and any consumer that wants the full CWE catalog without hitting MITRE directly
data/cwe.slim.tsv 2-column TSV (~50 KB), CWE-ID\tName only Derived from data/cwe.tsv (same row order) Joined against data/cve-*.tsv for cwe_report.py
report/cwe.top100.by-cve-count.report.tsv 5-column TSV (~6 KB), top 100 by CVE count, all years Aggregated from data/cve-*.tsvdata/cwe.slim.tsv Machine-readable top-N ranking
report/cwe.top100.by-cve-score.report.tsv 5-column TSV (~6 KB), top 100 by avg CVSS, all years same same
report/cwe.top100.by-cve-count.since-2024.report.tsv 5-column TSV (~6 KB), top 100 by CVE count, since 2024 same, year >= 2024 same
report/cwe.top100.by-cve-score.since-2024.report.tsv 5-column TSV (~6 KB), top 100 by avg CVSS, since 2024 same, year >= 2024 same
report/cwe.report.md Markdown with two top-10 tables (since 2024) Sliced from the two since-2024 TSVs Stitches into the README + README.cn front-matter via release.yml's inline step

Why we mirror the catalog: the upstream MITRE 2000.csv.zip is 644 KB and the unzipped csv is ~3 MB. xz-compressed to ~150 KB. We can afford to ship a full mirror, and it gives offline consumers the same data they'd get from MITRE without the network hop. The TSV keeps MITRE's column names (only spaces → underscores) so downstream code can use either format.

Why we don't ship a copy of the per-CVE catalog as a release asset today: the x-cwe module currently fetches 2000.csv from MITRE on its own and caches it locally (~/.x-cmd.root/local/data/cwe/). A future version of x-cwe could optionally read data/cwe.tsv from this repo's release instead, but that's not wired up yet.

CI

.github/workflows/release.yml runs every 4 hours (37 minutes past the hour, off-the-hour to spread load), plus on manual dispatch. Each run:

  1. Clones CVEProject/cvelistV5 (depth 1) and runs .x-cmd/tsv.py --rebuild to refresh data/cve-*.tsv.
  2. Regenerates data/cwe.tsv + data/cwe.slim.tsv from MITRE (.x-cmd/cwe.py) and the CWE cross-reference report (.x-cmd/cwe_report.pyreport/cwe.report.{tsv,md}).
  3. Regenerates the year-stats report (.x-cmd/report.pyreport/cve.report.{tsv,md}).
  4. Inlines both report markdown files into README.md as the first section (idempotent — BEGIN/END markers round-trip), then commits README.md + the four *.report.{md,tsv} back to main (skip if nothing changed), so the README on github.com always tracks the latest data.
  5. xz-compresses each changed per-year file (xz -9, ~85% reduction), replaces the matching release asset, force-moves the data-packaged git tag so the next run's diff is correct.

No .xz files are committed to main — binaries live in release assets, not source. The per-year data/cve-*.tsv and the CWE catalog (data/cwe.tsv, data/cwe.slim.tsv) likewise stay out of git under this flow; only the derived reports and the README are committed back, keeping the git history focused on real code changes.

The workflow used to have a separate delta-update workflow that ran on the same 4-hour cadence and produced an incremental data/cve.tsv; its output was overwritten by step 1's full rebuild every time release.yml followed via workflow_run, so the incremental work was dead weight. See issue #1 for the numbers.

License

Apache License 2.0 — see LICENSE.

The underlying CVE records are derived from CVEProject/cvelistV5, which is released under CC BY 4.0. Downstream consumers of these TSVs must retain that attribution.

Related

About

Per-year CVE / CWE indexes for x cve, x cwe.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages