How we compute trends.
CVE Trends publishes immutable snapshots once a period closes. Every metric on the site maps to a column in the trend_* tables. Snapshots are versioned per (period_type, period_start, version); republished data never overwrites a published report.
Sources
All upstream feeds we mirror and re-aggregate. Vulnerability records are merged into a single unified layer per CVE; enrichment feeds attach exploitation and detection context.
Snapshot pipeline
Reports are computed by a durable workflow, one isolated run per period.
- 01 A scheduler fires after each period closes — monthly and weekly — and a full backfill covers every period since 1999. Each period runs as its own child workflow, so one bad month never blocks the rest.
- 02 Per period we compute the overview (totals, severity, KEV), the vendor leaderboard with rank deltas and newcomers, the CWE distribution, the solution-sector breakdown, and response-velocity metrics (time to KEV, time to Nuclei).
- 03 Runs are idempotent on
(period_type, period_start, version)— recomputing a period replaces its rows instead of duplicating them. - 04 After all periods finish, a post-pass recomputes cross-period deltas (MoM, YoY, rank movement) over the stored series and invalidates the public API cache.
Solution sectors
Sector charts answer "what kind of software is being hit" — every (vendor, product) pair is mapped to one sector and one subsector from a fixed, versioned taxonomy.
Hybrid tagging. Package-registry pseudo-vendors (npm, PyPI, Maven, Go, RubyGems, crates.io, NuGet, Packagist, Hex, pub) map deterministically to oss-libraries subsectors — no model involved. Everything else is classified by an LLM in two passes: vendors first (one wildcard row covers all of a vendor's products), then individual products of high-volume vendors where one vendor spans several sectors.
Cached, versioned, reviewable. Assignments land in a persistent product_sectors map (tens of thousands of tagged pairs) — the snapshot pipeline only joins against it, it never calls the model. Bumping the taxonomy version re-queues every machine-tagged row; human-reviewed rows are pinned and survive re-tags. Low-confidence pairs fall back to unknown.
Counting rule. Sector numbers are summed over subsectors: a CVE affecting products in two subsectors counts once in each. Distinct-CVE totals per subsector are exact; sector-level sums are therefore an upper bound, same approximation the report breakdown uses.
Known limitations
- KEV is curated by CISA with a US-federal lens — sector KEV rates measure what CISA confirms exploited, not everything exploited.
- SaaS undercounts. Cloud services patch silently and often never file a CVE; deployment-model comparisons inherit this survivorship bias.
- Country means the vendor's home country, not where code was written or hosted. Treat country charts as a disclosure-landscape view.
- Machine tags carry confidence scores. Unrecognized vendors fall back to
unknownrather than a guess; long-tail tags are less reliable than head vendors.
Spotted a wrong sector, country or vendor type? Report a misclassification — confirmed fixes are pinned and survive re-tagging.
Definitions
- Period
- Calendar month (UTC) or ISO week. A period is "complete" when its end timestamp is in the past.
- Total CVEs
- Distinct CVE IDs whose
date_publishedfalls inside the period. For the in-progress period the headline number is linearly projected to the full window — marked with · proj. - KEV added
- CVEs CISA added to the Known Exploited Vulnerabilities catalog within the period. "Ransomware-linked" counts where CISA's
ransomware_campaign_use = 'Known'. - Critical
- CVSS-derived priority bucket from the unified scoring layer — typically CVSS ≥ 9.0.
- MoM / YoY
- Change vs the previous period / the same period a year earlier (12 months or 52 weeks back), computed over the stored snapshot series.
- Newcomer
- Vendor in the current top-100 that did not appear in top-100 in any of the prior 24 periods.
- Breakout factor
- Vendor's current CVE count divided by its 12-period median. Flagged as a breakout at ≥3×.
- Rank delta
- Movement vs the previous period: ↑ climbed (lower rank number = higher position), ↓ fell.
- Solution sector
- Sector/subsector assigned to each
(vendor, product)pair via the taxonomy above. Per-sector history pages aggregate subsector rows per period; their MoM/YoY are computed on the aggregated series. - Detection gap
- Vendors with KEV pressure (≥1 KEV in the period) and zero Nuclei templates. Computed client-side from the period's vendor list.
- CWE × Vendor
- Sparse co-occurrence matrix: distinct CVE IDs joined on
affected_json.vendorandweaknesses_json.cwe_id. NVD placeholder CWEs are excluded. - CWE × Sector
- Same construction with the vendor axis replaced by the solution sector of the affected products — which weakness classes hit which software categories.
- Median days → KEV
- For CVEs published in the period that entered the KEV catalog, the median delay from CVE publish to the CISA
date_added. - Median days → Nuclei
- For CVEs published in the period that received a Nuclei template, the median delay from CVE publish to template publish.
Pipeline health
Long-arc context for the production pipeline. Lives here, not on the front page, because monthly readers don't re-derive value from 25-year history — but methodology readers do.
8,311
peak month since 1999
—%
% of monthly CVEs with a template
0
distinct vendors / month
Reproducibility
Every published report is keyed by (period_type, period_start, version). Version bumps when methodology changes — older versions remain accessible. Republishing a snapshot does not overwrite the read API: previous cache keys are abandoned via a trends:cache_version stamp; consumers either keep the response they have or fetch fresh.
The full HTTP API is unauthenticated. See /api/public/trends. Every report page offers CSV and JSON export of the underlying rows.