| name | cve-triage-rubric |
| description | Standard operating procedure for triaging the impact of a CVE for a security operations team. Use when assessing a CVE's severity, exploitability, and asset impact, and deciding whether to patch, mitigate, monitor, or take no action. Combines CVSS, EPSS, and CISA KEV signals with asset-impact analysis, keeps all math deterministic, requires human review before any action, and pulls external context via a web_search tool rather than raw downloads. |
CVE Impact Triage Rubric
A repeatable procedure for turning a raw CVE identifier into a defensible action decision. Optimized for consistency and auditability across a security operations team: the same inputs must always yield the same recommendation.
Operating Principles (read first)
- Deterministic math only. All scoring, thresholds, and tier assignments are computed by fixed rules, never estimated by the model. If a number is missing, mark it
UNKNOWN — do not guess or interpolate.
- Mandatory human review. This procedure produces a recommendation, never an executed change. A human analyst must approve before any patch, mitigation, or ticket-closing action.
- Egress via
web_search, not raw download. Fetch advisories, vendor bulletins, and exploit-status context through the web_search tool (returns text). Never download binaries, PoC archives, or executables into the environment.
- Cite every claim. Each field in the output must trace to a tool result (NVD/EPSS/KEV lookup or
web_search) or be UNKNOWN. No confabulation.
- Assume prod when uncertain. If asset criticality cannot be confirmed, treat the asset as production/critical.
Inputs
cve_id (required): e.g. CVE-2021-44228 (Log4Shell).
affected_assets (optional): list of asset identifiers or a query against the asset inventory.
environment (optional): defaults to treating unclassified assets as production.
Step 1 — Gather deterministic signals
Use the available tools (exposed as MCP tools on the gateway). Do not compute these yourself.
| Signal | Source tool | Field |
|---|
| CVSS base score + vector | nvd_lookup | cvss_v3.baseScore, cvss_v3.vectorString |
| Attack vector / privileges / UI | nvd_lookup | parsed from CVSS vector |
| EPSS probability (0.0–1.0) | epss_kev | epss.score |
| Known Exploited (CISA KEV) | epss_kev | kev.listed (bool) + kev.dateAdded |
| Vendor patch availability | web_search | text, cited |
Record UNKNOWN for any signal a tool cannot return.
Step 2 — Compute the severity tier (fixed rules)
Apply these rules in order; the first match wins. This is deterministic — do not deviate.
- CRITICAL if
kev.listed == true (actively exploited in the wild), OR (cvss_baseScore >= 9.0 AND epss >= 0.5).
- HIGH if
cvss_baseScore >= 7.0 AND (epss >= 0.1 OR kev.listed == true).
- MEDIUM if
cvss_baseScore >= 4.0.
- LOW if
cvss_baseScore < 4.0.
- INDETERMINATE if
cvss_baseScore == UNKNOWN. Do not assign a numeric tier; escalate to human review with the missing-data note.
EPSS reference bands (for the report, not for re-tiering): >= 0.5 high exploit likelihood; 0.1–0.5 elevated; < 0.1 low.
Step 3 — Asset-impact analysis
For each affected asset (via asset_lookup), determine:
- Exposure: internet-facing / internal / isolated.
- Criticality: crown-jewel / production / non-production (unknown → production).
- Reachability of the vulnerable component: is the affected package/config actually present and the vulnerable code path reachable? An unreachable component downgrades urgency but never the severity tier.
- Blast radius: count and criticality of dependent systems.
Compute an impact multiplier deterministically:
INTERNET_FACING + CRITICAL → urgency = severity tier as-is.
INTERNAL + CRITICAL or INTERNET_FACING + PRODUCTION → urgency = severity tier as-is.
ISOLATED or component_not_present → urgency = one tier lower (but log the original severity).
Step 4 — Action decision (deterministic mapping)
| Urgency | Default action | SLA guidance |
|---|
| CRITICAL | PATCH (emergency change) | Immediate; interim MITIGATE if no patch |
| HIGH | PATCH (expedited) or MITIGATE if patch unavailable | Days |
| MEDIUM | MITIGATE or schedule PATCH in normal cycle | Next cycle |
| LOW | MONITOR | Track only |
| Component not present / not reachable | NO-ACTION (document rationale) | Re-check on inventory change |
| INDETERMINATE | HUMAN REVIEW — do not recommend an action | Blocking |
MITIGATE means a compensating control (WAF rule, config change, network segmentation, feature disable) when a patch is unavailable or cannot be applied in time.
Step 5 — Emit structured output
Produce a CVETriage object:
{
"cve_id": "CVE-XXXX-XXXXX",
"cvss_base_score": 0.0,
"cvss_vector": "string|UNKNOWN",
"epss_score": 0.0,
"kev_listed": false,
"severity_tier": "CRITICAL|HIGH|MEDIUM|LOW|INDETERMINATE",
"affected_assets": [{"id": "...", "exposure": "...", "criticality": "...", "component_present": true}],
"urgency": "CRITICAL|HIGH|MEDIUM|LOW|NO-ACTION|HUMAN-REVIEW",
"recommended_action": "PATCH|MITIGATE|MONITOR|NO-ACTION|HUMAN-REVIEW",
requires_human_approval is always true.
Guardrails
- Never mark a CVE resolved or close a ticket autonomously — that is a human action.
- Never fetch or execute proof-of-concept code. Reference exploit status (from KEV/EPSS/advisories) only.
- If EPSS or KEV lookups fail, degrade gracefully: tier on CVSS alone and flag the missing signal in
unknowns.
- Persist the verdict and rationale to memory so repeat lookups of the same CVE are consistent and auditable.