---
name: performing-cve-prioritization-with-kev-catalog
description: Leverage the CISA Known Exploited Vulnerabilities catalog alongside EPSS
  and CVSS to prioritize CVE remediation based on real-world exploitation evidence.
domain: cybersecurity
subdomain: vulnerability-management
tags:
- cisa-kev
- cve
- vulnerability-prioritization
- epss
- bod-22-01
- threat-intelligence
- remediation
version: '1.0'
author: mahipal
license: Apache-2.0
nist_ai_rmf:
- MEASURE-2.7
- MAP-5.1
- MANAGE-2.4
atlas_techniques:
- AML.T0070
- AML.T0066
- AML.T0082
nist_csf:
- ID.RA-01
- ID.RA-02
- ID.IM-02
- ID.RA-06
mitre_attack:
- T1190
- T1203
- T1068
---
# Performing CVE Prioritization with KEV Catalog

## Overview
The CISA Known Exploited Vulnerabilities (KEV) catalog, established through Binding Operational Directive (BOD) 22-01, is a living list of CVEs that have been actively exploited in the wild and carry significant risk. As of early 2026, the catalog contains over 1,484 entries, growing 20% in 2025 alone with 245 new additions. This skill covers integrating the KEV catalog into vulnerability prioritization workflows alongside EPSS (Exploit Prediction Scoring System) and CVSS to create a risk-based approach that prioritizes vulnerabilities with confirmed exploitation activity over theoretical severity alone.


## When to Use

- When conducting security assessments that involve performing cve prioritization with kev catalog
- When following incident response procedures for related security events
- When performing scheduled security testing or auditing activities
- When validating security controls through hands-on testing

## Prerequisites
- Access to vulnerability scan results (Qualys, Nessus, Rapid7, etc.)
- Familiarity with CVE identifiers and NVD
- Understanding of CVSS scoring (v3.1 and v4.0)
- API access to CISA KEV, EPSS, and NVD endpoints
- Python 3.8+ with requests and pandas libraries

## Core Concepts

### CISA KEV Catalog Structure
Each KEV entry contains:
- **CVE ID**: The CVE identifier (e.g., CVE-2024-3094)
- **Vendor/Project**: Affected vendor and product name
- **Vulnerability Name**: Short description of the vulnerability
- **Date Added**: When CISA added it to the catalog
- **Short Description**: Brief technical description
- **Required Action**: Recommended remediation action
- **Due Date**: Deadline for federal agencies (FCEB) to remediate
- **Known Ransomware Campaign Use**: Whether ransomware groups exploit it

### BOD 22-01 Remediation Timelines
| CVE Publication Date | Remediation Deadline |
|----------------------|---------------------|
| 2021 or later | 2 weeks from KEV listing |
| Before 2021 | 6 months from KEV listing |

### Multi-Factor Prioritization Model

| Factor | Weight | Data Source | Rationale |
|--------|--------|-------------|-----------|
| CISA KEV Listed | 30% | CISA KEV JSON feed | Confirmed active exploitation |
| EPSS Score | 25% | FIRST EPSS API | Predicted exploitation probability |
| CVSS Base Score | 20% | NVD API v2.0 | Intrinsic vulnerability severity |
| Asset Criticality | 15% | CMDB/Asset inventory | Business impact context |
| Network Exposure | 10% | Network architecture | Attack surface accessibility |

### KEV + EPSS Decision Matrix

| KEV Listed | EPSS > 0.5 | CVSS >= 9.0 | Priority | SLA |
|------------|-----------|-------------|----------|-----|
| Yes | Any | Any | P1-Emergency | 48 hours |
| No | Yes | Yes | P1-Emergency | 48 hours |
| No | Yes | No | P2-Critical | 7 days |
| No | No | Yes | P2-Critical | 7 days |
| No | No | No (>= 7.0) | P3-High | 14 days |
| No | No | No (>= 4.0) | P4-Medium | 30 days |
| No | No | No (< 4.0) | P5-Low | 90 days |

## Workflow

### Step 1: Fetch and Parse the KEV Catalog

```python
import requests
import json
from datetime import datetime

KEV_URL = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"

def fetch_kev_catalog():
    """Download and parse the CISA KEV catalog."""
    response = requests.get(KEV_URL, timeout=30)
    response.raise_for_status()
    data = response.json()

    catalog = {}
    for vuln in data.get("vulnerabilities", []):
        cve_id = vuln["cveID"]
        catalog[cve_id] = {
            "vendor": vuln.get("vendorProject", ""),
            "product": vuln.get("product", ""),
            "name": vuln.get("vulnerabilityName", ""),
            "date_added": vuln.get("dateAdded", ""),
            "description": vuln.get("shortDescription", ""),
            "action": vuln.get("requiredAction", ""),
            "due_date": vuln.get("dueDate", ""),
            "ransomware_use": vuln.get("knownRansomwareCampaignUse", "Unknown"),
        }

    print(f"[+] Loaded {len(catalog)} CVEs from CISA KEV catalog")
    print(f"    Catalog version: {data.get('catalogVersion', 'N/A')}")
    print(f"    Last updated: {data.get('dateReleased', 'N/A')}")
    return catalog

kev = fetch_kev_catalog()
```

### Step 2: Enrich with EPSS Scores

```python
EPSS_API = "https://api.first.org/data/v1/epss"

def get_epss_scores(cve_list):
    """Fetch EPSS scores for a batch of CVEs."""
    scores = {}
    batch_size = 100
    for i in range(0, len(cve_list), batch_size):
        batch = cve_list[i:i + batch_size]
        cve_param = ",".join(batch)
        response = requests.get(EPSS_API, params={"cve": cve_param}, timeout=30)
        if response.status_code == 200:
            for entry in response.json().get("data", []):
                scores[entry["cve"]] = {
                    "epss": float(entry.get("epss", 0)),
                    "percentile": float(entry.get("percentile", 0)),
                }
    return scores
```

### Step 3: Build the Prioritization Engine

```python
import pandas as pd

def prioritize_vulnerabilities(scan_results, kev_catalog, epss_scores):
    """Apply multi-factor prioritization to scan results."""
    prioritized = []

    for vuln in scan_results:
        cve_id = vuln.get("cve_id", "")
        cvss_score = float(vuln.get("cvss_score", 0))
        asset_criticality = float(vuln.get("asset_criticality", 3))
        exposure = float(vuln.get("network_exposure", 3))

        in_kev = cve_id in kev_catalog
        kev_data = kev_catalog.get(cve_id, {})
        epss_data = epss_scores.get(cve_id, {"epss": 0, "percentile": 0})
        epss_score = epss_data["epss"]

        # Composite risk score calculation
        risk_score = (
            (1.0 if in_kev else 0.0) * 10 * 0.30 +
            epss_score * 10 * 0.25 +
            cvss_score * 0.20 +
            (asset_criticality / 5.0) * 10 * 0.15 +
            (exposure / 5.0) * 10 * 0.10
        )

        # Assign priority level
        if in_kev or (epss_score > 0.5 and cvss_score >= 9.0):
            priority = "P1-Emergency"
            sla_days = 2
        elif epss_score > 0.5 or cvss_score >= 9.0:
            priority = "P2-Critical"
            sla_days = 7
        elif cvss_score >= 7.0:
            priority = "P3-High"
            sla_days = 14
        elif cvss_score >= 4.0:
            priority = "P4-Medium"
            sla_days = 30
        else:
            priority = "P5-Low"
            sla_days = 90

        prioritized.append({
            "cve_id": cve_id,
            "cvss_score": cvss_score,
            "epss_score": round(epss_score, 4),
            "epss_percentile": round(epss_data["percentile"], 4),
            "in_cisa_kev": in_kev,
            "ransomware_use": kev_data.get("ransomware_use", "N/A"),
            "kev_due_date": kev_data.get("due_date", "N/A"),
            "risk_score": round(risk_score, 2),
            "priority": priority,
            "sla_days": sla_days,
            "asset": vuln.get("asset", ""),
            "asset_criticality": asset_criticality,
        })

    df = pd.DataFrame(prioritized)
    df = df.sort_values("risk_score", ascending=False)
    return df
```

### Step 4: Generate Prioritization Report

```python
def generate_report(df, output_file="kev_prioritized_report.csv"):
    """Generate summary report from prioritized vulnerabilities."""
    print("\n" + "=" * 70)
    print("VULNERABILITY PRIORITIZATION REPORT - KEV + EPSS + CVSS")
    print("=" * 70)

    print(f"\nTotal vulnerabilities analyzed: {len(df)}")
    print(f"KEV-listed vulnerabilities:    {df['in_cisa_kev'].sum()}")
    print(f"Ransomware-associated:         {(df['ransomware_use'] == 'Known').sum()}")

    print("\nPriority Distribution:")
    print(df["priority"].value_counts().to_string())

    print("\nTop 15 Highest Risk Vulnerabilities:")
    top = df.head(15)[["cve_id", "cvss_score", "epss_score", "in_cisa_kev",
                        "risk_score", "priority"]]
    print(top.to_string(index=False))

    df.to_csv(output_file, index=False)
    print(f"\n[+] Full report saved to: {output_file}")
```

## Best Practices
1. Update the KEV catalog daily since CISA adds new entries multiple times per week
2. Always cross-reference KEV with EPSS; a CVE may have high EPSS but not yet be in KEV
3. Treat all KEV-listed CVEs as P1-Emergency regardless of CVSS score
4. Pay special attention to KEV entries flagged with "Known Ransomware Campaign Use"
5. Automate KEV comparison against your vulnerability scan results in CI/CD pipelines
6. Track KEV due dates separately for FCEB compliance requirements
7. Use KEV as a leading indicator for threat hunting; if a CVE is added, check for prior exploitation in your environment

## Common Pitfalls
- Relying solely on CVSS scores without checking KEV or EPSS data
- Not updating the KEV catalog frequently enough (CISA updates multiple times weekly)
- Treating non-KEV CVEs as safe; they may be exploited but not yet cataloged
- Ignoring the "ransomware use" field which indicates highest-urgency threats
- Using KEV only for compliance instead of integrating into overall risk management

## Related Skills
- prioritizing-vulnerabilities-with-cvss-scoring
- building-vulnerability-data-pipeline-with-api
- implementing-threat-intelligence-scoring
- implementing-vulnerability-remediation-sla
