CVSS base score tells you a vulnerability's theoretical severity; it does not tell you whether anyone is exploiting it, whether an exploit exists, or whether the affected asset even matters in your environment.
Patching strictly by CVSS means you spend the same urgency on a critical bug in a locked-down internal tool as on a medium bug being weaponized in the wild against your public API. AI helps by fusing the signals that actually predict risk — EPSS exploitation probability, CISA KEV known-exploited status, and your own asset context — into a defensible priority order. The model reasons and explains; the feeds provide the ground truth. Your job is to confirm the inputs are current and the ranking survives scrutiny.
CVSS = severity if exploited; EPSS = probability of exploitation in the next 30 days; KEV = confirmed exploited in the wild right now. A mature prioritization uses all three plus asset context — never CVSS alone.
Assemble the inputs. For each vulnerability: CVE ID, CVSS, the current EPSS score, KEV membership, and asset context (internet-facing? sensitive data? compensating controls?). Pull EPSS and KEV fresh — they change daily.
Prompt for a ranked, reasoned priority — and use structured output so it's programmatic. For a repeatable pipeline, drive it through the Anthropic SDK:
import anthropic
from pydantic import BaseModel
class Ranked(BaseModel):
cve: str
priority: int # 1 = patch first
tier: str # "Immediate" | "This cycle" | "Backlog"
rationale: str # why this rank, citing EPSS/KEV/asset context
class Plan(BaseModel):
items: list[Ranked]
client = anthropic.Anthropic()
response = client.messages.parse(
model="claude-opus-4-8",
max_tokens=8000,
thinking={"type": "adaptive"},
messages=[{
"role": "user",
"content": (
"Rank these vulnerabilities for patching by REAL exploitability, "
"not raw CVSS. Weight KEV membership and high EPSS above CVSS, and "
"weight internet-facing / sensitive assets above internal ones. "
"Cite the specific signals in each rationale.\n\n" + vuln_table
),
}],
output_format=Plan,
)
plan = response.parsed_output
for item in plan.items:
print(item.priority, item.cve, item.tier, "-", item.rationale)
Expected output: a validated ranking where a KEV-listed, high-EPSS, internet-facing medium sits above a critical that's internal-only with no known exploit — each with a rationale you can quote to leadership.
Sanity-check the top of the list against KEV directly. Anything on CISA KEV is being exploited now; confirm every KEV item landed in the Immediate tier regardless of CVSS.
Reconcile with asset reality. The model only knows the asset context you fed it. Cross-check the top items against your CMDB — is the "internet-facing" flag still true? Is there a compensating control (WAF rule, network segmentation) that changes the urgency?
Produce the patch plan. Group by tier, attach the rationale, and hand it to the owners — the rationale is what gets a disruptive emergency patch approved.
Vulnerability inventories reveal a client's weak spots and asset topology — sensitive if leaked. EPSS and KEV are public feeds, so you can enrich locally without exposing anything. Before prompting, replace real hostnames and asset identifiers with roles ("public API gateway", "internal HR DB") — the ranking logic only needs exposure and sensitivity, not names. Where the client bars external AI, run a local model for the reasoning; the feeds are just data files you already hold. Keep the patch plan in the client's own tracker and confirm per-client tool approval before sending any inventory detail outward.