Tool: lookup_kev
Check whether a CVE is being exploited in the wild, against the VulnCheck KEV catalog. VulnCheck KEV is a superset of CISA's KEV, so a CVE CISA has not listed can still come back as known exploited, and the entry says which source traced it.
Ask your agent:
Are any of these CVEs known to be exploited?
Scoring does not need this. score_risk composes the KEV catalog itself and returns what it found in each verdict's evidence. Call this tool when you want the record directly: explaining a verdict to someone, filtering a backlog before you start analysis, or answering a question about one CVE without scoring anything.
KEV membership is the strongest threat evidence k9 uses. In the rubric it sets the threat factor to present, and it drives two policy floors: kev_emergency keeps a KEV-listed vulnerability out of DEFER, and ransomware_floor forces FIX_TODAY when the catalog records ransomware-campaign use.
Request
lookup_kev(cves)
cves: a list of CVE ids, max 100 per call. Case- and whitespace-insensitive.
Duplicates collapse before the limit is counted, and because these ids are normalized to upper case, cve-2021-44228 and CVE-2021-44228 are one id rather than two.
{ "cves": ["CVE-2021-44228", "cve-2017-0144", "CVE-2019-11043"] }
Response
A dictionary keyed by CVE, upper-cased. Every CVE you send comes back, because absence from the catalog is itself the answer: a miss carries known_exploited: false rather than being dropped.
| Field | Type | Description |
|---|---|---|
cve |
string | The CVE, upper-cased. |
known_exploited |
bool | Whether the CVE is in the catalog. This is the load-bearing field. |
vendor |
string | Vendor, from the catalog record. Hits only. |
product |
string | Product, from the catalog record. Hits only. |
vulnerability_name |
string | The catalog's name for the vulnerability. Hits only. |
known_ransomware_use |
bool | Whether the catalog records use in a ransomware campaign. Hits only. |
date_added_vulncheck |
string | When VulnCheck added the record. Hits only. |
date_added_cisa |
string | When CISA added it. Present only for records CISA also traced, so its absence on a hit means VulnCheck listed the CVE and CISA has not. |
due |
string | The CISA-mandated remediation date for federal agencies. CISA-traced records only. Useful as a published reference point even if the mandate does not apply to you. |
data_age_seconds |
int | Seconds since the catalog was last loaded. See below. |
Fields absent from a record are omitted rather than returned as null, so test for absence.
{
"CVE-2021-44228": {
"cve": "CVE-2021-44228",
"known_exploited": true,
"vendor": "Apache",
"product": "Log4j2",
"vulnerability_name": "Apache Log4j2 Remote Code Execution Vulnerability",
"known_ransomware_use": true,
"date_added_vulncheck": "2021-12-10",
"date_added_cisa": "2021-12-10",
"due": "2021-12-24",
"data_age_seconds": 412
},
"CVE-2019-11043": {
"cve": "CVE-2019-11043",
"known_exploited": false,
"data_age_seconds": 412
}
}
Freshness
The catalog refreshes from k9's store every 15 minutes, and every entry carries data_age_seconds so you can tell how current the answer is.
- Under
900: fresh. - Over
3600: the background refresh has probably been failing. Callhealth_checkbefore you rely on aknown_exploited: false.
A stale catalog is dangerous in one direction only. A hit is still a hit; a miss on a stale catalog might be a CVE added since the last successful load.
Errors
Sending more than 100 CVEs raises an error naming the count. Split the batch and call again.
Related
- Score alerts, which reads KEV for you: score_risk, and its policy floors.
- Exploitation probability for CVEs that are not KEV-listed: lookup_epss.
- Get the CVE behind a GHSA or other advisory id first: resolve_vuln_ids.
- Set up the server: Configure the k9 MCP server.