CVSS measures severity, not urgency. A 9.8 that requires local access and has no public exploit is not a weekend call. A 7.2 with active exploitation in the wild and scriptable delivery is. Treating them the same is how backlogs fill up with critical findings that nobody actually fixes.
CISA built a framework for the urgency question. It is called SSVC. Since early 2024, they have been publishing SSVC assessments on new CVEs through a public GitHub repo called vulnrichment. Machine-readable JSON, free, and most teams have never looked at it.
What SSVC Is
SSVC is Stakeholder-Specific Vulnerability Categorization, developed by CERT/CC and adopted by CISA as their primary triage framework. It is not a replacement for CVSS. It asks a different set of questions.
CVSS asks: how bad could this be if exploited?
SSVC asks: should you be patching this right now?
The CISA Coordinator decision tree uses three inputs.
Exploitation: What is the current state of real-world exploitation?
none: no public exploit, no reported in-the-wild usagepoc: a public proof-of-concept exists but no confirmed exploitation in the wildactive: exploitation confirmed in the wild
Automatable: Can an attacker exploit this at scale without manual effort per target?
yes: the exploit chain is scriptable; a single operator can hit thousands of targetsno: exploitation requires manual targeting, specific local conditions, or dependencies that limit at-scale delivery
Technical Impact: What does a successful exploit give the attacker?
partial: limited access, constrained data exposure, or partial controltotal: full control of the affected component, unrestricted code execution, or full data access
Those three inputs produce one of four recommendations: Track, Track*, Attend, or Act.
Act means patch now. Track means your standard cadence.
A CVSS 9.8 with Exploitation: none, Automatable: no, and Technical Impact: partial comes out as Track. A CVSS 7.2 with Exploitation: active, Automatable: yes, and Technical Impact: total is Act. That is the part your scanner does not surface.
What Vulnrichment Contains
The vulnrichment repo at github.com/cisagov/vulnrichment is CISA’s public record of their ADP (Authorized Data Publisher) work. Every CVE file contains a CISA-authored ADP container sitting alongside the originating CNA’s data. CISA does not overwrite CNA records. It annotates them.
For every CVE that CISA assesses, the ADP container includes the three SSVC decision points above. For those that score as high-risk on any SSVC dimension and where the CNA did not already provide CWE or CVSS data, CISA adds those fields from analyst review.
If the CVE also appears on CISA’s Known Exploited Vulnerabilities catalog, the ADP container gets a KEV block: the date it was added and a reference URL.
As of the ADP program launch in mid-2024, all of this data flows back into the live CVE corpus through the CVE Services API. If you already consume live CVE data from another source, you may already have it. The GitHub repo is the most direct path to explore and filter the enriched dataset without standing up a pipeline first.
How to Query It
Clone the repo once. The structure is organized by year and CVE number range, one JSON file per CVE.
git clone https://github.com/cisagov/vulnrichment
cd vulnrichment
The SSVC data lives inside the ADP container. The relevant section of each CVE JSON looks like this:
{
"containers": {
"cna": { },
"adp": [
{
"title": "CISA ADP Vulnrichment",
"metrics": [
{
"other": {
"type": "ssvc",
"content": {
"id": "CVE-2024-XXXXX",
"role": "CISA Coordinator",
"version": "2.0.3",
"options": [
{ "Exploitation": "active" },
{ "Automatable": "yes" },
{ "Technical Impact": "total" }
]
}
}
}
]
}
]
}
}
To pull every 2024 CVE where exploitation is active and the attack is automatable:
find ./2024 -name "CVE-*.json" | while read f; do
jq -r '
. as $root |
(.containers.adp[]?.metrics[]?.other
| select(.type == "ssvc")
| .content.options) as $opts |
select(
($opts[]? | select(has("Exploitation")) | .Exploitation) == "active" and
($opts[]? | select(has("Automatable")) | .Automatable) == "yes"
) |
$root.cveMetadata.cveId
' "$f" 2>/dev/null
done | sort -u
To narrow further to only CVEs that also appear on the KEV:
find ./2024 -name "CVE-*.json" | while read f; do
jq -r '
. as $root |
(.containers.adp[]?.metrics[]?.other
| select(.type == "ssvc")
| .content.options) as $opts |
(.containers.adp[]?.metrics[]?.other
| select(.type == "kev")) as $kev |
select(
($opts[]? | select(has("Exploitation")) | .Exploitation) == "active" and
($opts[]? | select(has("Automatable")) | .Automatable) == "yes" and
($kev != null)
) |
$root.cveMetadata.cveId
' "$f" 2>/dev/null
done | sort -u
KEV + active exploitation + automatable is as urgent as it gets. If your scanner found any of those CVEs in your environment and they are sitting in a backlog, that list is your first problem to solve.
To pull the SSVC fields alongside each CVE ID for a full triage view:
find ./2024 -name "CVE-*.json" | while read f; do
jq -r '
. as $root |
(.containers.adp[]?.metrics[]?.other
| select(.type == "ssvc")
| .content.options) as $opts |
{
id: $root.cveMetadata.cveId,
exploitation: ($opts[]? | select(has("Exploitation")) | .Exploitation),
automatable: ($opts[]? | select(has("Automatable")) | .Automatable),
impact: ($opts[]? | select(has("Technical Impact")) | ."Technical Impact")
} |
[.id, .exploitation, .automatable, .impact] | @tsv
' "$f" 2>/dev/null
done | sort | column -t
That outputs a tab-separated table of every CISA-assessed CVE in 2024 with its three SSVC fields. You can pipe it through grep, awk, or import it into a spreadsheet for a broader view of the landscape.
The Triage Matrix
Two versions follow. The first uses SSVC alone. The second layers KEV on top. Use the first if you are just getting started. Use the second if you want the tightest possible signal.
SSVC Only
“This sprint” means the next available patch window, not the next monthly cycle. “Track” means no remediation deadline until the exploitation or automatable status changes.
| Exploitation | Automatable | Technical Impact | Patch Cadence |
|---|---|---|---|
| active | yes | total | This sprint |
| active | yes | partial | This sprint |
| active | no | total | This sprint |
| poc | yes | total | Next sprint |
| poc | yes | partial | Next sprint |
| active | no | partial | Next sprint |
| poc | no | total | Next sprint |
| none | yes | total | Next sprint |
| poc | no | partial | Standard cadence |
| none | yes | partial | Standard cadence |
| none | no | total | Standard cadence |
| none | no | partial | Track |
The input that shifts cadence most in practice is Exploitation. When a CVE moves from none to poc to active, the urgency changes materially. CISA updates their assessments as exploitation status evolves, which is why pulling a fresh clone regularly matters more than any other step in this workflow.
SSVC + KEV
KEV acts as a hard floor. When CISA adds a CVE to the KEV catalog, they have confirmed it is being actively exploited in the wild. That signal overrides the SSVC calculation in one specific way: any CVE on the KEV is at minimum a next-sprint item, and a this-sprint item if the attack is also automatable.
| On KEV | Exploitation | Automatable | Technical Impact | Patch Cadence |
|---|---|---|---|---|
| yes | active | yes | any | This sprint |
| yes | active | no | any | This sprint |
| yes | poc | yes | any | This sprint |
| yes | poc | no | any | Next sprint |
| yes | none | any | any | Next sprint |
| no | active | yes | total | This sprint |
| no | active | yes | partial | This sprint |
| no | active | no | total | This sprint |
| no | poc | yes | total | Next sprint |
| no | poc | yes | partial | Next sprint |
| no | active | no | partial | Next sprint |
| no | poc | no | total | Next sprint |
| no | none | yes | total | Next sprint |
| no | poc | no | partial | Standard cadence |
| no | none | yes | partial | Standard cadence |
| no | none | no | total | Standard cadence |
| no | none | no | partial | Track |
In practice, most CVEs on the KEV also carry Exploitation: active in their SSVC record. The KEV column matters most for the edge cases: a CVE where the CNA submitted the record before CISA completed their SSVC assessment, or where the SSVC exploitation field has not yet been updated to reflect confirmed in-the-wild usage. KEV is a second independent confirmation, not a duplicate signal.
Why Auditors Care
PCI DSS Requirement 6.3.1 requires a risk-based patching process that prioritizes based on risk. Using SSVC-derived urgency as the basis for that process is more defensible than CVSS thresholds alone, because it is grounded in real-world exploitation state rather than theoretical attack complexity.
If your current SLA says “CVSS critical patches within 15 days,” you can keep that SLA. Add a second tier: “SSVC Act-tier patches within 7 days.” The second tier catches the high-urgency lower-CVSS cases your current SLA misses, and it gives your auditor a clear answer to how you determine what gets treated as critical.
SOC 2 CC7.1 asks whether you have a process to detect and respond to vulnerabilities in a timely manner. Your answer improves when “timely” is defined by exploitation state, not a number on a scoring rubric.
| SSVC Outcome | Patch Cadence | NIST CSF 2.0 | CIS v8 IG1 |
|---|---|---|---|
| Act (active + automatable) | This sprint | ID.RA-5, RS.MI-3 | 7.4 |
| Attend (poc or high impact) | Next sprint | ID.RA-5 | 7.4 |
| Track* (watch, low urgency) | Standard cadence | ID.RA-5 | 7.3 |
| Track | Backlog, no deadline | GV.RM-05 | 7.1 |
Getting Started Without a Pipeline
The fastest path to value does not require automation. Clone the repo. Run the jq filter above against the 2024 directory. Compare the output against your open scanner findings. Do that once. You will know immediately whether you have Act-tier items sitting in your backlog labeled as low risk.
Once you have run it manually twice, a cron job that pulls the latest commits weekly and posts new matches to your security channel is about two hours of setup. From that point, CISA’s analysts are running triage on your behalf on every new CVE they assess.
One practical note: the jq queries above will silently skip CVE files where the ADP container is absent or where CISA has not yet assessed the CVE. That is expected behavior, not an error. Not every CVE in the repo has a full SSVC entry. Coverage is highest for CVEs from 2024 onward and for software categories CISA considers higher-risk.
The downstream consumer path (CVE Services API rather than the GitHub repo) gives you the same data without cloning. If you already pull live CVE data from another provider, check whether your provider passes through ADP container data. If they do, the SSVC fields are already in your pipeline.
CVSS is not going away. The ecosystem depends on it and it is embedded in too many compliance frameworks to remove. But SSVC-based urgency on top of CVSS severity is a better decision model than either one alone. CISA built the enrichment layer. It is free, public, and updated continuously. Using it costs nothing except the time to run a jq query.
Need a hand with this at your company?
543HQ helps startups and growing companies build security programs that actually work. Start with a free 30-minute call.
Book a Free Call