Vulnerability intelligence is not vulnerability scanning — it is the analysis that answers “which of these vulnerabilities actually matters to us right now?”
Vulnerability Prioritization Framework
VULNERABILITY PRIORITIZATION METHODOLOGY
=========================================
INPUT: 847 vulnerabilities (CVSS 7.0+)
GOAL: Identify top 50 for immediate patching
PASS 1 — Confirmed exploitation filter (binary — include/exclude)
Check each CVE against CISA KEV catalog:
→ KEV hit = automatic top-50 candidate regardless of CVSS
Check each CVE against EPSS:
→ EPSS > 0.50 (50% exploitation probability in 30 days) = top-50 candidate
Result: likely 20-80 CVEs pass this filter (varies by environment)
PASS 2 — Threat actor relevance filter
For each remaining CVE:
→ Has any threat actor targeting our sector exploited this CVE?
→ Sources: vendor reports, CISA advisories, ISAC bulletins, threat actor profiles
Result: CVEs with actor attribution + organizational relevance elevated to top priority
PASS 3 — Asset criticality filter
For each remaining CVE:
→ What asset is vulnerable? (internet-facing vs. internal vs. non-critical)
→ Internet-facing assets: elevated priority
→ Assets processing PII, financial data, or intellectual property: elevated
→ End-of-life systems that cannot be patched: document separately for risk acceptance
Result: same CVE in internet-facing VPN vs. air-gapped lab = very different priority
PASS 4 — Exploitability in environment filter
For each remaining CVE:
→ Is the exploitation condition met in our environment?
→ Auth required: do external users have valid credentials?
→ Adjacent network access required: is the service network-reachable from expected attacker vantage?
Result: narrows further based on realistic exploitation path
FINAL RANKING:
Priority 1: KEV + EPSS>0.50 + internet-facing + actor-relevant = EMERGENCY PATCH (this week)
Priority 2: EPSS>0.20 + actor-relevant + critical asset = URGENT (this sprint)
Priority 3: EPSS>0.05 + internet-facing = STANDARD (this quarter)
Priority 4: Everything else = SCHEDULED (next quarter or risk-accept)
OUTPUT: Ranked list with CVSS, EPSS, KEV status, exploiting actor, affected asset tier
EPSS and KEV Data Access
# Pull EPSS scores from FIRST API
import requests
import json
def get_epss_scores(cve_list):
"""Fetch EPSS scores for a list of CVEs"""
# EPSS API - free, no key required
cve_param = ','.join(cve_list)
url = f"https://api.first.org/data/v1/epss?cve={cve_param}"
response = requests.get(url)
data = response.json()
results = {}
for item in data['data']:
results[item['cve']] = {
'epss': float(item['epss']),
'percentile': float(item['percentile']),
'date': item['date']
}
return results
# Pull CISA KEV catalog
def get_kev_catalog():
"""Download the full CISA KEV catalog"""
url = "https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
response = requests.get(url)
kev_data = response.json()
kev_cves = {v['cveID']: v for v in kev_data['vulnerabilities']}
return kev_cves
# Prioritization analysis
def prioritize_vulnerabilities(vuln_list):
"""
vuln_list: list of dicts with at least 'cve_id', 'cvss_score', 'asset_tier'
asset_tier: 1=internet-facing, 2=internal-critical, 3=internal-standard
"""
kev = get_kev_catalog()
cve_ids = [v['cve_id'] for v in vuln_list]
epss = get_epss_scores(cve_ids)
prioritized = []
for vuln in vuln_list:
cve = vuln['cve_id']
score = {
'cve': cve,
'cvss': vuln['cvss_score'],
'epss': epss.get(cve, {}).get('epss', 0),
'in_kev': cve in kev,
'kev_due_date': kev.get(cve, {}).get('dueDate', None),
'asset_tier': vuln['asset_tier'],
}
# Calculate priority score
priority = 0
if score['in_kev']:
priority += 100 # KEV = always high priority
priority += score['epss'] * 50 # 0-50 points for exploitation probability
priority += (4 - score['asset_tier']) * 20 # 20 points for internet-facing
score['priority_score'] = priority
prioritized.append(score)
return sorted(prioritized, key=lambda x: x['priority_score'], reverse=True)
# Example output format for CTI vulnerability advisory
def format_advisory(prioritized_vulns, top_n=50):
print(f"VULNERABILITY PRIORITY ADVISORY — TOP {top_n}")
print(f"{'CVE':<20} {'CVSS':<6} {'EPSS':<6} {'KEV':<5} {'Asset':<8} {'Priority'}")
print("-" * 60)
for v in prioritized_vulns[:top_n]:
kev_str = "YES" if v['in_kev'] else "no"
print(f"{v['cve']:<20} {v['cvss']:<6.1f} {v['epss']:<6.2f} {kev_str:<5} {'Tier '+str(v['asset_tier']):<8} {v['priority_score']:.0f}")