A vulnerability scanner can hand you ten thousand findings before lunch. Almost none of them matter this week. The CISA Known Exploited Vulnerabilities (KEV) catalog exists to cut that noise down to the handful of bugs attackers are actually using right now, and as of early September 2026 it is doing that job for a widening set of products: Zimbra Collaboration Suite, JetBrains TeamCity, VMware vCenter Server, IBM’s Langflow, and more. On August 21, 2026, CISA added CVE-2026-73570, an unauthenticated command injection flaw in Zimbra’s zimbra-snmp package, with a due date of September 4, 2026 — today, if you’re reading this the week it published. This tutorial walks through building a repeatable workflow that pulls the KEV catalog into your environment, maps entries to what you actually run, and gets patches verified before the clock runs out.
This is not a theoretical exercise. Security teams that treat KEV entries as background noise are the ones showing up in breach disclosures six months later. The goal here is a workflow you can stand up in one afternoon and keep running indefinitely, built from a small set of scripts, a ticketing template, and a handful of scheduled checks. By the end you’ll have a working KEV watcher, a patch-verification routine, and a rollback plan for when a fix breaks something else.
Don't miss new tech stories on Google
Add Tech Insider once in the Google app and our stories appear in your news suggestions.
What the CISA KEV Catalog Actually Is (and Why CVSS Alone Isn’t Enough)
The Common Vulnerability Scoring System (CVSS) measures theoretical severity: how bad a bug could be if exploited. The KEV catalog measures something different and arguably more useful for triage: whether a bug is being exploited right now, in the wild, against real organizations. CISA only adds a CVE to the list once it has evidence of active exploitation, and federal civilian agencies are bound by Binding Operational Directive 26-04 to remediate KEV entries by the assigned due date. Private companies aren’t legally bound by that directive, but plenty of cyber insurance policies, SOC 2 auditors, and enterprise customers now ask directly whether your patch cadence tracks the KEV list.
A weekly report tracking the CVE Program’s published records counted 1,877 new CVEs registered the week of August 10, 2026 alone, with six confirmed as actively exploited. That ratio, roughly three-tenths of a percent of new vulnerabilities crossing into active-exploitation status, is exactly why a KEV-driven workflow beats a CVSS-only one. Chasing every 9.8-rated bug burns your team out on things nobody is attacking, while a genuinely dangerous 7.5-rated bug with active exploitation sits unpatched. The Zimbra CVE-2026-73570 case is a good illustration: it scored 8.9, not the maximum 9.8, and would have ranked behind a dozen “more critical” bugs on a CVSS-only spreadsheet. It made the KEV list anyway because it was being actively used.
KEV vs. CVSS vs. EPSS: Three Different Questions
Teams that are new to KEV-driven triage often conflate it with CVSS or EPSS (Exploit Prediction Scoring System). They answer different questions, and a mature patch workflow uses all three together rather than picking one.
| Signal | Question it answers | Data source | Best use in triage |
|---|---|---|---|
| CVSS | How bad could this be if exploited? | NVD, vendor advisories | Baseline severity ranking |
| EPSS | How likely is this to be exploited in the next 30 days? | FIRST.org EPSS model | Prioritizing among unexploited CVEs |
| CISA KEV | Is this being exploited right now, confirmed? | CISA KEV catalog | Forcing function for immediate action |
| Vendor advisory | Is a fix available, and for which versions? | Vendor security bulletins | Determines whether you can even patch yet |
In practice, a bug that clears all three bars — high CVSS, high EPSS, and a KEV listing — goes to the front of every queue, interrupts sprint planning, and gets a same-day patch window. A bug with high CVSS but no KEV listing and low EPSS gets scheduled into the normal patch cycle. That distinction alone will cut wasted emergency-patching effort dramatically, freeing your team to actually chase what matters, similar to the prioritization logic covered in our broader vulnerability management program guide.
Prerequisites: Tools, Access, and Versions You’ll Need
Before starting, get these in place. None of this requires an enterprise vulnerability management platform — the workflow below runs on open tools and a scheduler.
- A Linux, macOS, or WSL2 shell with
bash5.x,curl8.x, andjq1.7 or later installed - Python 3.11 or newer, with the
requestsandpandaspackages (pip install requests pandas) - Read access to your asset inventory — a CSV export from your CMDB, cloud provider tags, or an agent-based tool works fine to start
- Admin or maintainer access to your ticketing system (Jira, Linear, or GitHub Issues) to create a patch-ticket template
- A scheduler:
cron, a systemd timer, or a serverless cron trigger (AWS EventBridge Scheduler, GitHub Actions on a schedule) - Slack, Microsoft Teams, or email webhook credentials for alerting
- Change-management approval workflow for production patches, even an informal one
- Roughly 90 minutes for the initial setup, plus recurring maintenance of about 20 minutes a week
You do not need a paid CVE feed. The KEV catalog itself is published as free, structured JSON by CISA and updates as new entries are confirmed, typically several times a week.
Step 1: Pull the KEV Catalog Feed Into Your Environment
Start by fetching the raw KEV catalog and storing it locally so you can diff it against your asset list without hammering CISA’s endpoint on every run. The catalog is published as JSON with fields for CVE ID, vendor, product, vulnerability name, date added, short description, required action, and due date.
#!/usr/bin/env bash
# fetch-kev.sh — pull the latest CISA KEV catalog and store it with a timestamp
set -euo pipefail
KEV_URL="https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json"
OUT_DIR="./kev-data"
STAMP=$(date -u +%Y%m%dT%H%M%SZ)
mkdir -p "$OUT_DIR"
curl -sSL -A "kev-watcher/1.0 ([email protected])" \
-o "$OUT_DIR/kev-$STAMP.json" "$KEV_URL"
# keep a stable "latest" symlink for downstream scripts
ln -sf "kev-$STAMP.json" "$OUT_DIR/kev-latest.json"
COUNT=$(jq '.vulnerabilities | length' "$OUT_DIR/kev-latest.json")
echo "Fetched $COUNT KEV entries at $STAMP"
Run it once manually to confirm it works before wiring it into a scheduler:
$ chmod +x fetch-kev.sh
$ ./fetch-kev.sh
Fetched 1428 KEV entries at 20260904T140212Z
If the count comes back as zero or the script errors out, jump ahead to the troubleshooting section — a stale user agent or a corporate proxy stripping query parameters are the two most common culprits.
Step 2: Map KEV Entries to Your Asset Inventory
A raw KEV feed with 1,400-plus entries is useless without knowing which ones touch your environment. This step cross-references the catalog’s vendor and product fields against your own asset list. Export your inventory as a CSV with at minimum three columns: hostname, vendor, and product_version.
import json
import pandas as pd
with open("kev-data/kev-latest.json") as f:
kev = json.load(f)["vulnerabilities"]
kev_df = pd.DataFrame(kev)[[
"cveID", "vendorProject", "product", "vulnerabilityName",
"dateAdded", "dueDate", "shortDescription", "requiredAction"
]]
assets = pd.read_csv("asset-inventory.csv")
# simple substring match, since exact strings rarely align between
# your CMDB labels and CISA's vendor/product naming
rows = []
for _, asset in assets.iterrows():
for _, entry in kev_df.iterrows():
if entry["vendorProject"].lower() in str(asset["vendor"]).lower():
rows.append({**asset.to_dict(), **entry.to_dict()})
exposure = pd.DataFrame(rows)
exposure.to_csv("kev-exposure.csv", index=False)
print(f"{len(exposure)} asset/KEV matches found across {exposure['hostname'].nunique()} hosts")
Sample output on a mid-size fleet:
$ python3 map-kev-assets.py
14 asset/KEV matches found across 6 hosts
Six hosts out of a fleet of hundreds is a manageable list for this week’s patch cycle — that’s the entire point of the exercise. Vendor and product string matching is intentionally loose here because CISA’s naming doesn’t always match how your CMDB labels software; expect to spend the first couple of runs tightening the match logic by hand.
Step 3: Score Urgency With CVSS, EPSS, and KEV Due Dates Together
Once you know which hosts are exposed, rank them. CISA’s own due dates are usually set at 14 days for standard entries, but recent high-severity items have shipped with far tighter windows — the Zimbra CVE-2026-73570 entry carried just a 14-day window from its August 21 addition to the September 4 due date, and some critical remote-code-execution bugs get a 24-hour “immediate” action flag, as happened with JetBrains TeamCity’s CVE-2026-63077 in the August 10, 2026 weekly report.
| CVE | Product | CVSS | Exploitation type | Action window |
|---|---|---|---|---|
| CVE-2026-63077 | JetBrains TeamCity | 9.8 Critical | Unauthenticated RCE | Immediate / 24 hours |
| CVE-2026-73570 | Zimbra Collaboration Suite (zimbra-snmp) | 8.9 High | Unauthenticated command injection / RCE | 14 days |
| CVE-2026-59310 | VMware vCenter Server | 9.8 Critical | Directory traversal, syslog server RCE | 14 days |
| CVE-2026-9198 | IBM Langflow OSS | 9.8 Critical | Auth bypass chained to RCE | 14 days |
| CVE-2026-8037 | Progress LoadMaster (ADC) | 9.6 Critical | OS command injection RCE | 14 days |
| CVE-2026-15972 | HashiCorp Consul | 7.5 High | Fixed in Consul 2.0.3 / Enterprise 1.21.17, 1.22.11 | 14 days |
Build a simple weighted score so the ranking isn’t purely manual. A workable formula: multiply CVSS by a KEV multiplier (2x if listed, 1x if not), then subtract days remaining until the due date. Sort descending. Hosts running internet-facing services jump another tier automatically — an exposed vCenter management interface is a very different risk than one sitting behind a jump box with no public route.
Step 4: Build a Patch Ticket Template With SLA Fields
Every KEV match should spawn a ticket automatically, not get typed up by hand under deadline pressure. The template needs the CVE ID, the KEV due date, the affected host list, the required action text straight from CISA’s field, and a rollback plan field that must be filled in before the ticket can move to “in progress.” That last field sounds bureaucratic until the first patch breaks a production login flow and someone has to improvise a rollback at 2 a.m.
{
"title": "[KEV] CVE-2026-73570 - Zimbra ZCS command injection - due 2026-09-04",
"labels": ["kev", "security-patch", "sla-14d"],
"fields": {
"cve_id": "CVE-2026-73570",
"cvss": 8.9,
"kev_due_date": "2026-09-04",
"affected_hosts": ["mail01.internal", "mail02.internal"],
"required_action": "Update Zimbra ZCS to 10.1.20+ or disable the zimbra-snmp module",
"rollback_plan": "",
"verification_method": "",
"owner": "",
"status": "triage"
}
}
Wire this into your ticketing system’s API so Step 2’s exposure CSV creates one ticket per affected host group automatically. Most teams start with a Jira Automation rule or a small script hitting the REST API on a schedule; either works as long as duplicate tickets don’t get created on every run — dedupe on the CVE ID plus hostname combination.
Step 5: Automate KEV Alerts With a Scheduled Script
Manual checking doesn’t scale and gets skipped the week everyone is busy. Schedule the fetch-and-match pipeline to run daily and post new matches to a Slack or Teams channel. A cron entry is the simplest version.
# crontab -e
# Run KEV check every day at 07:00 UTC
0 7 * * * /opt/kev-watcher/fetch-kev.sh && /opt/kev-watcher/venv/bin/python /opt/kev-watcher/map-kev-assets.py && /opt/kev-watcher/venv/bin/python /opt/kev-watcher/notify-slack.py >> /var/log/kev-watcher.log 2>&1
If you’re already running GitHub Actions for CI, a scheduled workflow avoids standing up a separate cron host entirely:
name: kev-watch
on:
schedule:
- cron: "0 7 * * *"
workflow_dispatch: {}
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- run: pip install -r requirements.txt
- run: bash fetch-kev.sh
- run: python map-kev-assets.py
- run: python notify-slack.py
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Either path gets you the same outcome: new KEV entries touching your fleet show up in a channel your team actually watches, within 24 hours of CISA publishing them, instead of surfacing three weeks later during a routine scan review.
Step 6: Patch the Worked Example — Zimbra, TeamCity, and vCenter
With tickets generated and prioritized, the actual patching follows a consistent pattern regardless of product. Take the three highest-profile late-August 2026 KEV entries as a worked example.
Zimbra Collaboration Suite (CVE-2026-73570)
CISA’s required action for this entry is direct: update to ZCS 10.1.20 or later, or disable the zimbra-snmp module if an immediate upgrade isn’t possible. Check your current version first, since the flaw only affects builds prior to 10.1.20.
$ zmcontrol -v
Release 10.1.18.GA.4521.UBUNTU22_64 UBUNTU22_64 FOSS edition
# version is below the fixed 10.1.20 build — proceed with the update
$ su - zimbra
$ zmcontrol stop
$ ./install.sh --platform-override
$ zmcontrol start
$ zmcontrol -v
Release 10.1.20.GA.4589.UBUNTU22_64 UBUNTU22_64 FOSS edition
If the upgrade can’t happen inside the 14-day window, the compensating control is disabling zimbra-snmp entirely on internet-facing nodes, which removes the vulnerable code path without a full version bump.
JetBrains TeamCity (CVE-2026-63077)
This one carries an immediate, 24-hour action window because it’s an unauthenticated remote code execution flaw. CISA’s guidance is to patch TeamCity On-Premises to 2026.1.3 or 2025.11.7, or apply the vendor’s security patch plugin if a full upgrade isn’t feasible on short notice. Check the JetBrains TeamCity download page for the current build before starting.
The patch plugin route buys time on a production build server that can’t take an unscheduled restart mid-pipeline, but treat it as a stopgap — schedule the full version upgrade within the same week regardless.
VMware vCenter Server (CVE-2026-59310)
A directory traversal bug in vCenter’s syslog server that chains to remote code execution, scored 9.8. Check the VMware security advisories page for the exact build number that resolves this CVE for your vCenter version line, since Broadcom (VMware’s parent since the 2023 acquisition) ships fixes per major version branch rather than a single universal build.
vCenter upgrades are disruptive enough that most teams schedule a maintenance window rather than patch live. If the management interface is reachable from outside your network — which it should never be — restrict access at the firewall immediately, then patch on the next available window.
Step 7: Verify the Patch Actually Closed the Vulnerability
A version number bump doesn’t guarantee the vulnerable code path is gone — installers fail silently, packages get cached, and containers sometimes rebuild from a stale base image. Verification is its own step, not an assumption.
#!/usr/bin/env bash
# verify-patch.sh — confirm a service reports a fixed version after patching
set -euo pipefail
HOST="$1"
EXPECT_MIN_VERSION="$2"
BANNER=$(curl -sSk "https://$HOST/api/version" | jq -r '.version')
python3 - "$BANNER" "$EXPECT_MIN_VERSION" <<'PY'
import sys
from packaging import version
banner, expected = sys.argv[1], sys.argv[2]
ok = version.parse(banner) >= version.parse(expected)
print(f"host reports {banner}, expected >= {expected}: {'PASS' if ok else 'FAIL'}")
sys.exit(0 if ok else 1)
PY
For services without a public version endpoint, re-run your original vulnerability scanner against just the patched hosts — a targeted rescan rather than a full sweep gets you a fast pass/fail signal. If your team already has a scanning routine in place, this step slots directly into the process described in our vulnerability scan walkthrough. Close the ticket only after the rescan comes back clean, not when the deploy pipeline reports success — those are two different claims.
Step 8: Roll Back Safely If a Patch Breaks Production
Emergency patches under a 24-hour KEV window skip the normal staging soak time, which raises the odds something breaks. Have a rollback path ready before you patch, not after.
- Snapshot or image the host immediately before applying the patch — a VM snapshot or an EBS volume snapshot takes under two minutes and costs nothing meaningful compared to an extended outage
- Keep the previous package or installer binary on disk until verification passes, not just in a remote repository
- For containerized services, tag the previous image explicitly (
service:pre-cve-2026-73570) rather than relying on registry history - Write the rollback command into the ticket before starting the patch, not after something goes wrong
- Set a hard time-box: if the patch and verification aren’t done within two hours, roll back and reassess rather than troubleshooting indefinitely on a production system
Step 9: Document Compensating Controls When You Can’t Patch in Time
Sometimes the due date arrives and the patch isn’t ready — a legacy integration breaks on the new version, or change management can’t approve a window that fast. CISA’s own guidance for federal agencies allows documented risk acceptance with compensating controls in these cases, and the same discipline works for any organization tracking KEV compliance for a customer or auditor.
A compensating control record should state the CVE, why the patch is delayed, the specific mitigating action taken (network isolation, WAF rule, disabling the vulnerable module, restricting to VPN-only access), who approved the exception, and — critically — a re-review date no more than 30 days out. An exception with no expiry date has a habit of becoming permanent.
Step 10: Report KEV Compliance to Leadership and Auditors
Once the workflow is running, the exposure CSV and ticket data become the raw material for a compliance report almost for free. A simple weekly rollup — number of KEV entries matched, number patched within SLA, number under a documented exception, mean time to patch — gives leadership a number to track and gives auditors evidence without a scramble before every review cycle.
| Metric | Week of Aug 24 | Week of Aug 31 | Target |
|---|---|---|---|
| New KEV matches | 3 | 2 | n/a |
| Patched within SLA | 3 | 1 | 100% |
| Under documented exception | 0 | 1 | Under 10% of matches |
| Mean time to patch (hours) | 19 | 31 | Under 24 for critical |
A slipping mean-time-to-patch number is usually an early signal that the on-call rotation is overloaded or that change-management approval is the actual bottleneck, not the patching itself — worth surfacing before it shows up as a missed SLA on a customer’s security questionnaire.
Step 11: Wire KEV Checks Into CI/CD and Change Management
The most durable version of this workflow doesn’t live as a side project — it’s a gate in your existing pipelines. Add a KEV check to your CI build so a dependency matching an active KEV entry fails the build rather than shipping.
#!/usr/bin/env bash
# ci-kev-gate.sh — fail CI if a build dependency matches an active KEV entry
set -euo pipefail
DEPS_FILE="sbom.json" # generated by your SBOM tool (syft, cyclonedx, etc.)
KEV_FILE="kev-data/kev-latest.json"
MATCHES=$(jq -r --slurpfile kev "$KEV_FILE" '
.components[] as $c |
$kev[0].vulnerabilities[] |
select(($c.name | ascii_downcase) == (.product | ascii_downcase)) |
"\(.cveID) matches \($c.name)@\($c.version)"
' "$DEPS_FILE")
if [ -n "$MATCHES" ]; then
echo "BLOCKED: build depends on components with active CISA KEV entries:"
echo "$MATCHES"
exit 1
fi
echo "No KEV matches in current SBOM — build allowed to proceed"
This is intentionally strict at first, and it will produce false positives until the name-matching logic is tuned to your SBOM format. Run it in warn-only mode for the first couple of weeks before flipping it to a hard fail. Teams already running container scanning as part of their build process can extend that same gate rather than standing up a second, parallel one.
Step 12: Run a Quarterly Tabletop Review of the Workflow
Automation drifts. API endpoints change, CMDB exports get reformatted, and Slack webhooks expire without anyone noticing until the day it matters. Schedule a quarterly 30-minute review: run the fetch script manually and confirm it still returns results, pick one recent KEV entry and walk through the full ticket-to-verification chain by hand, and confirm the notification channel is still receiving alerts. This single habit catches most silent failures long before an actual incident forces the discovery.
Common Pitfalls When Chasing the KEV Deadline
These are the mistakes that show up repeatedly once a team starts running a KEV-driven process at speed.
- Treating the KEV due date as the start of the patch process instead of the deadline. Teams that wait until day 13 of a 14-day window to begin testing routinely miss it. Start triage the day the entry appears.
- Patching without checking whether the fix applies to your actual deployment. Some KEV entries only affect specific modules or configurations — the Zimbra CVE-2026-73570 case only matters if zimbra-snmp is installed at all, and a blanket full reinstall wastes hours a targeted module disable would have avoided.
- Skipping verification because the deploy pipeline reported success. A successful deployment and a closed vulnerability are not the same claim, especially with cached container layers or CDN-fronted services still serving old responses.
- No rollback plan written down before the emergency patch starts. Improvising a rollback under time pressure, on a production system, at 2 a.m. is how a patch becomes an outage.
- Letting compensating-control exceptions run without an expiry date. An exception with no re-review date is a permanent unpatched vulnerability with a paper trail attached.
- Matching KEV vendor/product strings too loosely and drowning the team in false positives. A substring match on “Apache” will flag Apache Tomcat, Apache Kafka, and Apache HTTP Server as the same hit unless the matching logic accounts for the distinct product field.
- Forgetting that KEV due dates apply per-entry, not per-patch-cycle. Batching KEV patches into the next scheduled maintenance window defeats the entire point of the accelerated timeline.
Troubleshooting Your CISA KEV Patch Workflow
Issues that come up when running this pipeline in production, and how to resolve them.
- The fetch script returns a 403 or empty response. CISA’s endpoint sometimes rate-limits or blocks requests without a descriptive user agent string. Set an explicit
-Aflag identifying your organization and retry; corporate proxies that strip headers are the second most common cause. - jq reports “Cannot index string with string” when parsing the catalog. This usually means the download failed silently and saved an HTML error page instead of JSON. Check the file’s first line with
head -c 200 kev-latest.jsonbefore assuming the parser is broken. - The asset-matching script returns zero hits even though you know you run an affected product. Vendor and product naming rarely aligns between your CMDB and CISA’s catalog labels — check the exact strings CISA uses for that entry and adjust your normalization logic accordingly.
- Duplicate tickets get created on every scheduled run. Add a dedupe check against existing open tickets by CVE ID plus hostname before creating a new one, and close the loop by updating the existing ticket’s due-date field instead.
- The Slack notification never arrives. Webhook URLs expire or get revoked when a workspace admin rotates app credentials. Test the webhook independently with a plain curl POST before assuming the pipeline logic is at fault.
- Patch verification passes but the vulnerability scanner still flags the host. Scanner signature databases can lag a few days behind a fresh patch release — rerun the scan 48 hours later before escalating, and cross-check the version banner manually in the meantime.
- A patched service won’t restart cleanly. Check for a configuration schema change between versions; JetBrains and VMware both occasionally introduce config file migrations alongside security patches that fail silently if a custom setting isn’t recognized.
- CI/CD KEV gate blocks a build on a false positive. Confirm the SBOM’s product name and version actually match the KEV entry’s affected version range, not just the product name — some entries only affect versions below a specific fix, and a build already on a patched version shouldn’t trip the gate.
- The quarterly tabletop review reveals the cron job silently stopped running weeks ago. Add a dead-man’s-switch check: a separate, independent monitor that alerts if no successful fetch has logged in over 48 hours.
Advanced Tips: Scaling KEV Response Across Hundreds of Assets
Once the core workflow is stable, a few refinements matter more as your fleet grows.
Layer EPSS scores into your ranking alongside KEV status, since not every KEV entry carries equal urgency and EPSS gives you a probability estimate for CVEs that haven’t made the KEV list yet but might soon — catching them a step earlier than waiting for confirmed exploitation. Cross-reference the exploitation technique named in each KEV entry’s description against the MITRE ATT&CK framework to see which technique IDs recur most often across your fleet’s matches — that pattern often points to a systemic gap (unauthenticated management interfaces, for instance) worth fixing architecturally rather than patch by patch. Segment your asset inventory by network exposure before scoring; a KEV match on an internet-facing load balancer and the same CVE on an air-gapped internal test box are not the same priority even though the CVE ID is identical. Consider integrating with a dedicated vulnerability scanning platform once your fleet crosses a few hundred hosts, since manual CSV matching becomes a maintenance burden past that scale — most enterprise scanners now ingest the KEV catalog natively and can automate Steps 1 through 3 directly. Finally, track a “KEV debt” metric over time: total number of open KEV matches multiplied by days past due date, summed across the fleet. A rising trend line is an early warning that patch capacity is falling behind exposure growth well before any single miss becomes a headline.
Complete Working Project: A KEV Watcher End to End
Putting every piece from this tutorial together, here is the full project layout you can clone and adapt.
kev-watcher/
├── fetch-kev.sh # Step 1: pull the catalog
├── map-kev-assets.py # Step 2: cross-reference asset inventory
├── score-urgency.py # Step 3: weighted CVSS + KEV + due-date scoring
├── create-tickets.py # Step 4: open/dedupe tickets via API
├── notify-slack.py # Step 5: post new matches to a channel
├── verify-patch.sh # Step 7: confirm a patched version banner
├── ci-kev-gate.sh # Step 11: block CI builds with KEV matches
├── asset-inventory.csv # your exported CMDB/asset list
├── kev-data/ # fetched catalog snapshots, gitignored
├── requirements.txt # requests, pandas, packaging
└── .github/workflows/kev-watch.yml # the scheduled runner
A minimal requirements.txt to make the Python scripts runnable end to end:
requests>=2.32
pandas>=2.2
packaging>=24.0
Wire the pieces together in this order: fetch-kev.sh runs first and populates kev-data/kev-latest.json, map-kev-assets.py reads that plus asset-inventory.csv to produce kev-exposure.csv, score-urgency.py ranks that file, create-tickets.py opens or updates tickets from the ranked list, and notify-slack.py posts a summary. verify-patch.sh and ci-kev-gate.sh run independently — the first after a patch ships, the second on every CI build. Total setup time for a team that already has a CMDB export and a ticketing API token is close to the 90-minute estimate at the top of this guide; teams building the asset inventory from scratch for the first time should budget closer to half a day.
How This Compares to a Generic Vulnerability Scan Workflow
It’s worth being explicit about where this workflow sits relative to routine scanning. A vulnerability scan finds everything present on a host, patched or not, exploited or not — thorough but undifferentiated. The KEV-driven process described here is a prioritization layer on top of that broader picture, not a replacement for it. Run both: scans for full-coverage visibility on a weekly or monthly cadence, and the KEV watcher for a daily forcing function on the handful of bugs attackers are actually using today. Teams that skip scanning entirely and rely only on KEV entries miss the slower-burn vulnerabilities that never make the actively-exploited list but still get chained together in a multi-step attack — the kind of gap that shows up in a post-incident review with an uncomfortable “we knew about this” footnote. If you haven’t already documented your SLA structure by severity tier, the framework in our vulnerability management program breakdown pairs directly with the workflow above.
Recent KEV activity also underscores why software-supply-chain visibility matters as much as patch speed. When GitLab shipped a fix for a CVSS 9.4 flaw under active exploitation within 48 hours, and when a self-hosted N-able bug tied to StormEncryptor ransomware activity left roughly half of exposed instances unpatched weeks later, the difference between those two outcomes wasn’t the severity score — it was whether each organization had a workflow already running that caught the advisory the day it published.
Where KEV Compliance Fits Into Broader Audits
Most teams don’t build a KEV workflow purely out of good security hygiene — it usually gets prioritized because an auditor, a customer’s vendor security questionnaire, or a cyber insurance renewal asked a pointed question about patch timelines. It’s worth understanding how the pieces connect so the workflow above doesn’t end up duplicated across three separate compliance efforts.
SOC 2’s common criteria around vulnerability and patch management (typically mapped under CC7.1 and CC7.2) don’t name the KEV catalog explicitly, but auditors increasingly expect evidence that critical, actively-exploited vulnerabilities get remediated on a defined SLA rather than an ad hoc basis — the ticket data and weekly rollup from Step 10 doubles as that evidence with almost no extra work. ISO 27001’s Annex A control on technical vulnerability management (A.8.8 in the 2022 revision) asks for a documented process with defined timeframes, which the SLA fields baked into the ticket template in Step 4 satisfy directly. PCI DSS 4.0 goes further and sets an explicit six-month patch requirement for critical vulnerabilities discovered through its own scanning requirement, with a much tighter expectation for anything under active exploitation — precisely the category the KEV catalog exists to flag.
The practical takeaway: don’t build a KEV tracker as a one-off security team tool. Point compliance, GRC, and audit stakeholders at the same ticket data and weekly metrics from day one. It saves the awkward scramble of reconstructing a patch history from memory the week before an audit, and it turns a purely defensive exercise into something that also shortens the next SOC 2 or ISO 27001 renewal cycle.
Frequently Asked Questions
What is the CISA KEV catalog, in plain terms?
It’s a public, continuously updated list published by the Cybersecurity and Infrastructure Security Agency of vulnerabilities that have confirmed evidence of active exploitation in the wild, along with a required action and a due date for remediation.
Is following the KEV catalog legally required for private companies?
The binding directive applies to federal civilian executive branch agencies. Private organizations aren’t legally bound, but many cyber insurance underwriters, SOC 2 auditors, and enterprise customers now reference KEV compliance as an expected baseline during due diligence.
How often does the KEV catalog get updated?
New entries are added as CISA confirms active exploitation, which in practice means several times a week rather than on a fixed schedule. A daily automated check, as built in Step 5, is enough to stay current without manual polling.
What’s the difference between a 14-day and a 24-hour KEV due date?
CISA assigns the accelerated 24-hour “immediate action” window to a small subset of entries it judges to carry the most severe, actively-exploited risk, typically unauthenticated remote code execution flaws in widely deployed software. Most entries carry the standard 14-day window.
Can I patch a KEV vulnerability without an official fix being available yet?
Not always — some entries get added before a permanent fix ships. In that gap, apply the compensating controls CISA lists in the required-action field (disabling a module, restricting network access) and document the exception with a re-review date as described in Step 9.
Does EPSS replace the need to track the KEV catalog?
No. EPSS estimates the probability a CVE will be exploited in the near future; KEV confirms exploitation has already happened. They’re complementary signals — EPSS helps you get ahead of a bug before it’s confirmed, KEV tells you a bug is confirmed and time-critical right now.
What happens if I miss a KEV due date?
For federal agencies, missed due dates trigger escalation under the binding directive. For private organizations, there’s no automatic penalty, but a documented, expired, un-reviewed exception is exactly the kind of gap that shows up as a finding in a SOC 2 audit or a post-breach forensic report. Document the delay and set a firm re-review date rather than letting it go unaddressed.
Do I need an enterprise vulnerability management platform to run this workflow?
No — everything in this tutorial runs on open tools: curl, jq, Python, and a scheduler you likely already have. An enterprise platform becomes worth the cost once your fleet grows large enough that manual CSV matching and ticket creation become a bottleneck, typically somewhere past a few hundred assets.


