Skip to content
Back to skills

Vulnerability Triage

ASecurity

Triages and prioritizes security vulnerabilities (CVEs) by combining CVSS base/temporal scores, real-world exploitability (EPSS, KEV, public PoCs), environmental exposure (internet-facing, network reachability, authentication), and business impact (data sensitivity, asset criticality) into a defensible, ranked remediation plan with SLAs. Use this skill when asked to triage CVEs, prioritize a vulnerability scan, assess whether a CVE is exploitable or reachable in a given environment, decide pa...

  • 12 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 14, 2026
ai-agentsrustgogitci/cdsecurity

Works with

  • cli

Security analysis

A100/100

Pro scans all 8 files and shows the line behind each finding

Scanned October 14, 2026

npx -y skills add JayRHa/agent-skills --skill vulnerability-triage --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Vulnerability Triage?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Vulnerability Triage
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/jayrha-vulnerability-triage/badge)](https://www.skillsdirectory.com/skills/jayrha-vulnerability-triage)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: vulnerability-triage
description: Triages and prioritizes security vulnerabilities (CVEs) by combining CVSS base/temporal scores, real-world exploitability (EPSS, KEV, public PoCs), environmental exposure (internet-facing, network reachability, authentication), and business impact (data sensitivity, asset criticality) into a defensible, ranked remediation plan with SLAs. Use this skill when asked to triage CVEs, prioritize a vulnerability scan, assess whether a CVE is exploitable or reachable in a given environment, decide patch urgency, set remediation SLAs, write a vulnerability risk assessment, deduplicate scanner findings, or answer "how bad is CVE-XXXX-YYYYY for us?" / "should we drop everything to patch this?".
license: MIT
---

# Vulnerability Triage

## Overview

Vulnerability triage turns a flood of scanner findings or a single CVE into a
**ranked, justified, time-bound remediation decision**. CVSS alone is a poor
prioritizer: only a small fraction of CVEs are ever exploited, and a "Critical"
CVSS on an isolated internal box may matter far less than a "Medium" on an
internet-facing crown-jewel system.

This skill scores each vulnerability across four dimensions and combines them:

1. **Severity** — CVSS base + temporal (intrinsic technical impact).
2. **Exploitability** — EPSS probability, CISA KEV listing, public exploit/PoC, weaponization.
3. **Exposure** — attack vector, internet-facing, network reachability, authentication/preconditions, compensating controls.
4. **Business impact** — asset criticality, data sensitivity, blast radius, regulatory scope.

Keywords: CVE, CVSS, EPSS, CISA KEV, exploitability, attack vector, remediation
SLA, patch priority, vulnerability management, risk score, false positive,
compensating control, SSVC, internet-facing, privilege escalation.

## When to Use

- Triaging output from Nessus / Qualys / Tenable / Trivy / Grype / Dependabot / Snyk.
- Deciding patch urgency for a newly disclosed CVE.
- Writing a vulnerability risk assessment or exception/risk-acceptance memo.
- Deduplicating and clustering scanner findings by root cause.
- Justifying *why* something is (or is not) urgent to leadership or auditors.

## Workflow

Follow these steps in order. For a single CVE, steps 2-5 take minutes; for a
scan, batch through `scripts/triage.py` first, then hand-review the top tier.

### 1. Normalize and deduplicate the input
- Collapse duplicate findings: same CVE + same package/component on the same host
  is one finding instance; many hosts = one vuln with N instances.
- Group by **root cause** (e.g., one vulnerable `openssl` version → all dependent
  findings). Patching the root usually clears the cluster.
- Drop **confirmed false positives** (see references/false-positives.md) before scoring.

### 2. Establish severity (CVSS)
- Capture the **CVSS v3.1/v4.0 base score** and the **vector string**, not just the number.
- Read the vector: `AV` (attack vector), `AC` (complexity), `PR` (privileges
  required), `UI` (user interaction), and impact metrics `C/I/A`.
- Apply **temporal** metrics if available (Exploit Code Maturity, Remediation
  Level). A high base with `E:U` (unproven) is less urgent than one with `E:H` (high/weaponized).
- See references/cvss-guide.md for vector decoding and common miscalibrations.

### 3. Establish exploitability (the single biggest re-ranking signal)
Gather, in priority order:
- **CISA KEV**: Is the CVE on the Known Exploited Vulnerabilities catalog? If yes,
  it is being exploited in the wild now — treat as top priority regardless of CVSS.
- **EPSS**: Exploit Prediction Scoring System probability (0-1) of exploitation in
  the next 30 days. EPSS ≥ 0.5 is high; ≥ 0.1 is elevated.
- **Public exploit / PoC**: Exploit-DB, Metasploit module, GitHub PoC, Nuclei
  template. Weaponized + reliable > theoretical.
- **Ransomware / campaign association**: known use by ransomware crews escalates urgency.

### 4. Establish exposure (environmental reality)
Answer for *your* environment, not the abstract CVE:
- **Internet-facing?** Reachable from untrusted networks?
- **Network reachability**: Can an attacker actually reach the vulnerable port/service/path?
- **Authentication / preconditions**: Does exploitation need valid creds, local
  access, a specific non-default config, or user interaction?
- **Compensating controls**: WAF rule, network segmentation, EDR, MFA, the
  feature being disabled, the package present but unused/dead code.
- **Is the vulnerable code path actually invoked?** (Reachability analysis for
  dependencies — a vulnerable function never called ≈ not exploitable.)

### 5. Establish business impact
- **Asset criticality**: crown-jewel / production / internal / dev-test / decommissioning.
- **Data sensitivity**: regulated PII/PHI/PCI, secrets, IP, or low-value data.
- **Blast radius**: lateral movement potential, shared credentials, identity-tier
  (Tier 0 / domain controller / CI-CD / cloud control plane).
- **Regulatory / contractual** clocks (e.g., CISA BOD 22-01 deadlines for federal,
  PCI DSS timelines).

### 6. Compute the composite priority and SLA
Use the decision framework below (or run `scripts/triage.py`). Map the result to a
**priority tier (P0-P4)** and a **remediation SLA**. Record the *rationale* — triage
is only defensible if the reasoning is written down.

### 7. Decide the action
For each finding choose exactly one: **Patch now / Patch within SLA / Mitigate
(compensating control) / Accept risk (with expiry + owner) / False positive**.
Risk acceptance always needs an owner, a justification, and an expiry date.

## Decision Framework

### Fast-path overrides (apply first, in order)
1. **On CISA KEV** AND reachable/exposed → **P0** (drop-everything), SLA ≤ 24-72h.
2. **EPSS ≥ 0.5** AND internet-facing AND `AV:N` → **P0/P1**.
3. **CVSS ≥ 9.0** AND internet-facing AND public weaponized exploit → **P1**.
4. **Confirmed not reachable / dead code / not deployed** → downgrade to **P4** or
   mark false-positive — exposure gates everything else.

### Composite scoring (when no fast-path fires)
Compute a 0-100 priority score (this is what `scripts/triage.py` implements):

```
priority = 100 * normalize(
      0.30 * severity_norm        # CVSS base / 10
    + 0.30 * exploitability_norm  # max(EPSS, KEV=1.0, weaponized=0.9, PoC=0.6)
    + 0.25 * exposure_norm        # internet/auth/controls-adjusted, 0..1
    + 0.15 * impact_norm          # asset+data criticality, 0..1
)
```

| Priority | Score band | Meaning | Default SLA |
|----------|-----------|---------|-------------|
| P0 | KEV-exposed or ≥ 90 | Active exploitation, exposed, high impact | 24-72 hours |
| P1 | 75-89 | Likely-exploitable, exposed | 7 days |
| P2 | 50-74 | Meaningful risk, moderate exposure | 30 days |
| P3 | 25-49 | Low likelihood or well-contained | 90 days |
| P4 | < 25 | Negligible / accept or backlog | Next maintenance cycle |

This mirrors the spirit of **SSVC** (Stakeholder-Specific Vulnerability
Categorization): decisions driven by exploitation status, exposure, and impact —
not raw CVSS. See references/scoring-model.md for the full rationale, the SSVC
decision tree, and how to tune weights per organization.

## Worked Example (condensed)

CVE-2024-3094 (xz/liblzba backdoor), internal build server, not internet-facing,
sshd not exposed externally, package present:
- Severity: CVSS 10.0.
- Exploitability: KEV-adjacent, supply-chain, but exploit requires specific sshd+systemd path.
- Exposure: SSH only reachable from internal admin VLAN; affected versions present.
- Impact: build server = CI/CD = Tier-0-adjacent, high blast radius.
- Result: KEV/severity high but reachable internally + Tier-0 impact → **P0**,
  patch/downgrade immediately, rotate any secrets handled by the host.

See examples/triage-walkthrough.md for three fully scored examples, including one
that gets *downgraded* by exposure and one false positive.

## Best Practices

- **Exploitability and exposure beat CVSS.** Always pull KEV + EPSS before ranking.
- **Score the instance in your environment**, not the abstract CVE. Reachability changes everything.
- **Cluster by root cause** — fix once, clear many.
- **Write the rationale.** A triage decision without a recorded "why" is not defensible.
- **Risk acceptance is a decision, not a default.** Owner + justification + expiry, always.
- **Re-triage on new signal.** EPSS and KEV change daily; a P3 can become P0 overnight.
- **Track SLA aging**, not just open counts.

## Common Pitfalls

- Sorting by CVSS alone and drowning in "Criticals" nobody can exploit.
- Treating a scanner "Critical" as ground truth without confirming the package is
  deployed and the version is actually vulnerable (version-range false positives).
- Ignoring KEV/EPSS because "the CVSS is only Medium" — KEV Mediums are real and exploited.
- Forgetting compensating controls and over-prioritizing already-mitigated issues.
- Counting transitive/dev-only dependencies as production exposure.
- Accepting risk with no expiry, so it silently lives forever.

## Bundled Files

- `references/cvss-guide.md` — decode CVSS v3.1/v4.0 vectors, temporal metrics, miscalibrations.
- `references/scoring-model.md` — composite model, SSVC tree, weight tuning, data sources.
- `references/false-positives.md` — confirming/ruling out findings, reachability analysis.
- `references/sla-policy-template.md` — ready-to-adopt SLA + risk-acceptance policy.
- `scripts/triage.py` — stdlib CLI that scores findings from JSON/CSV and emits a ranked report.
- `examples/triage-walkthrough.md` — three fully worked, scored examples.
- `templates/triage-report.md` — fill-in assessment / report template.

Files in this skill

  • SKILL.md9.5 KB
  • examples/triage-walkthrough.md3.2 KB
  • references/cvss-guide.md4.2 KB
  • references/false-positives.md3.2 KB
  • references/scoring-model.md4.6 KB
  • references/sla-policy-template.md2.6 KB
  • scripts/triage.py7.6 KB
  • templates/triage-report.md2.1 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.