endpoint security

Performing Endpoint Vulnerability Remediation

Performs vulnerability remediation on endpoints by prioritizing CVEs based on risk scoring, deploying patches, applying configuration changes, and validating fixes. Use when remediating findings from vulnerability scans, responding to critical CVE advisories, or maintaining endpoint compliance with patch management SLAs. Activates for requests involving vulnerability remediation, CVE patching, endpoint vulnerability management, or security fix deployment.

cvecvssendpointpatchingremediationvulnerability-management
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

When to Use

Use this skill when:

  • Remediating vulnerabilities identified by scanners (Nessus, Qualys, Rapid7)
  • Responding to zero-day CVE advisories requiring immediate patching
  • Maintaining compliance with patch management SLAs (critical within 14 days, high within 30 days)
  • Building a prioritized remediation plan from vulnerability scan results

Do not use this skill for vulnerability scanning itself (use scanning tools) or for application-layer vulnerability remediation (use DevSecOps processes).

Prerequisites

  • Vulnerability scan results (Nessus, Qualys, or Rapid7 export in CSV/XML format)
  • Patch management platform (WSUS, SCCM, Intune, or third-party like Automox)
  • Administrative access to target endpoints or deployment infrastructure
  • Change management process for production endpoint patching
  • Testing environment for patch validation before production rollout

Workflow

Step 1: Import and Prioritize Vulnerability Findings

Priority scoring combines:
1. CVSS Base Score (0-10)
2. EPSS (Exploit Prediction Scoring System) - probability of exploitation
3. CISA KEV (Known Exploited Vulnerabilities) catalog membership
4. Asset criticality (business impact of affected endpoint)
5. Network exposure (internet-facing vs. internal)
 
Priority Matrix:
  P1 (Critical - 14 days SLA):
    - CVSS >= 9.0 OR
    - Listed in CISA KEV OR
    - Active exploitation in the wild + CVSS >= 7.0
 
  P2 (High - 30 days SLA):
    - CVSS 7.0-8.9 AND
    - EPSS > 0.5 (50% probability of exploitation)
 
  P3 (Medium - 60 days SLA):
    - CVSS 4.0-6.9 OR
    - CVSS 7.0-8.9 with EPSS < 0.1
 
  P4 (Low - 90 days SLA):
    - CVSS < 4.0 AND
    - No known exploit

Step 2: Identify Remediation Actions

For each vulnerability, determine the appropriate remediation:

Remediation Types:
1. Patch: Apply vendor security update (most common)
2. Configuration change: Modify settings to mitigate (registry, GPO)
3. Upgrade: Update to newer software version
4. Workaround: Apply temporary mitigation when patch unavailable
5. Compensating control: Network segmentation, WAF rule, EDR rule
6. Accept risk: Document accepted risk with CISO sign-off

Step 3: Deploy Patches via WSUS/SCCM

# WSUS: Approve patches for deployment
# 1. Open WSUS Console
# 2. Navigate to Updates → Security Updates
# 3. Approve selected KBs for target computer groups
 
# SCCM: Create Software Update Group
# 1. Software Library → Software Updates → All Software Updates
# 2. Select required KBs → Create Software Update Group
# 3. Deploy to target collection with maintenance window
 
# Intune: Create Windows Update Ring
# Devices → Windows → Update rings
# Configure: Quality updates deferral = 0 days (for critical)
# Feature updates deferral = per policy
 
# PowerShell: Force Windows Update check
Install-Module PSWindowsUpdate -Force
Get-WindowsUpdate -KBArticleID "KB5034441" -Install -AcceptAll -AutoReboot
 
# Verify patch installation
Get-HotFix -Id "KB5034441"
systeminfo | findstr "KB5034441"

Step 4: Apply Configuration-Based Remediations

# Example: Disable SMBv1 (CVE-2017-0144 - EternalBlue)
Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force
Disable-WindowsOptionalFeature -Online -FeatureName SMB1Protocol -NoRestart
 
# Example: Disable Print Spooler on non-print servers (CVE-2021-34527 - PrintNightmare)
Stop-Service -Name Spooler -Force
Set-Service -Name Spooler -StartupType Disabled
 
# Example: Disable LLMNR (credential theft mitigation)
# Via GPO: Computer Configuration → Admin Templates → Network → DNS Client
# Turn off multicast name resolution: Enabled
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient" `
  -Name EnableMulticast -Value 0 -PropertyType DWORD -Force
 
# Example: Restrict NTLM authentication
# Via GPO: Security Settings → Local Policies → Security Options
# Network security: Restrict NTLM: Audit/Deny

Step 5: Handle Zero-Day Vulnerabilities (No Patch Available)

When vendor patch is not yet available:
 
1. Check vendor advisory for workarounds
   - Microsoft: https://msrc.microsoft.com/update-guide
   - Adobe: https://helpx.adobe.com/security.html
   - Linux: Distribution security trackers
 
2. Apply temporary mitigations:
   - Disable vulnerable feature/service
   - Deploy EDR detection rule for exploitation attempt
   - Apply network-level blocking (WAF/firewall rules)
   - Restrict access to vulnerable application
 
3. Monitor for patch release:
   - Subscribe to vendor security mailing list
   - Monitor CISA KEV additions
   - Set calendar reminder for next Patch Tuesday
 
4. Document workaround with expiration date

Step 6: Validate Remediation

# Re-scan remediated endpoints to confirm vulnerability closure
# Option 1: Targeted vulnerability scan
nessuscli scan --target 192.168.1.0/24 --plugin-id 12345
 
# Option 2: PowerShell verification
# Check specific KB is installed
$kb = Get-HotFix -Id "KB5034441" -ErrorAction SilentlyContinue
if ($kb) {
    Write-Host "PASS: KB5034441 installed on $(hostname)" -ForegroundColor Green
} else {
    Write-Host "FAIL: KB5034441 missing on $(hostname)" -ForegroundColor Red
}
 
# Check service is disabled
$svc = Get-Service -Name Spooler
if ($svc.StartType -eq 'Disabled') {
    Write-Host "PASS: Print Spooler disabled" -ForegroundColor Green
}
 
# Check registry configuration
$val = Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" `
  -Name SMB1 -ErrorAction SilentlyContinue
if ($val.SMB1 -eq 0) {
    Write-Host "PASS: SMBv1 disabled" -ForegroundColor Green
}

Step 7: Report and Track

Generate remediation status report:

Remediation Metrics:
  - Total vulnerabilities: X
  - Remediated: Y (Z%)
  - Pending (within SLA): A
  - Overdue (past SLA): B
  - Accepted risk: C
  - Mean time to remediate (MTTR): D days
  - SLA compliance rate: E%

Key Concepts

Term Definition
CVSS Common Vulnerability Scoring System; 0-10 severity scale for vulnerabilities
EPSS Exploit Prediction Scoring System; probability (0-1) that a CVE will be exploited in the wild within 30 days
CISA KEV CISA Known Exploited Vulnerabilities catalog; federal mandate to patch these CVEs within specified timeframes
SLA Service Level Agreement for remediation timelines based on vulnerability severity
MTTR Mean Time To Remediate; average days from vulnerability discovery to confirmed fix
Compensating Control Alternative security measure when direct remediation is not feasible

Tools & Systems

  • Nessus/Tenable.io: Vulnerability scanning and remediation tracking
  • Qualys VMDR: Vulnerability management, detection, and response platform
  • Rapid7 InsightVM: Vulnerability assessment with live dashboards
  • WSUS/SCCM/Intune: Microsoft patch deployment infrastructure
  • Automox: Cloud-native patch management for Windows, macOS, Linux
  • CISA KEV Catalog: https://www.cisa.gov/known-exploited-vulnerabilities-catalog

Common Pitfalls

  • Patching without testing: Apply patches to a test group first. Some patches cause application compatibility issues or BSOD.
  • Ignoring EPSS scores: A CVSS 9.8 vulnerability with EPSS 0.01 may be less urgent than a CVSS 7.5 with EPSS 0.95 (actively exploited).
  • Not validating remediation: Deploying a patch does not guarantee installation. Always re-scan to confirm closure.
  • Excluding critical servers from patching: Servers that "cannot be rebooted" accumulate critical vulnerabilities. Schedule maintenance windows.
  • Treating all CVEs equally: Risk-based prioritization (CVSS + EPSS + asset criticality + exposure) is more effective than patching all criticals first.
Source materials

References and resources

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

References 3

api-reference.md4.4 KB

API Reference — Performing Endpoint Vulnerability Remediation

Libraries Used

Library Purpose
csv Parse vulnerability scan CSV exports (Nessus, Qualys, Rapid7)
subprocess Check installed Windows patches via wmic qfe and PowerShell
socket Validate port-based remediation via TCP connect
json Read/write remediation plans and reports
argparse CLI argument parsing for scan file and host parameters
datetime Track patch dates and SLA deadlines

CLI Interface

python agent.py parse --scan-file scan.csv
python agent.py patches
python agent.py validate --host 10.0.0.1 --port 445
python agent.py report --scan-file scan.csv [--output plan.json]

Core Functions

parse_scan_report(csv_file) — Parse and prioritize vulnerabilities by severity

def parse_scan_report(csv_file):
    """Parse Nessus/Qualys CSV export, group by host, sort by severity."""
    with open(csv_file, newline="") as f:
        reader = csv.DictReader(f)
        vulns = []
        for row in reader:
            vulns.append({
                "host": row.get("Host", row.get("IP")),
                "plugin_id": row.get("Plugin ID", row.get("QID")),
                "severity": row.get("Risk", row.get("Severity", "Info")),
                "name": row.get("Name", row.get("Title")),
                "cve": row.get("CVE", ""),
                "solution": row.get("Solution", row.get("Fix", "")),
            })
    severity_order = {"Critical": 0, "High": 1, "Medium": 2, "Low": 3, "Info": 4}
    return sorted(vulns, key=lambda v: severity_order.get(v["severity"], 5))

check_windows_patches() — List installed Windows hotfixes via WMIC

def check_windows_patches():
    """Query installed patches on a Windows endpoint."""
    result = subprocess.run(
        ["wmic", "qfe", "get", "HotFixID,InstalledOn,Description", "/format:csv"],
        capture_output=True, text=True, timeout=30,
    )
    patches = []
    for line in result.stdout.strip().split("\n")[1:]:
        parts = line.strip().split(",")
        if len(parts) >= 4:
            patches.append({
                "hotfix_id": parts[1],
                "description": parts[2],
                "installed_on": parts[3],
            })
    return patches

validate_remediation(host, port) — TCP connect to verify port closure

def validate_remediation(host, port):
    """Verify that a vulnerable port has been closed after remediation."""
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(5)
    try:
        result = sock.connect_ex((host, int(port)))
        return {
            "host": host,
            "port": port,
            "status": "open" if result == 0 else "closed",
            "remediated": result != 0,
        }
    finally:
        sock.close()

generate_remediation_report(scan_file, output) — Group vulns by host for remediation

def generate_remediation_report(scan_file, output=None):
    """Generate a prioritized remediation plan from scan results."""
    vulns = parse_scan_report(scan_file)
    by_host = {}
    for v in vulns:
        by_host.setdefault(v["host"], []).append(v)
 
    report = {
        "total_vulns": len(vulns),
        "hosts_affected": len(by_host),
        "by_severity": {},
        "remediation_plan": [],
    }
    for severity in ["Critical", "High", "Medium", "Low"]:
        count = sum(1 for v in vulns if v["severity"] == severity)
        report["by_severity"][severity] = count
 
    for host, host_vulns in sorted(by_host.items()):
        report["remediation_plan"].append({
            "host": host,
            "vuln_count": len(host_vulns),
            "critical": sum(1 for v in host_vulns if v["severity"] == "Critical"),
            "patches": [v["name"] for v in host_vulns[:10]],
        })
 
    if output:
        with open(output, "w") as f:
            json.dump(report, f, indent=2)
    return report

Output Format

{
  "total_vulns": 245,
  "hosts_affected": 42,
  "by_severity": {
    "Critical": 8,
    "High": 35,
    "Medium": 112,
    "Low": 90
  },
  "remediation_plan": [
    {
      "host": "10.0.0.50",
      "vuln_count": 12,
      "critical": 2,
      "patches": ["MS17-010: EternalBlue", "CVE-2024-21887: Ivanti RCE"]
    }
  ]
}

Dependencies

No external packages — Python standard library only.

standards.md2.6 KB

Standards & References - Performing Endpoint Vulnerability Remediation

Primary Standards

NIST SP 800-40 Rev 4 - Guide to Enterprise Patch Management Planning

CISA Binding Operational Directive 22-01 - Known Exploited Vulnerabilities

FIRST CVSS v3.1 Specification

FIRST EPSS Model

  • Publisher: FIRST
  • URL: https://www.first.org/epss/
  • Scope: Machine learning model predicting probability of CVE exploitation within 30 days

Compliance Mappings

Framework Requirement Remediation Coverage
PCI DSS 4.0 6.3.3 - Patch within one month of release Patch SLA tracking and compliance
PCI DSS 4.0 11.3.1 - Internal vulnerability scans quarterly Scan-remediate-validate cycle
NIST 800-53 SI-2 Flaw Remediation Vulnerability identification and patching
NIST 800-53 RA-5 Vulnerability Monitoring and Scanning Ongoing scan-remediate process
HIPAA 164.308(a)(1)(ii)(B) - Risk Management Vulnerability remediation as risk reduction
ISO 27001 A.12.6.1 - Management of technical vulnerabilities Systematic vulnerability remediation
SOC 2 CC7.1 - Detect and address vulnerabilities Vulnerability management program

Remediation SLA Benchmarks

Severity CVSS Range Industry Standard SLA CISA KEV Timeline
Critical 9.0-10.0 14 days Per directive (usually 14 days)
High 7.0-8.9 30 days Per directive
Medium 4.0-6.9 60 days N/A unless in KEV
Low 0.1-3.9 90 days N/A

Supporting References

workflows.md3.5 KB

Workflows - Performing Endpoint Vulnerability Remediation

Workflow 1: Standard Vulnerability Remediation Cycle

[Vulnerability Scan Complete]


[Import scan results into tracking system]


[Risk-based prioritization]

    ├── CVSS + EPSS + CISA KEV + Asset criticality


[Assign priorities: P1/P2/P3/P4]


[Identify remediation action per CVE]

    ├── Patch available ──► [Schedule patch deployment]
    ├── Config change needed ──► [Create change request]
    ├── No patch available ──► [Apply workaround/compensating control]
    └── Accept risk ──► [Document with CISO approval]


[Test patches in staging environment]


[Deploy to production (phased rollout)]


[Re-scan to validate remediation]

    ├── Vulnerability closed ──► [Mark resolved in tracker]

    └── Still open ──► [Investigate failure, re-remediate]

Workflow 2: Emergency Zero-Day Response

[Zero-day CVE announced (CISA alert / vendor advisory)]


[Assess exposure: How many endpoints affected?]


[Is patch available?]

    ├── Yes ──► [Emergency patch deployment (skip staging)]
    │               │
    │               ▼
    │          [Monitor for deployment failures]
    │               │
    │               ▼
    │          [Validate patch across fleet]

    └── No ──► [Apply vendor workaround immediately]

                    ├── Disable vulnerable service/feature
                    ├── Deploy network-level mitigation
                    ├── Create EDR detection rule


               [Monitor for patch release]


               [Deploy patch when available]


               [Remove workaround, validate fix]

Workflow 3: Patch Deployment Pipeline

[Patch Tuesday (or vendor release)]


[Download and catalog new patches]


[Risk assessment: Which patches are critical?]


[Deploy to test ring (5% of fleet) - Day 1-3]

    ├── Test application compatibility
    ├── Monitor for BSOD, crashes, performance issues


[Deploy to pilot ring (20% of fleet) - Day 4-7]

    ├── Broader application testing
    ├── User feedback collection


[Deploy to production ring (remaining fleet) - Day 8-14]


[Generate compliance report]

    ├── Endpoints patched: X%
    ├── Pending reboot: Y
    └── Failed deployments: Z (investigate)

Workflow 4: SLA Compliance Tracking

[Weekly SLA Review]


[Query open vulnerabilities grouped by SLA status]

    ├── Within SLA ──► [Track progress, no action needed]

    ├── Approaching SLA (7 days) ──► [Escalate to endpoint team]

    └── Overdue (past SLA) ──► [Escalate to management]

                                     ├── Remediation feasible ──► [Emergency remediation]

                                     └── Blocked (dependency) ──► [Document exception, compensating control]

Scripts 2

agent.py4.6 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for performing endpoint vulnerability remediation tracking and validation."""

import json
import argparse
import subprocess
import csv
from datetime import datetime


def parse_scan_report(csv_file):
    """Parse a vulnerability scan CSV report and prioritize remediation."""
    with open(csv_file, "r", encoding="utf-8", errors="replace") as f:
        reader = csv.DictReader(f)
        rows = list(reader)
    vulns = []
    for row in rows:
        severity = row.get("Severity", row.get("severity", row.get("Risk", ""))).lower()
        vulns.append({
            "host": row.get("Host", row.get("IP", row.get("ip", ""))),
            "port": row.get("Port", row.get("port", "")),
            "cve": row.get("CVE", row.get("cve", row.get("Plugin ID", ""))),
            "title": row.get("Name", row.get("title", row.get("Summary", "")))[:200],
            "severity": severity,
            "solution": row.get("Solution", row.get("Fix", ""))[:300],
        })
    by_severity = {}
    for v in vulns:
        s = v["severity"]
        by_severity[s] = by_severity.get(s, 0) + 1
    critical_high = [v for v in vulns if v["severity"] in ("critical", "high")]
    return {
        "total_vulns": len(vulns),
        "by_severity": by_severity,
        "critical_high_count": len(critical_high),
        "remediation_queue": sorted(critical_high, key=lambda x: 0 if x["severity"] == "critical" else 1),
    }


def check_windows_patches():
    """Check installed Windows patches and identify missing ones."""
    try:
        result = subprocess.run(
            ["wmic", "qfe", "get", "HotFixID,InstalledOn,Description", "/format:csv"],
            capture_output=True, text=True, timeout=30
        )
        from io import StringIO
        reader = csv.DictReader(StringIO(result.stdout))
        patches = [{"id": r.get("HotFixID"), "date": r.get("InstalledOn"), "desc": r.get("Description")}
                    for r in reader if r.get("HotFixID")]
        return {"installed_patches": len(patches), "patches": patches}
    except Exception as e:
        return {"error": str(e)}


def validate_remediation(host, port, check_type="port_open"):
    """Validate that a vulnerability has been remediated."""
    import socket
    result = {"host": host, "port": int(port), "check_type": check_type}
    if check_type == "port_open":
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(5)
        try:
            sock.connect((host, int(port)))
            result["status"] = "STILL_OPEN"
            result["remediated"] = False
        except (socket.timeout, ConnectionRefusedError, OSError):
            result["status"] = "CLOSED"
            result["remediated"] = True
        finally:
            sock.close()
    return result


def generate_remediation_report(scan_file, output=None):
    """Generate a remediation plan from scan results."""
    parsed = parse_scan_report(scan_file)
    plan = {"generated": datetime.utcnow().isoformat(), "source": scan_file}
    plan["summary"] = parsed["by_severity"]
    plan["total"] = parsed["total_vulns"]
    hosts = {}
    for v in parsed["remediation_queue"]:
        h = v["host"]
        if h not in hosts:
            hosts[h] = []
        hosts[h].append(v)
    plan["by_host"] = {h: {"count": len(vs), "vulns": vs} for h, vs in hosts.items()}
    if output:
        with open(output, "w") as f:
            json.dump(plan, f, indent=2)
    return plan


def main():
    parser = argparse.ArgumentParser(description="Endpoint Vulnerability Remediation Agent")
    sub = parser.add_subparsers(dest="command")
    p = sub.add_parser("parse", help="Parse vulnerability scan report")
    p.add_argument("--scan-file", required=True)
    sub.add_parser("patches", help="Check installed Windows patches")
    v = sub.add_parser("validate", help="Validate remediation")
    v.add_argument("--host", required=True)
    v.add_argument("--port", required=True)
    r = sub.add_parser("report", help="Generate remediation report")
    r.add_argument("--scan-file", required=True)
    r.add_argument("--output", help="Output JSON file")
    args = parser.parse_args()
    if args.command == "parse":
        result = parse_scan_report(args.scan_file)
    elif args.command == "patches":
        result = check_windows_patches()
    elif args.command == "validate":
        result = validate_remediation(args.host, args.port)
    elif args.command == "report":
        result = generate_remediation_report(args.scan_file, args.output)
    else:
        parser.print_help()
        return
    print(json.dumps(result, indent=2, default=str))


if __name__ == "__main__":
    main()
process.py7.8 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
Endpoint Vulnerability Remediation Prioritizer

Parses vulnerability scan exports (Nessus CSV), enriches with EPSS scores,
cross-references CISA KEV catalog, and generates prioritized remediation plans.
"""

import json
import csv
import sys
import os
from datetime import datetime, timedelta
from collections import defaultdict
from urllib.request import urlopen
from urllib.error import URLError


CISA_KEV_URL = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
EPSS_API_URL = "https://api.first.org/data/v1/epss"


def load_nessus_csv(csv_path: str) -> list:
    """Parse Nessus scan export CSV into vulnerability records."""
    vulns = []

    with open(csv_path, "r", encoding="utf-8-sig") as f:
        reader = csv.DictReader(f)
        for row in reader:
            cvss = 0.0
            try:
                cvss = float(row.get("CVSS v3.0 Base Score", "0") or
                             row.get("CVSS v2.0 Base Score", "0") or "0")
            except ValueError:
                pass

            cve_list = [c.strip() for c in row.get("CVE", "").split(",") if c.strip()]

            vuln = {
                "plugin_id": row.get("Plugin ID", ""),
                "plugin_name": row.get("Name", ""),
                "severity": row.get("Risk", "None"),
                "host": row.get("Host", ""),
                "protocol": row.get("Protocol", ""),
                "port": row.get("Port", ""),
                "cvss_score": cvss,
                "cves": cve_list,
                "solution": row.get("Solution", ""),
                "synopsis": row.get("Synopsis", ""),
                "description": row.get("Description", "")[:200],
            }
            vulns.append(vuln)

    return vulns


def fetch_cisa_kev() -> set:
    """Fetch CISA Known Exploited Vulnerabilities catalog."""
    try:
        with urlopen(CISA_KEV_URL, timeout=15) as resp:
            data = json.loads(resp.read())
            return {v["cveID"] for v in data.get("vulnerabilities", [])}
    except (URLError, json.JSONDecodeError, KeyError) as e:
        print(f"Warning: Could not fetch CISA KEV catalog: {e}")
        return set()


def fetch_epss_scores(cves: list) -> dict:
    """Fetch EPSS scores for a list of CVEs."""
    epss_scores = {}
    batch_size = 100

    for i in range(0, len(cves), batch_size):
        batch = cves[i:i + batch_size]
        cve_param = ",".join(batch)
        url = f"{EPSS_API_URL}?cve={cve_param}"
        try:
            with urlopen(url, timeout=15) as resp:
                data = json.loads(resp.read())
                for item in data.get("data", []):
                    epss_scores[item["cve"]] = float(item.get("epss", 0))
        except (URLError, json.JSONDecodeError) as e:
            print(f"Warning: EPSS lookup failed for batch: {e}")

    return epss_scores


def prioritize_vulnerabilities(vulns: list, kev_cves: set, epss_scores: dict) -> list:
    """Assign remediation priority based on risk scoring."""
    for vuln in vulns:
        cvss = vuln["cvss_score"]
        cves = vuln["cves"]

        in_kev = any(cve in kev_cves for cve in cves)
        max_epss = max((epss_scores.get(cve, 0) for cve in cves), default=0)

        vuln["in_cisa_kev"] = in_kev
        vuln["epss_score"] = round(max_epss, 4)

        if cvss >= 9.0 or in_kev or (cvss >= 7.0 and max_epss > 0.7):
            vuln["priority"] = "P1"
            vuln["sla_days"] = 14
        elif cvss >= 7.0 and max_epss > 0.5:
            vuln["priority"] = "P2"
            vuln["sla_days"] = 30
        elif cvss >= 4.0:
            vuln["priority"] = "P3"
            vuln["sla_days"] = 60
        else:
            vuln["priority"] = "P4"
            vuln["sla_days"] = 90

        vuln["sla_deadline"] = (
            datetime.utcnow() + timedelta(days=vuln["sla_days"])
        ).strftime("%Y-%m-%d")

    vulns.sort(key=lambda v: (
        {"P1": 0, "P2": 1, "P3": 2, "P4": 3}.get(v["priority"], 4),
        -v["cvss_score"],
        -v["epss_score"],
    ))

    return vulns


def generate_remediation_plan(vulns: list, output_path: str) -> None:
    """Generate prioritized remediation plan in JSON."""
    summary = defaultdict(int)
    hosts_affected = defaultdict(set)

    for vuln in vulns:
        summary[vuln["priority"]] += 1
        hosts_affected[vuln["priority"]].add(vuln["host"])

    plan = {
        "report_generated": datetime.utcnow().isoformat() + "Z",
        "summary": {
            "total_vulnerabilities": len(vulns),
            "by_priority": dict(summary),
            "unique_hosts": {p: len(h) for p, h in hosts_affected.items()},
        },
        "kev_vulnerabilities": [v for v in vulns if v.get("in_cisa_kev")],
        "remediation_queue": [
            {
                "priority": v["priority"],
                "sla_deadline": v["sla_deadline"],
                "host": v["host"],
                "plugin_name": v["plugin_name"],
                "cvss": v["cvss_score"],
                "epss": v["epss_score"],
                "cisa_kev": v["in_cisa_kev"],
                "cves": v["cves"],
                "solution": v["solution"],
            }
            for v in vulns
        ],
    }

    with open(output_path, "w", encoding="utf-8") as f:
        json.dump(plan, f, indent=2)


def export_remediation_csv(vulns: list, output_path: str) -> None:
    """Export remediation plan to CSV for team assignment."""
    with open(output_path, "w", newline="", encoding="utf-8") as f:
        writer = csv.writer(f)
        writer.writerow([
            "Priority", "SLA Deadline", "Host", "Vulnerability",
            "CVSS", "EPSS", "CISA KEV", "CVEs", "Solution",
            "Status", "Assigned To", "Notes",
        ])
        for v in vulns:
            writer.writerow([
                v["priority"], v["sla_deadline"], v["host"],
                v["plugin_name"], v["cvss_score"], v["epss_score"],
                v["in_cisa_kev"], "; ".join(v["cves"]),
                v["solution"][:200], "Open", "", "",
            ])


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python process.py <nessus_export.csv>")
        print()
        print("Parses Nessus CSV export, enriches with EPSS/CISA KEV data,")
        print("and generates a prioritized remediation plan.")
        sys.exit(1)

    csv_path = sys.argv[1]
    if not os.path.exists(csv_path):
        print(f"Error: File not found: {csv_path}")
        sys.exit(1)

    print("Parsing vulnerability scan results...")
    vulns = load_nessus_csv(csv_path)
    print(f"Loaded {len(vulns)} vulnerability findings")

    all_cves = list({cve for v in vulns for cve in v["cves"]})
    print(f"Unique CVEs: {len(all_cves)}")

    print("Fetching CISA KEV catalog...")
    kev_cves = fetch_cisa_kev()
    print(f"KEV catalog contains {len(kev_cves)} CVEs")

    print("Fetching EPSS scores...")
    epss_scores = fetch_epss_scores(all_cves) if all_cves else {}
    print(f"Retrieved EPSS scores for {len(epss_scores)} CVEs")

    print("Prioritizing vulnerabilities...")
    vulns = prioritize_vulnerabilities(vulns, kev_cves, epss_scores)

    base = os.path.splitext(os.path.basename(csv_path))[0]
    out_dir = os.path.dirname(csv_path) or "."

    plan_path = os.path.join(out_dir, f"{base}_remediation_plan.json")
    generate_remediation_plan(vulns, plan_path)
    print(f"Remediation plan: {plan_path}")

    csv_out = os.path.join(out_dir, f"{base}_remediation.csv")
    export_remediation_csv(vulns, csv_out)
    print(f"Remediation CSV: {csv_out}")

    print(f"\n--- Remediation Summary ---")
    for p in ["P1", "P2", "P3", "P4"]:
        count = sum(1 for v in vulns if v["priority"] == p)
        if count:
            print(f"  {p}: {count} vulnerabilities")

    kev_count = sum(1 for v in vulns if v.get("in_cisa_kev"))
    if kev_count:
        print(f"\n  CISA KEV matches: {kev_count} (mandatory remediation)")

Assets 1

template.mdtext/markdown · 1.9 KB
Keep exploring