vulnerability management

Implementing EPSS Score for Vulnerability Prioritization

Integrate FIRST's Exploit Prediction Scoring System (EPSS) API to prioritize vulnerability remediation based on real-world exploitation probability within 30 days.

cvssepssexploit-predictionfirstmachine-learningrisk-basedvulnerability-prioritization
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Overview

The Exploit Prediction Scoring System (EPSS) is a data-driven model developed by FIRST (Forum of Incident Response and Security Teams) that estimates the probability of a CVE being exploited in the wild within the next 30 days. EPSS produces scores from 0.0 to 1.0 (0% to 100%) using machine learning trained on real-world exploitation data. Unlike CVSS which measures severity, EPSS measures likelihood of exploitation, making it essential for risk-based vulnerability prioritization.

When to Use

  • When deploying or configuring implementing epss score for vulnerability prioritization capabilities in your environment
  • When establishing security controls aligned to compliance requirements
  • When building or improving security architecture for this domain
  • When conducting security assessments that require this implementation

Prerequisites

  • Python 3.9+ with requests, pandas, matplotlib
  • Access to FIRST EPSS API (https://api.first.org/data/v1/epss)
  • Vulnerability scan results with CVE identifiers
  • Optional: NVD API key for CVSS enrichment

EPSS API Usage

Query Single CVE

# Get EPSS score for a specific CVE
curl -s "https://api.first.org/data/v1/epss?cve=CVE-2024-3400" | python3 -m json.tool
 
# Response:
# {
#   "status": "OK",
#   "status-code": 200,
#   "version": "1.0",
#   "total": 1,
#   "data": [
#     {
#       "cve": "CVE-2024-3400",
#       "epss": "0.95732",
#       "percentile": "0.99721",
#       "date": "2024-04-15"
#     }
#   ]
# }

Query Multiple CVEs

# Batch query up to 100 CVEs
curl -s "https://api.first.org/data/v1/epss?cve=CVE-2024-3400,CVE-2024-21887,CVE-2023-44228" | \
  python3 -c "
import sys, json
data = json.load(sys.stdin)
for item in data['data']:
    pct = float(item['epss']) * 100
    print(f\"{item['cve']}: {pct:.2f}% exploitation probability (percentile: {item['percentile']})\")
"

Download Full EPSS Dataset

# Download complete daily EPSS scores (CSV format)
curl -s "https://epss.cyentia.com/epss_scores-current.csv.gz" | gunzip > epss_scores_current.csv
 
# Check size and preview
wc -l epss_scores_current.csv
head -5 epss_scores_current.csv

Query Historical EPSS Scores

# Get EPSS score for a specific date
curl -s "https://api.first.org/data/v1/epss?cve=CVE-2024-3400&date=2024-04-12"
 
# Get time series data
curl -s "https://api.first.org/data/v1/epss?cve=CVE-2024-3400&scope=time-series"

Prioritization Strategy

EPSS + CVSS Combined Approach

EPSS Score CVSS Score Priority Action
> 0.7 >= 9.0 P0 - Immediate Remediate within 24 hours
> 0.7 >= 7.0 P1 - Urgent Remediate within 48 hours
> 0.4 >= 7.0 P2 - High Remediate within 7 days
> 0.1 >= 4.0 P3 - Medium Remediate within 30 days
<= 0.1 >= 7.0 P3 - Medium Remediate within 30 days
<= 0.1 < 7.0 P4 - Low Remediate within 90 days

EPSS Percentile Thresholds

  • Top 1% (percentile >= 0.99): Extremely likely to be exploited; treat as Critical
  • Top 5% (percentile >= 0.95): High exploitation probability; prioritize remediation
  • Top 10% (percentile >= 0.90): Elevated risk; schedule for near-term remediation
  • Bottom 50%: Low exploitation probability; handle in normal patch cycle

Implementation

import requests
import pandas as pd
from datetime import datetime
 
def fetch_epss_scores(cve_list):
    """Fetch EPSS scores for a list of CVEs from FIRST API."""
    scores = {}
    batch_size = 100
    for i in range(0, len(cve_list), batch_size):
        batch = cve_list[i:i + batch_size]
        resp = requests.get(
            "https://api.first.org/data/v1/epss",
            params={"cve": ",".join(batch)},
            timeout=30
        )
        if resp.status_code == 200:
            for entry in resp.json().get("data", []):
                scores[entry["cve"]] = {
                    "epss": float(entry["epss"]),
                    "percentile": float(entry["percentile"]),
                    "date": entry.get("date", ""),
                }
    return scores
 
def prioritize_vulnerabilities(scan_results_csv, output_csv):
    """Enrich scan results with EPSS scores and assign priorities."""
    df = pd.read_csv(scan_results_csv)
    cve_list = df["cve_id"].dropna().unique().tolist()
 
    epss_data = fetch_epss_scores(cve_list)
 
    df["epss_score"] = df["cve_id"].map(lambda c: epss_data.get(c, {}).get("epss", 0))
    df["epss_percentile"] = df["cve_id"].map(lambda c: epss_data.get(c, {}).get("percentile", 0))
 
    def assign_priority(row):
        epss = row.get("epss_score", 0)
        cvss = row.get("cvss_score", 0)
        if epss > 0.7 and cvss >= 9.0:
            return "P0"
        if epss > 0.7 and cvss >= 7.0:
            return "P1"
        if epss > 0.4 and cvss >= 7.0:
            return "P2"
        if epss > 0.1 or cvss >= 7.0:
            return "P3"
        return "P4"
 
    df["priority"] = df.apply(assign_priority, axis=1)
    df = df.sort_values(["priority", "epss_score"], ascending=[True, False])
    df.to_csv(output_csv, index=False)
    print(f"[+] Prioritized {len(df)} vulnerabilities -> {output_csv}")
    print(f"    P0: {len(df[df['priority']=='P0'])}")
    print(f"    P1: {len(df[df['priority']=='P1'])}")
    print(f"    P2: {len(df[df['priority']=='P2'])}")
    print(f"    P3: {len(df[df['priority']=='P3'])}")
    print(f"    P4: {len(df[df['priority']=='P4'])}")
    return df

EPSS Trend Analysis

def fetch_epss_timeseries(cve_id):
    """Get historical EPSS scores for trend analysis."""
    resp = requests.get(
        "https://api.first.org/data/v1/epss",
        params={"cve": cve_id, "scope": "time-series"},
        timeout=30
    )
    if resp.status_code == 200:
        return resp.json().get("data", [])
    return []
 
def detect_epss_spikes(cve_id, threshold=0.3):
    """Detect significant EPSS score increases indicating emerging threats."""
    timeseries = fetch_epss_timeseries(cve_id)
    if len(timeseries) < 2:
        return False
    sorted_data = sorted(timeseries, key=lambda x: x.get("date", ""))
    latest = float(sorted_data[-1].get("epss", 0))
    previous = float(sorted_data[-2].get("epss", 0))
    increase = latest - previous
    if increase >= threshold:
        print(f"[!] EPSS spike detected for {cve_id}: {previous:.3f} -> {latest:.3f} (+{increase:.3f})")
        return True
    return False

References

Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md1.6 KB

API Reference — Implementing EPSS Score for Vulnerability Prioritization

Libraries Used

  • requests: HTTP client for FIRST.org EPSS API
  • csv: Parse and enrich vulnerability scan CSV files

CLI Interface

python agent.py score --cves CVE-2024-1234 CVE-2024-5678
python agent.py enrich --scan-file scan.csv [--output enriched.csv]

Core Functions

get_epss_scores(cve_list)

Fetches EPSS scores from the FIRST.org API (batches of 100).

API Endpoint: GET https://api.first.org/data/v1/epss?cve=CVE-1,CVE-2

Returns: dict with scores list, each containing cve, epss (0.0-1.0), percentile (0.0-1.0).

prioritize_vulnerabilities(cve_scores, epss_threshold=0.1, percentile_threshold=0.9)

Classifies CVEs into priority buckets based on EPSS probability.

Priority Buckets:

Priority Criteria
CRITICAL EPSS >= 0.1 or percentile >= 90th
HIGH EPSS >= 0.05
MEDIUM EPSS >= 0.01
LOW EPSS < 0.01

enrich_from_scan(scan_file, output_file=None)

Reads a CSV vulnerability scan, fetches EPSS for all CVEs, and writes enriched output.

Auto-detects columns: CVE, cve, CVE-ID, cve_id, vulnerability_id.

FIRST.org EPSS API

Parameter Description
cve Comma-separated CVE IDs (max 100 per request)
envelope Wrap response in metadata envelope
date Get scores for a specific date (YYYY-MM-DD)

Response Fields:

  • epss: Probability of exploitation in next 30 days (0.0–1.0)
  • percentile: Percentile rank relative to all scored CVEs

Dependencies

pip install requests>=2.31
standards.md2.7 KB

Standards and References - EPSS Vulnerability Prioritization

Primary Standards

FIRST EPSS

CVSS v3.1 and v4.0

  • Source: FIRST
  • URL: https://www.first.org/cvss/
  • Relevance: EPSS complements CVSS; CVSS measures severity, EPSS measures exploitation probability

CISA Stakeholder-Specific Vulnerability Categorization (SSVC)

CISA Known Exploited Vulnerabilities (KEV)

Research Papers

Original EPSS Paper

  • Title: "Improving Vulnerability Remediation Through Better Exploit Prediction"
  • Authors: Jay Jacobs, Sasha Romanosky, Benjamin Edwards, Michael Roytman, Idris Adjerid
  • Published: Workshop on the Economics of Information Security (WEIS), 2021

EPSS v3 Model

  • Features: 1,477 features including CVE properties, vendor data, social media mentions, exploit code availability
  • Training Data: Historical exploitation events from multiple sources
  • Performance: AUC of 0.85+ for 30-day exploitation prediction

Data Sources Used by EPSS

Source Data Type Update Frequency
NVD CVE metadata, CVSS scores Real-time
CISA KEV Confirmed exploitation As new CVEs added
Exploit-DB Public exploit code Daily
GitHub Exploit PoC repositories Daily
Metasploit Exploit modules Weekly
SecurityFocus Vulnerability discussions Daily
Social Media Twitter/X mentions of CVEs Real-time
Fortinet Exploitation telemetry Daily
AlienVault OTX Threat intelligence Daily

API Reference

Endpoints

  • Single CVE: GET https://api.first.org/data/v1/epss?cve=CVE-YYYY-NNNNN
  • Multiple CVEs: GET https://api.first.org/data/v1/epss?cve=CVE-1,CVE-2,...
  • Date-specific: GET https://api.first.org/data/v1/epss?cve=CVE-YYYY-NNNNN&date=YYYY-MM-DD
  • Time series: GET https://api.first.org/data/v1/epss?cve=CVE-YYYY-NNNNN&scope=time-series
  • Top scoring: GET https://api.first.org/data/v1/epss?percentile-gt=0.95
  • Full download: https://epss.cyentia.com/epss_scores-current.csv.gz
workflows.md1.3 KB

Workflows - EPSS Vulnerability Prioritization

Workflow 1: Daily EPSS Enrichment Pipeline

Steps

  1. Download full EPSS dataset from https://epss.cyentia.com/epss_scores-current.csv.gz
  2. Load into local database for fast lookups
  3. Query open vulnerabilities from vulnerability management platform
  4. Enrich each CVE with current EPSS score and percentile
  5. Apply priority matrix combining EPSS and CVSS scores
  6. Update priority fields in DefectDojo/Jira/tracking system
  7. Alert on any CVEs that crossed EPSS threshold (e.g., jumped above 0.4)

Workflow 2: EPSS Spike Detection

Steps

  1. Compare today's EPSS scores against yesterday's scores for all open CVEs
  2. Identify CVEs with EPSS increase > 0.2 in past 24 hours
  3. Cross-reference spike CVEs with asset inventory
  4. Send high-priority alert for spiking CVEs affecting production assets
  5. Automatically escalate to P1 if EPSS crosses 0.7 threshold

Workflow 3: Prioritized Remediation Report

Steps

  1. Pull all open vulnerabilities from scanner
  2. Enrich with EPSS scores and CISA KEV membership
  3. Apply combined EPSS + CVSS + KEV priority matrix
  4. Group by priority tier (P0-P4)
  5. Within each tier, sort by EPSS score descending
  6. Generate report showing estimated risk reduction per remediation action
  7. Distribute to asset owners with assigned remediation timelines

Scripts 2

agent.py5.0 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for implementing EPSS (Exploit Prediction Scoring System) for vulnerability prioritization."""

import json
import argparse
import csv

try:
    import requests
except ImportError:
    requests = None

EPSS_API_URL = "https://api.first.org/data/v1/epss"


def get_epss_scores(cve_list):
    """Fetch EPSS scores for a list of CVE IDs from the FIRST.org API."""
    if not requests:
        return {"error": "requests library not installed"}
    results = []
    # API supports up to 100 CVEs per request
    for i in range(0, len(cve_list), 100):
        batch = cve_list[i:i + 100]
        params = {"cve": ",".join(batch)}
        resp = requests.get(EPSS_API_URL, params=params, timeout=30)
        resp.raise_for_status()
        data = resp.json()
        for item in data.get("data", []):
            results.append({
                "cve": item["cve"],
                "epss": float(item["epss"]),
                "percentile": float(item["percentile"]),
            })
    return {"total": len(results), "scores": results}


def get_epss_csv():
    """Download the full EPSS score CSV from FIRST.org."""
    if not requests:
        return {"error": "requests library not installed"}
    resp = requests.get(f"{EPSS_API_URL}?envelope=true&pretty=true", timeout=60)
    resp.raise_for_status()
    return resp.json()


def prioritize_vulnerabilities(cve_scores, epss_threshold=0.1, percentile_threshold=0.9):
    """Prioritize vulnerabilities based on EPSS score and percentile."""
    critical = []
    high = []
    medium = []
    low = []
    for item in cve_scores:
        epss = item["epss"]
        pct = item["percentile"]
        if epss >= epss_threshold or pct >= percentile_threshold:
            item["priority"] = "CRITICAL"
            critical.append(item)
        elif epss >= 0.05:
            item["priority"] = "HIGH"
            high.append(item)
        elif epss >= 0.01:
            item["priority"] = "MEDIUM"
            medium.append(item)
        else:
            item["priority"] = "LOW"
            low.append(item)
    return {
        "thresholds": {"epss": epss_threshold, "percentile": percentile_threshold},
        "summary": {
            "critical": len(critical),
            "high": len(high),
            "medium": len(medium),
            "low": len(low),
        },
        "critical": sorted(critical, key=lambda x: x["epss"], reverse=True),
        "high": sorted(high, key=lambda x: x["epss"], reverse=True),
    }


def enrich_from_scan(scan_file, output_file=None):
    """Enrich a vulnerability scan CSV with EPSS scores."""
    with open(scan_file, "r") as f:
        reader = csv.DictReader(f)
        rows = list(reader)
    cve_col = None
    for col in ["CVE", "cve", "CVE-ID", "cve_id", "vulnerability_id"]:
        if col in (rows[0] if rows else {}):
            cve_col = col
            break
    if not cve_col:
        return {"error": "No CVE column found in scan file"}
    cves = [row[cve_col] for row in rows if row.get(cve_col, "").startswith("CVE-")]
    if not cves:
        return {"error": "No CVE IDs found in scan file"}
    epss_data = get_epss_scores(cves)
    epss_map = {s["cve"]: s for s in epss_data.get("scores", [])}

    enriched = []
    for row in rows:
        cve = row.get(cve_col, "")
        epss_info = epss_map.get(cve, {})
        row["epss_score"] = epss_info.get("epss", "N/A")
        row["epss_percentile"] = epss_info.get("percentile", "N/A")
        enriched.append(row)

    if output_file:
        fieldnames = list(enriched[0].keys())
        with open(output_file, "w", newline="") as f:
            writer = csv.DictWriter(f, fieldnames=fieldnames)
            writer.writeheader()
            writer.writerows(enriched)

    prioritized = prioritize_vulnerabilities(
        [s for s in epss_data.get("scores", [])]
    )
    return {
        "scan_file": scan_file,
        "total_cves": len(cves),
        "enriched_count": sum(1 for r in enriched if r["epss_score"] != "N/A"),
        "prioritization": prioritized["summary"],
        "top_10_exploitable": prioritized.get("critical", [])[:10],
    }


def main():
    parser = argparse.ArgumentParser(description="EPSS Vulnerability Prioritization Agent")
    sub = parser.add_subparsers(dest="command")
    s = sub.add_parser("score", help="Get EPSS scores for CVE IDs")
    s.add_argument("--cves", nargs="+", required=True, help="CVE IDs (e.g., CVE-2024-1234)")
    e = sub.add_parser("enrich", help="Enrich vulnerability scan with EPSS scores")
    e.add_argument("--scan-file", required=True, help="CSV vulnerability scan report")
    e.add_argument("--output", help="Output enriched CSV file")
    args = parser.parse_args()
    if args.command == "score":
        epss = get_epss_scores(args.cves)
        result = prioritize_vulnerabilities(epss.get("scores", []))
        result["raw_scores"] = epss["scores"]
    elif args.command == "enrich":
        result = enrich_from_scan(args.scan_file, args.output)
    else:
        parser.print_help()
        return
    print(json.dumps(result, indent=2, default=str))


if __name__ == "__main__":
    main()
process.py7.5 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""EPSS Vulnerability Prioritization Tool.

Fetches EPSS scores from FIRST API and prioritizes vulnerabilities
using a combined EPSS + CVSS matrix approach.
"""

import argparse
import csv
import gzip
import io
import json
import sys
import time
from datetime import datetime, timezone
from pathlib import Path

import requests

EPSS_API = "https://api.first.org/data/v1/epss"
EPSS_BULK_URL = "https://epss.cyentia.com/epss_scores-current.csv.gz"
KEV_URL = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"

PRIORITY_MAP = {
    "P0": {"label": "Immediate", "sla_hours": 24},
    "P1": {"label": "Urgent", "sla_hours": 48},
    "P2": {"label": "High", "sla_days": 7},
    "P3": {"label": "Medium", "sla_days": 30},
    "P4": {"label": "Low", "sla_days": 90},
}


def fetch_epss_bulk():
    """Download full EPSS dataset for local lookups."""
    print("[*] Downloading full EPSS dataset...")
    resp = requests.get(EPSS_BULK_URL, timeout=60)
    resp.raise_for_status()
    content = gzip.decompress(resp.content).decode("utf-8")
    reader = csv.DictReader(io.StringIO(content))
    scores = {}
    for row in reader:
        cve = row.get("cve", "").strip()
        if cve:
            scores[cve] = {
                "epss": float(row.get("epss", 0)),
                "percentile": float(row.get("percentile", 0)),
            }
    print(f"    Loaded EPSS scores for {len(scores)} CVEs")
    return scores


def fetch_epss_api(cve_list):
    """Fetch EPSS scores for specific CVEs via API."""
    scores = {}
    batch_size = 100
    for i in range(0, len(cve_list), batch_size):
        batch = cve_list[i : i + batch_size]
        try:
            resp = requests.get(
                EPSS_API, params={"cve": ",".join(batch)}, timeout=30
            )
            if resp.status_code == 200:
                for entry in resp.json().get("data", []):
                    scores[entry["cve"]] = {
                        "epss": float(entry.get("epss", 0)),
                        "percentile": float(entry.get("percentile", 0)),
                    }
        except requests.RequestException as e:
            print(f"[-] EPSS API error: {e}")
        time.sleep(0.5)
    return scores


def fetch_kev_catalog():
    """Download CISA KEV catalog."""
    resp = requests.get(KEV_URL, timeout=30)
    resp.raise_for_status()
    return {v["cveID"] for v in resp.json().get("vulnerabilities", [])}


def assign_priority(epss_score, cvss_score, in_kev=False):
    """Assign priority based on EPSS + CVSS + KEV matrix."""
    if in_kev:
        if cvss_score >= 9.0:
            return "P0"
        return "P1"
    if epss_score > 0.7 and cvss_score >= 9.0:
        return "P0"
    if epss_score > 0.7 and cvss_score >= 7.0:
        return "P1"
    if epss_score > 0.4 and cvss_score >= 7.0:
        return "P2"
    if epss_score > 0.1 or cvss_score >= 7.0:
        return "P3"
    return "P4"


def prioritize_scan_results(input_csv, output_csv, use_bulk=False):
    """Enrich vulnerability scan results with EPSS and prioritize."""
    vulnerabilities = []
    with open(input_csv, "r", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        for row in reader:
            vulnerabilities.append(row)

    cve_list = list({v.get("cve_id", "") for v in vulnerabilities if v.get("cve_id")})
    print(f"[*] Processing {len(vulnerabilities)} findings ({len(cve_list)} unique CVEs)")

    if use_bulk:
        epss_scores = fetch_epss_bulk()
    else:
        epss_scores = fetch_epss_api(cve_list)

    print("[*] Fetching CISA KEV catalog...")
    kev_set = fetch_kev_catalog()
    print(f"    {len(kev_set)} CVEs in KEV catalog")

    results = []
    for vuln in vulnerabilities:
        cve_id = vuln.get("cve_id", "")
        cvss = float(vuln.get("cvss_score", 0))
        epss_data = epss_scores.get(cve_id, {"epss": 0, "percentile": 0})
        in_kev = cve_id in kev_set
        priority = assign_priority(epss_data["epss"], cvss, in_kev)

        results.append({
            **vuln,
            "epss_score": round(epss_data["epss"], 5),
            "epss_percentile": round(epss_data["percentile"], 5),
            "in_cisa_kev": in_kev,
            "priority": priority,
            "priority_label": PRIORITY_MAP[priority]["label"],
        })

    results.sort(key=lambda r: (
        {"P0": 0, "P1": 1, "P2": 2, "P3": 3, "P4": 4}[r["priority"]],
        -r["epss_score"],
    ))

    if results:
        with open(output_csv, "w", newline="", encoding="utf-8") as f:
            writer = csv.DictWriter(f, fieldnames=results[0].keys())
            writer.writeheader()
            writer.writerows(results)

    priority_counts = {}
    for r in results:
        p = r["priority"]
        priority_counts[p] = priority_counts.get(p, 0) + 1

    print(f"\n[+] Prioritization Results -> {output_csv}")
    for p in ["P0", "P1", "P2", "P3", "P4"]:
        count = priority_counts.get(p, 0)
        print(f"    {p} ({PRIORITY_MAP[p]['label']}): {count}")
    print(f"    KEV matches: {sum(1 for r in results if r['in_cisa_kev'])}")
    return results


def detect_epss_spikes(previous_csv, current_scores, threshold=0.2):
    """Compare EPSS scores to detect significant increases."""
    previous = {}
    with open(previous_csv, "r", encoding="utf-8") as f:
        reader = csv.DictReader(f)
        for row in reader:
            cve = row.get("cve_id", "")
            if cve:
                previous[cve] = float(row.get("epss_score", 0))

    spikes = []
    for cve, prev_score in previous.items():
        current = current_scores.get(cve, {}).get("epss", 0)
        increase = current - prev_score
        if increase >= threshold:
            spikes.append({
                "cve_id": cve,
                "previous_epss": prev_score,
                "current_epss": current,
                "increase": round(increase, 5),
            })

    spikes.sort(key=lambda s: s["increase"], reverse=True)
    if spikes:
        print(f"\n[!] EPSS Spikes Detected ({len(spikes)} CVEs):")
        for s in spikes[:20]:
            print(f"    {s['cve_id']}: {s['previous_epss']:.4f} -> {s['current_epss']:.4f} (+{s['increase']:.4f})")
    return spikes


def main():
    parser = argparse.ArgumentParser(description="EPSS Vulnerability Prioritization Tool")
    parser.add_argument("--input", help="Input CSV with vulnerability scan results")
    parser.add_argument("--output", default="epss_prioritized.csv", help="Output prioritized CSV")
    parser.add_argument("--bulk", action="store_true", help="Use bulk EPSS download instead of API")
    parser.add_argument("--detect-spikes", help="Previous results CSV for spike detection")
    parser.add_argument("--spike-threshold", type=float, default=0.2, help="EPSS increase threshold")
    parser.add_argument("--query", help="Query EPSS for specific CVE(s), comma-separated")
    args = parser.parse_args()

    if args.query:
        cves = [c.strip() for c in args.query.split(",")]
        scores = fetch_epss_api(cves)
        for cve, data in scores.items():
            pct = data["epss"] * 100
            print(f"{cve}: {pct:.2f}% exploitation probability (percentile: {data['percentile']:.4f})")
    elif args.input:
        results = prioritize_scan_results(args.input, args.output, args.bulk)
        if args.detect_spikes:
            current_scores = {r["cve_id"]: {"epss": r["epss_score"]} for r in results if r.get("cve_id")}
            detect_epss_spikes(args.detect_spikes, current_scores, args.spike_threshold)
    else:
        parser.print_help()


if __name__ == "__main__":
    main()

Assets 1

template.mdtext/markdown · 1.7 KB
Keep exploring