---
name: dependency-cve-triage
description: "Triages a known CVE in a dependency by reachability and exposure — is the vulnerable code actually reached, is it fed untrusted input, does a fix exist — to decide fix-now vs schedule vs document-as-not-affected, instead of acting on the CVSS number alone. Use when a scanner, Dependabot alert, or audit flags a specific known vulnerability in a library you depend on and you must decide what to do about it. Do NOT use for reviewing a routine version bump, picking a new library, or reviewing application source code for its own vulnerabilities."
metadata:
  decimalai-skill-id: "43cc22ba-2265-4f72-8508-7294e72b0b13"
  decimalai-version-id: "b2ce51ce-01cd-46bc-91c9-fb2e1b56f596"
  decimalai-version: "1"
  decimalai-body-sha256: "206f1dbe4550abc9863474f6f7e728cd22c3cc342f2448df9b71bfd7731fd675"
  decimalai-name: "dependency-cve-triage"
  decimalai-format: "1"
  decimalai-invocation: "model"
  decimalai-category: "security"
  decimalai-source: "https://app.decimal.ai/s/dependency-cve-triage@1/SKILL.md"
---
# Dependency CVE Triage

A scanner just flagged a known vulnerability in one of your dependencies. A capable model can reason about every factor below, but by default it anchors on the **CVSS number**: it sees "critical, 9.8" and says drop everything, or sees "low, 4.3" and says accept it. That anchoring is the miscalibration this skill corrects. CVSS measures how bad the flaw is *if* it is exploited, in the abstract. It does not measure *your* risk. Your risk is **reachability × exposure × exploitability in your configuration**. Triage that first; use the score only to rank among issues that are actually reachable.

## When to activate

Activate when the request hands you **a specific known vulnerability in a dependency** — a CVE, a GHSA/Dependabot alert, an `npm audit` / `pip-audit` / `cargo audit` finding — and asks whether to fix it, how urgent it is, or what to do about it.

Do **not** activate to review a routine version bump for merge safety (that is a dependency-upgrade review), to choose or add a brand-new library, or to review your own application source for vulnerabilities.

## Triage by reachability, not by the score

Walk the ladder in order and **stop at the first decisive answer**. Most alerts resolve in the first two rungs.

1. **Is a fix available and cheap to take?** If a patched version exists and the upgrade is a non-breaking patch/minor, just upgrade. Patching is usually cheaper than analyzing — don't spend triage effort proving un-reachability when the fix is one line in a manifest.
2. **Is the vulnerable code path actually reached?** Look at whether the specific vulnerable function/class is invoked — by your code or transitively through a package you call. If the vulnerable symbol is never in your resolved call graph, you are **not affected**: the flaw cannot fire in your build.
3. **Is that path reachable with untrusted input?** A parsing/deserialization bug only matters if attacker-controlled bytes reach the parser. If the vulnerable code is only ever fed internal, trusted, constant input, the real exposure is far below the score.
4. **Where does the dependency run?** A vuln in a build-time, test-only, or dev tool that is never shipped in the production artifact is not the same as one in a live, internet-facing request handler. Un-shipped code has no runtime attack surface.
5. **Is exploitation gated behind a config you don't enable?** Many CVEs only trigger under a specific mode (external XML entities enabled, an unsafe deserialization option, a disabled-by-default feature). If you don't enable it, you are not affected in your current configuration.

## The decision

| Verdict | When | Action |
|---|---|---|
| **Fix now** | vulnerable code is reached **and** reachable with untrusted input **and** on a shipped/serving path | upgrade or patch immediately; if no fixed version exists, **mitigate** — remove or replace the dependency, disable the vulnerable feature, or validate/neutralize the input |
| **Schedule** | reachable but not exposed to untrusted input, or a fix exists but the upgrade is breaking | plan the upgrade into normal work; it is not a drop-everything emergency |
| **Not affected / accept** | vulnerable code not reachable, dev/build-only dependency, or exploitation gated behind a config you don't enable | **document the justification** (a VEX-style "not affected: vulnerable code not in the execution path") so the alert can be suppressed with a paper trail, not silently ignored |

## The two miscalibrations to resist

- **High score, unreachable → still not urgent.** A CVSS 9.8 in a function you never call, or in a build tool you never ship, is not your emergency. Confirm un-reachability and document it; don't halt the release for it.
- **Low score, reachable → can outrank a higher one.** A "medium" flaw reachable with untrusted input on an auth or request path matters more than a "critical" sitting in dead code or a dev linter. Re-rank by reachability and exposure, not by the vendor's number.
- **"No fix yet" is not "accept."** If it is reachable and exposed, absence of a patch means you **mitigate now**, not that you wait.
- **Transitive still counts, but check your usage.** The vulnerable package may be pulled in by something you use — before treating it as urgent, confirm your call graph actually reaches the vulnerable path through that intermediate.
