A modern, fast front end over the CVE corpus: search, browse, and analyze vulnerabilities ranked by the signals that actually drive triage, not just CVSS.
Live: https://cloudanimal.github.io/cve-explorer/
Think of the classic CVE-database sites, rebuilt around prioritization. Every CVE is scored with CVSS and EPSS, CISA KEV, NIST LEV, and a simplified SSVC decision, rolled into one composite "patch now / this cycle / standard cadence" verdict.
No backend, no build step, no API keys. It runs entirely in the browser against public APIs, plus a handful of pre-built static datasets, so it hosts for free on GitHub Pages.
The Time to Exploit view — how fast confirmed-exploited CVEs go from disclosure to first in-the-wild exploitation.
The NASL Viewer — drop your own Nessus plugin database (or the whole archive) and read 56k+ plugins' source, queried entirely in your browser via WebAssembly SQLite.
| View | What it does | Data |
|---|---|---|
| NASL Viewer | Load your own Nessus plugin database (agent-*.db / plugins.db) or a single .nasl file and read the plugin source with NASL syntax highlighting — look up by plugin ID or filename, pin lines, and highlight strings/regex as you review. SQLite is parsed in-browser via WebAssembly (sql.js); nothing is uploaded, and Tenable-licensed content stays on your machine |
your plugin DB, in-browser |
| Morning Report | A daily briefing that leads with what's newly exploitable — CVEs newly added to CISA KEV, the biggest EPSS risers this week, fresh public exploits/PoCs across the aggregated feed — followed by new Critical CVEs from the last 48h. Built from the pre-built feeds plus one live NVD call | KEV, EPSS, exploit feeds, NVD |
| Ask AI | Ask in plain English ("ransomware-linked KEV vulns", "critical CVEs from 2024") and a bring-your-own-key Anthropic model maps the question onto the app's existing views and filters. It never invents CVE data — every answer is a validated link to a real route, and the key lives only in your browser | your Anthropic key → app routes |
| Search | Find CVEs by ID or keyword; results ranked with risk badges. Quick links render Latest (newest CVEs, 24h–30d window with a published/updated toggle) and Browse (filter the corpus by year, CVSS severity, and CWE) inline as result sets | NVD API (live) + EPSS |
| CVE detail | Full enriched record: composite verdict, five prioritization models side by side, fixed versions, Microsoft KBs, scanner/detection coverage deep-links (Tenable, Qualys, Rapid7, …), references | NVD, EPSS, OSV, MSRC, LEV |
| Triage | One CVE list, two views via a subnav: Table (bulk prioritization with CSV/JSON export) and Side-by-side (up to four CVEs compared across every risk signal). Paste once, switch views | NVD, EPSS, KEV, LEV |
| Tenable Analyzer | Drop a Tenable/Nessus export (or try the bundled sample) for an instant, 100%-client-side risk read-out cross-referenced against CISA KEV — your scan data never leaves the browser | local + KEV |
| Exploited | One page, two views: All sources (a per-CVE table aggregating CISA KEV, Exploit-DB, Metasploit, Google P0, VulnCheck, and NVD exploit refs, with CVE/exploit dates, CVSS, severity, and per-CVE time-to-exploit) and CISA KEV (the full catalog, searchable/sortable offline, with ransomware flags and due-date filters) | pre-built |
| Statistics | Two views: Trends (per-year counts/rates by lens, EPSS distribution, attack-surface profile, KEV trends, live NVD query composer) and Time to Exploit (median + trimmed-mean TTE by cohort, milestones, exploit rate, survival curve) | pre-built + live |
Most CVE databases lead with CVSS severity. CVE Explorer leads with a composite verdict and then shows how five models rate the same CVE, because they routinely disagree:
- CVSS severity — the traditional, severity-driven model
- EPSS threshold — probability of exploitation in the next 30 days (FIRST)
- CISA KEV — confirmed exploitation in the wild
- NIST LEV — probability the CVE has already been exploited, a lower-bound estimate (NIST CSWP 41)
- SSVC (simplified) — CISA's decision tree (Act / Attend / Track)
No backend, no build step, no server-side code. Two data paths feed one static single-page app:
flowchart TB
subgraph src["Public data sources"]
direction LR
S1["NVD · EPSS · OSV · MSRC<br/>Red Hat · CVE List V5 · endoflife.date"]
S2["CISA KEV · VulnCheck · Exploit-DB · Metasploit<br/>Google P0 · Nomi-sec · Ubuntu · Tenable RSS"]
end
subgraph build["Build time · scheduled GitHub Actions"]
SCRIPTS["scripts/build_*.py"] --> JSON[("data/*.json<br/>committed to the repo")]
MAN["build_manifest.py"] --> MANIFEST[("data/manifest.json")]
end
PAGES["GitHub Pages<br/>(static hosting)"]
SPA["CVE Explorer<br/>single-page app · vanilla JS · hash-routed"]
ANTH["Anthropic API<br/>(Ask AI, bring-your-own-key)"]
USER([Visitor's browser])
S2 -->|pulled at build| SCRIPTS
JSON --> PAGES
MANIFEST --> PAGES
PAGES --> SPA
USER --> SPA
S1 -.->|fetched live, per query| SPA
SPA -.->|key stays in browser| ANTH
Solid arrows = pre-built, committed datasets refreshed on a schedule. Dotted arrows = fetched live from the visitor's browser on demand (and for Ask AI, the user's own API key is sent only to Anthropic, never to the host). The Tenable Analyzer parses uploaded scans entirely client-side — that data never leaves the browser at all.
A full CVE database is ~250k records. CVE Explorer never mirrors all of it:
- Search, browse, and detail hit the live NVD/EPSS/OSV APIs on demand.
- Statistics are real NVD counts obtained cheaply: the NVD API returns a
totalResultsfield for any filtered query, soscripts/build_stats.pybuilds a per-year cube (total, severity split, KEV count) from metadata-only calls (chunked into ≤120-day windows, the API's range limit; cached on disk so reruns and the scheduled refresh are nearly free) instead of downloading the corpus. The KEV-per-year counts let the explorer show the exploitation rate over time. - The EPSS exploitability distribution comes from the full FIRST EPSS daily dataset, summarized locally by
scripts/build_epss_dist.pyinto a histogram and cumulative thresholds. - The query composer fires live
totalResultscalls so you can count any filter combination on demand, and shows the constructed API request. - The KEV catalog is small enough (~1.6k entries) to ship whole;
scripts/build_kev.pytrims and aggregates the official CISA feed. - LEV and Microsoft KB data are pre-computed by
build_lev.pyandbuild_msrc.py, the same pipelines used by cve-patch-lookup.
Scheduled GitHub Actions refresh each dataset (KEV daily, stats weekly, LEV/MSRC monthly) and commit the results, so the static data never goes stale.
NVD · FIRST EPSS · OSV.dev · CISA KEV · CISA Vulnrichment / SSVC · MSRC · Red Hat Security Data · Ubuntu CVE Tracker · endoflife.date · Exploit-DB · Metasploit · Nomi-sec PoC-in-GitHub · VulnCheck
On the CVE detail page, each record is additionally enriched with Red Hat product fix-state + errata (Red Hat Security Data API, live), Ubuntu per-release package fix status (Ubuntu CVE Tracker, pre-built by build_ubuntu.py since the site sends no CORS header), CISA's SSVC decision points (Exploitation / Automatable / Technical Impact, from the CVE List ADP "Vulnrichment" container, live), and product end-of-life status (endoflife.date, live) — because EOL software won't get a patch.
It's a static site. Serve the folder and open it:
python3 -m http.server 8000
# open http://localhost:8000To rebuild the static datasets:
python3 scripts/build_kev.py # KEV catalog + stats
python3 scripts/build_epss_dist.py # EPSS exploitability distribution
python3 scripts/build_stats.py # corpus statistics cube (slow without an NVD API key)
python3 scripts/build_lev.py # NIST LEV
python3 scripts/build_msrc.py # Microsoft CVE→KBSetting NVD_API_KEY speeds up the stats build considerably.
scripts/build_tte.py produces data/tte.json — it pulls confirmed-exploitation signals from CISA KEV (always), VulnCheck KEV, and VulnCheck XDB (the latter two when VULNCHECK_API_TOKEN is set; XDB only refines the exploit timestamp for already-KEV-confirmed CVEs, helping thin early-year cohorts), enriches each CVE with its publication date from the official CVE List (CVEProject/cvelistV5, one JSON per CVE carrying cveMetadata.datePublished — pulled in bulk from GitHub raw with no API key and no rate limit; cached in data/.tte_pubcache.json so reruns are cheap), and computes per-cohort-year TTE, milestones, and the survival curve. Using the CVE List date instead of NVD's published also avoids NVD's publication lag, which otherwise manufactures spurious negative TTE. Runs monthly via .github/workflows/refresh-tte.yml.
Repo secrets: none required — the build runs on CISA KEV + the public CVE List out of the box.
VULNCHECK_API_TOKEN(optional) adds VulnCheck KEV's broader analyst-confirmed signal and XDB timestamp refinement;NVD_API_KEY(optional) is used only as a fallback publication-date source for the rare CVE missing from the CVE List.
scripts/build_explorer.py produces data/exploited.json — the per-CVE Explorer dataset. It aggregates "this CVE has a known exploit / public PoC" signals across multiple public sources — CISA KEV, Exploit-DB (files_exploits.csv), Metasploit (modules_metadata_base.json), Google Project Zero 0days-in-the-wild, Nomi-sec PoC-in-GitHub, plus VulnCheck KEV/XDB when VULNCHECK_API_TOKEN is set — taking the earliest exploit date per CVE. Each candidate CVE is enriched from the official CVE List (CVEProject/cvelistV5) for its publication date, CVSS, severity, and product, and a CVE List reference tagged Exploit adds an nvd-exploit-ref source. Time-to-exploit is exploit date − publication date. To keep the static dataset small, the candidate set is limited to recently-disclosed CVEs plus everything in a confirmed-exploited source, and capped; enrichment is cached in data/.explorer_cache.json so reruns are cheap. Runs monthly via .github/workflows/refresh-explorer.yml.
Built by Joe Cook. CVE Explorer is a read-only analysis tool over public data; always confirm against the vendor before acting.

