<!-- AUTO-GENERATED by export-skills.py — DO NOT EDIT --> --- name: cve-epss-guide description: CVE/NVD/EPSS vulnerability prioritization guide for risk-based remediation tags: [security, vulnerability] ---
Scanned 6/6/2026
Install via CLI
openskills install frank-luongt/faos-skills-marketplace<!-- AUTO-GENERATED by export-skills.py — DO NOT EDIT -->
---
name: cve-epss-guide
description: CVE/NVD/EPSS vulnerability prioritization guide for risk-based remediation
tags: [security, vulnerability]
---
# CVE/NVD/EPSS Vulnerability Prioritization Guide
## Overview
Vulnerability management generates more findings than any team can remediate simultaneously. Effective prioritization separates critical risks from noise. This skill combines three complementary data sources to produce actionable remediation priorities:
- **CVE (Common Vulnerabilities and Exposures)** -- unique identifiers for publicly known vulnerabilities, managed by MITRE and assigned by CVE Numbering Authorities (CNAs)
- **NVD (National Vulnerability Database)** -- NIST-maintained database that enriches CVEs with CVSS scores, CWE classifications, and CPE (affected product) data
- **EPSS (Exploit Prediction Scoring System)** -- FIRST.org model that predicts the probability a vulnerability will be exploited in the wild within the next 30 days
- **CISA KEV (Known Exploited Vulnerabilities)** -- authoritative catalog of vulnerabilities confirmed to be actively exploited, with binding remediation deadlines for federal agencies
Using CVSS alone leads to "alert fatigue" -- roughly 50% of CVEs score 7.0 or higher, but fewer than 5% are ever exploited. EPSS and CISA KEV provide the exploit-likelihood signal needed to focus on what actually matters.
## When to Use This Skill
- You are triaging vulnerability scan results from tools like Trivy, Grype, Snyk, or Qualys
- You need to prioritize remediation when the backlog exceeds team capacity
- You are building an automated vulnerability management pipeline
- You want to set SLA thresholds based on actual exploit risk rather than CVSS alone
- You are reporting vulnerability posture to leadership and need risk-based metrics
- You are evaluating whether a newly disclosed CVE requires emergency patching
## How It Works
### Step 1: Identify the CVE
Gather CVE identifiers from your scanning tools, security advisories, or threat intelligence feeds. Each CVE follows the format `CVE-YYYY-NNNNN` (e.g., CVE-2024-3094).
Key data sources for CVE information:
| Source | URL | Data Provided |
|-------------|------------------------------------------|----------------------------------|
| NVD | https://nvd.nist.gov/vuln/detail/CVE-ID | CVSS, CWE, CPE, references |
| MITRE CVE | https://cve.mitre.org/cgi-bin/cvename.cgi | CVE description, status |
| GitHub Advisory | https://github.com/advisories | Ecosystem-specific (npm, pip) |
| OSV | https://osv.dev | Open-source vulnerability data |
CVE lifecycle stages: **Reserved** (ID assigned, details pending) -> **Published** (details disclosed) -> **Analyzed** (NVD adds CVSS/CWE) -> **Modified** (updates applied)
### Step 2: Check CVSS Score
CVSS v3.1 provides a standardized severity score from 0.0 to 10.0:
| Score Range | Severity | Typical SLA |
|-------------|----------|--------------|
| 9.0 - 10.0 | Critical | 24-72 hours |
| 7.0 - 8.9 | High | 7-14 days |
| 4.0 - 6.9 | Medium | 30-60 days |
| 0.1 - 3.9 | Low | 90 days |
CVSS comprises three metric groups:
- **Base Metrics** -- intrinsic characteristics (attack vector, complexity, privileges required, impact)
- **Temporal Metrics** -- factors that change over time (exploit maturity, remediation level, report confidence)
- **Environmental Metrics** -- organization-specific adjustments (asset criticality, modified impact)
Important: Base CVSS alone over-prioritizes. A CVSS 9.8 with no known exploit and low EPSS is lower risk than a CVSS 7.5 with active exploitation.
### Step 3: Check EPSS Probability
Query the EPSS API for the probability of exploitation within 30 days:
```bash
# Query EPSS for a single CVE
curl -s "https://api.first.org/data/v1/epss?cve=CVE-2024-3094" | jq '.data[0]'
# Response:
# {
# "cve": "CVE-2024-3094",
# "epss": "0.93217",
# "percentile": "0.99842",
# "date": "2026-02-24"
# }
```
EPSS interpretation:
| EPSS Score | Meaning | Action |
|------------|---------------------------------------|-----------------------|
| > 0.70 | Very high exploitation probability | Treat as emergency |
| 0.30-0.70 | Significant exploitation probability | Prioritize this week |
| 0.10-0.30 | Moderate exploitation probability | Schedule within SLA |
| < 0.10 | Low exploitation probability | Standard SLA applies |
### Step 4: Check CISA KEV
Query the CISA Known Exploited Vulnerabilities catalog:
```bash
# Download the full KEV catalog
curl -s "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json" \
| jq '.vulnerabilities[] | select(.cveID == "CVE-2024-3094")'
```
If a CVE appears in the KEV catalog, it has been **confirmed exploited in the wild**. CISA mandates federal agencies remediate KEV entries by the listed due date. Private organizations should treat KEV entries as highest priority.
### Step 5: Prioritize by Combined Risk
Combine all signals into a priority score:
| Priority | Criteria | Target SLA |
|----------|---------------------------------------------|--------------|
| P0 | In CISA KEV OR EPSS > 0.7 | 24-48 hours |
| P1 | CVSS >= 9.0 AND EPSS > 0.3 | 72 hours |
| P2 | CVSS >= 7.0 AND EPSS > 0.1 | 7 days |
| P3 | CVSS >= 7.0 AND EPSS <= 0.1 | 30 days |
| P4 | CVSS < 7.0 AND EPSS <= 0.1 | 90 days |
Asset criticality should further adjust priority: a P3 vulnerability on a production database may warrant P2 treatment.
### Step 6: Assign to Remediation
For each prioritized vulnerability:
1. Identify the affected component (library, OS package, container image)
2. Determine the fix version or mitigation
3. Assign to the responsible team with the target SLA
4. Track remediation progress in your issue tracker
5. Re-scan after patching to confirm the fix
## Examples
### Example 1: Python Script for Vulnerability Triage
```python
"""
Vulnerability triage script that combines NVD, EPSS, and CISA KEV data
to produce a prioritized remediation list.
"""
import requests
from dataclasses import dataclass
@dataclass
class VulnAssessment:
cve_id: str
cvss_score: float
epss_score: float
epss_percentile: float
in_kev: bool
priority: str
sla_hours: int
def get_cvss_score(cve_id: str) -> float:
"""Fetch CVSS v3.1 base score from NVD API."""
url = f"https://services.nvd.nist.gov/rest/json/cves/2.0?cveId={cve_id}"
resp = requests.get(url, headers={"apiKey": "YOUR_NVD_API_KEY"})
resp.raise_for_status()
data = resp.json()
vulns = data.get("vulnerabilities", [])
if not vulns:
return 0.0
metrics = vulns[0]["cve"].get("metrics", {})
cvss_v31 = metrics.get("cvssMetricV31", [{}])
if cvss_v31:
return cvss_v31[0]["cvssData"]["baseScore"]
return 0.0
def get_epss_score(cve_id: str) -> tuple[float, float]:
"""Fetch EPSS probability and percentile."""
url = f"https://api.first.org/data/v1/epss?cve={cve_id}"
resp = requests.get(url)
resp.raise_for_status()
data = resp.json()["data"]
if data:
return float(data[0]["epss"]), float(data[0]["percentile"])
return 0.0, 0.0
def check_kev(cve_id: str, kev_data: dict) -> bool:
"""Check if CVE is in CISA KEV catalog."""
return any(v["cveID"] == cve_id for v in kev_data.get("vulnerabilities", []))
def calculate_priority(cvss: float, epss: float, in_kev: bool) -> tuple[str, int]:
"""Calculate priority and SLA based on combined risk signals."""
if in_kev or epss > 0.7:
return "P0", 48
if cvss >= 9.0 and epss > 0.3:
return "P1", 72
if cvss >= 7.0 and epss > 0.1:
return "P2", 168 # 7 days
if cvss >= 7.0:
return "P3", 720 # 30 days
return "P4", 2160 # 90 days
def triage_vulnerabilities(cve_ids: list[str]) -> list[VulnAssessment]:
"""Triage a list of CVEs and return prioritized assessments."""
kev_url = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
kev_data = requests.get(kev_url).json()
results = []
for cve_id in cve_ids:
cvss = get_cvss_score(cve_id)
epss, percentile = get_epss_score(cve_id)
in_kev = check_kev(cve_id, kev_data)
priority, sla = calculate_priority(cvss, epss, in_kev)
results.append(VulnAssessment(
cve_id=cve_id,
cvss_score=cvss,
epss_score=epss,
epss_percentile=percentile,
in_kev=in_kev,
priority=priority,
sla_hours=sla,
))
results.sort(key=lambda v: (v.priority, -v.epss_score))
return results
```
### Example 2: Prioritization Matrix
```
EPSS > 0.3 EPSS 0.1-0.3 EPSS < 0.1
+-----------------+-----------------+-----------------+
CVSS >= 9.0 | P1 (72h) | P2 (7d) | P3 (30d) |
+-----------------+-----------------+-----------------+
CVSS 7.0-8.9 | P1 (72h) | P2 (7d) | P3 (30d) |
+-----------------+-----------------+-----------------+
CVSS 4.0-6.9 | P2 (7d) | P3 (30d) | P4 (90d) |
+-----------------+-----------------+-----------------+
CVSS < 4.0 | P3 (30d) | P4 (90d) | P4 (90d) |
+-----------------+-----------------+-----------------+
Override: CISA KEV = P0 (48h) regardless of CVSS/EPSS
Modifier: Critical asset = promote one level (P3 -> P2)
```
## Best Practices
### Do This
- Use EPSS as the primary exploit-likelihood signal alongside CVSS severity
- Check CISA KEV for every critical and high CVE -- KEV entries are confirmed exploited
- Automate EPSS and KEV lookups in your vulnerability management pipeline
- Set SLAs based on combined risk (CVSS + EPSS + KEV + asset criticality), not CVSS alone
- Re-evaluate EPSS scores periodically -- they update daily as new exploit data emerges
- Track mean-time-to-remediate (MTTR) by priority level for operational metrics
- Use NVD API keys for rate-limited access (50 requests/30s with key vs 5 without)
### Don't Do This
- Do not treat all "Critical" CVSS vulnerabilities equally -- EPSS differentiates actual risk
- Do not ignore low-CVSS vulnerabilities with high EPSS scores -- they are being exploited
- Do not rely solely on CVSS temporal scores -- they are rarely updated by vendors
- Do not skip CISA KEV checks -- these are confirmed exploited, not theoretical
- Do not set the same SLA for all vulnerability severities -- it leads to remediation fatigue
- Do not cache EPSS scores for more than 24 hours -- they change daily
## Security Checklist
- [ ] Vulnerability scanner is running on all production assets (containers, hosts, dependencies)
- [ ] NVD API key is configured for higher rate limits
- [ ] EPSS lookup is integrated into the vulnerability triage workflow
- [ ] CISA KEV catalog is checked automatically for all new findings
- [ ] Priority levels (P0-P4) are defined with clear SLA targets
- [ ] Asset criticality classifications are maintained and factored into priority
- [ ] Remediation SLA compliance is tracked and reported weekly
- [ ] Exception process exists for vulnerabilities that cannot be patched within SLA
- [ ] Vulnerability data is correlated with threat intelligence feeds
- [ ] Re-scanning occurs after patching to confirm remediation
- [ ] Metrics are tracked: MTTR by priority, SLA compliance rate, open vulnerability count
## Related Skills
- @mitre-attck-reference -- mapping CVEs to ATT&CK techniques for threat context
- @sigma-rules-guide -- writing detection rules for vulnerabilities before patches are applied
- @cwe-sans-top25 -- understanding root cause weakness categories behind CVEs
## Additional Resources
- [NVD API Documentation](https://nvd.nist.gov/developers/vulnerabilities) -- CVE data API
- [EPSS API Documentation](https://www.first.org/epss/api) -- exploit prediction scores
- [CISA KEV Catalog](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) -- confirmed exploited vulnerabilities
- [CVSS v3.1 Calculator](https://www.first.org/cvss/calculator/3.1) -- interactive score calculator
- [EPSS Model Documentation](https://www.first.org/epss/model) -- how EPSS predictions are generated
- [Stakeholder-Specific Vulnerability Categorization (SSVC)](https://www.cisa.gov/ssvc) -- CISA's decision-tree prioritization framework
<!-- Source: .faos/custom/skills/security/cve-epss-guide/SKILL.md -->
No comments yet. Be the first to comment!