Skip to content

Exploitability ​

Get EPSS (Exploit Prediction Scoring System) scores and CISA KEV (Known Exploited Vulnerabilities) data for tracked CVEs.

Endpoint ​

GET /api/v1/exploitability

Response ​

json
{
  "success": true,
  "data": {
    "epss": {
      "scores": {
        "CVE-2024-1234": {
          "epss": 0.42,
          "percentile": 0.97
        }
      },
      "lastUpdated": "2026-02-10T12:00:00.000Z",
      "totalCVEs": 150,
      "enrichedCount": 120,
      "highRiskCount": 15
    },
    "kev": {
      "kevMap": {
        "CVE-2024-1234": {
          "vendorProject": "openssl",
          "product": "OpenSSL",
          "dateAdded": "2024-03-15",
          "dueDate": "2024-04-05",
          "knownRansomwareCampaignUse": "Unknown"
        }
      },
      "catalogVersion": "2026.02.10",
      "dateReleased": "2026-02-10",
      "totalEntries": 1200,
      "matchingTracked": 5,
      "lastUpdated": "2026-02-10T12:00:00.000Z"
    }
  },
  "timestamp": "2026-02-10T12:00:00.000Z"
}

Response Fields ​

EPSS Object ​

FieldTypeDescription
scoresobjectMap of CVE ID to EPSS score and percentile
lastUpdatedstringWhen EPSS data was last refreshed
totalCVEsnumberTotal tracked CVEs
enrichedCountnumberCVEs with EPSS data
highRiskCountnumberCVEs with EPSS > 0.5 (high exploitability)

KEV Object ​

FieldTypeDescription
kevMapobjectMap of CVE ID to CISA KEV entry
catalogVersionstringCISA KEV catalog version
totalEntriesnumberTotal entries in KEV catalog
matchingTrackednumberHow many tracked CVEs appear in KEV
lastUpdatedstringWhen KEV data was last refreshed

Partial answers ​

data.partial is true when one of the two sources could not be read. The block that failed then carries available: false with every count null rather than zero, so kevMap: null next to partial: true means the catalogue was not consulted, not that nothing tracked is in it. Both blocks carry available in every answer.

Example ​

bash
curl https://api.vulnpatch.dev/api/v1/exploitability

Code Examples ​

javascript
async function getExploitability() {
  const response = await fetch('https://api.vulnpatch.dev/api/v1/exploitability');
  const { data } = await response.json();

  // High-risk CVEs by EPSS
  const highRisk = Object.entries(data.epss.scores)
    .filter(([, s]) => s.epss >= 0.5)
    .sort((a, b) => b[1].epss - a[1].epss);

  console.log(`High risk CVEs: ${highRisk.length}`);
  console.log(`In CISA KEV: ${data.kev.matchingTracked}`);
}
python
import requests

response = requests.get("https://api.vulnpatch.dev/api/v1/exploitability")
data = response.json()["data"]

# High-risk CVEs
high_risk = {cve: s for cve, s in data["epss"]["scores"].items() if s["epss"] >= 0.5}
print(f"High risk: {len(high_risk)}")
print(f"In CISA KEV: {data['kev']['matchingTracked']}")

Per-CVE Exploitability ​

EPSS and KEV data is also returned inline on individual CVE lookups via GET /api/v1/cve/:id. The response includes data.epss and data.kev fields when available, so you don't need to call this bulk endpoint for single-CVE lookups.

bash
# Get EPSS + KEV inline with CVE data
curl -s "https://api.vulnpatch.dev/api/v1/cve/CVE-2024-3094" | jq '{epss: .data.epss, kev: .data.kev}'

Exploit maturity on the dossier ​

GET /api/v1/cve/:id/dossier carries canonical.exploitMaturity: how far exploitation has been shown to go, from CISA KEV, CISA's SSVC decision, Exploit-DB, the Metasploit Framework, Nuclei templates and GitHub search.

levelMeaning
activeIn CISA KEV, or CISA's SSVC decision says exploitation is active
pocPublic exploit code or a detection template: an Exploit-DB entry, a Metasploit exploit module, a Nuclei template, a GitHub proof-of-concept repository or SSVC says poc
unreportedEvery source answered and none matched
unknownA source did not answer; sourcesUnreached names it

unreported and unknown are different answers. A fetch that failed has not said "no exploit", and an agent reading unknown as unreported acts past an exploit a failure hid.

Each artefact block (exploitdb, metasploit, nuclei, githubPoc) is null when its source did not answer, and otherwise lists up to ten items with the total stated. What is republished is identifiers, names, dates, ranks and links: an Exploit-DB entry as {edbId, title, datePublished, verified, type, platform, url}, a Metasploit module as {fullname, rank, rankName, disclosureDate, type, url}, a Nuclei template as its page in projectdiscovery/nuclei-templates, a GitHub repository as its name, link and stars. Exploit code, template bodies and comment text are never republished. Only a Metasploit module of type exploit counts towards poc; an auxiliary or post module scans, checks or acts after access, and is listed as such.

Each exploit source appears in the dossier's provenance with its licence and attribution: Exploit-DB (OffSec) under GPL-2.0, the Metasploit Framework under BSD-3-Clause (Copyright 2006-2026, Rapid7, Inc.; Rapid7 does not endorse this service), nuclei-templates under MIT (Copyright (c) 2025 ProjectDiscovery, Inc.) and GitHub repositories each under their own licence.

The Exploit-DB and Metasploit indexes are rebuilt by the scheduler from files_exploits.csv and modules_metadata_base.json, daily and weekly. A rebuild that fails leaves the previous index in place for a bounded time, after which lookups report the source as unreached rather than answer from stale data.

Use Cases ​

  • Prioritization: Rank CVEs by real-world exploitability (EPSS) rather than just CVSS
  • Compliance: Identify CVEs in CISA KEV that require mandatory remediation
  • Risk assessment: Combine EPSS with severity for a more complete risk picture