# Prioritizing Dependabot alerts, the complete guide: decide what to fix first with CVSS × EPSS × reachability

> When Dependabot alerts pile into double digits, which do you fix first? Sorting by severity (CVSS) alone gets the priority wrong. Faithful to the official docs, this guide combines CVSS (how bad the impact) with EPSS (the probability of being attacked, updated daily by FIRST) on two axes, then covers reachability, dependency scope, auto-triage rules (matching on severity/EPSS/scope), and REST-API inventory — a triage design that cuts alert fatigue and focuses on the truly dangerous few, with real code.

- Published: 2026-07-01
- Author: 友田 陽大
- Tags: Dependabot, サプライチェーンセキュリティ, 脆弱性管理, EPSS, DevSecOps, セキュリティ
- URL: https://tomodahinata.com/en/blog/dependabot-alerts-prioritization-cvss-epss-reachability-triage-guide
- Category: Dependabot & dependency automation
- Pillar guide: https://tomodahinata.com/en/blog/dependabot-production-guide

## Key points

- Severity (CVSS) is 'how bad the damage,' EPSS is 'the probability of actually being attacked.' Sorting by CVSS alone melts effort on Criticals that are rarely attacked while deferring the ones under active attack.
- EPSS is a machine-learning model published by FIRST that estimates, daily, the probability (0–1) a published CVE will be exploited in the wild within the next 30 days. GitHub has shown EPSS in Dependabot alerts since February 2025.
- In practice, handle it with a CVSS × EPSS matrix. In GitHub's own example, 'EPSS 85% / CVSS 9.8' should 'almost always' outrank 'EPSS 0.5% / CVSS 9.0.' Reachability (does your code hit the vulnerable path?) and dependency scope (dev/prod) are the third axis.
- auto-triage rules can match on severity, EPSS, scope, package, CVE, ecosystem, and manifest location. Auto-dismiss/prioritize by EPSS threshold or dev scope to cut noise before the notification ever fires.
- 'What to fix first' (ranking) and 'by when' (SLA) are different problems. Focus on the few, and you cover most of the vulnerabilities that are actually exploited with far less effort.

---

The Dependabot alert badge just hit double digits. So — **which do you fix first?** This is where many teams freeze. The common reflex is "**by descending severity (Critical/High).**" It looks right, but it's the biggest trap: it **gets the priority wrong.** Severity only tells you "**how much it hurts if it's exploited**," and says nothing about "**whether it will be exploited at all.**"

This article, a topic of the [Dependabot production-operations guide](/blog/dependabot-production-guide), focuses on **the ranking of "what to fix first."** Enablement, SLA, and the operation of auto-triage itself are left to the [alerts & security-updates guide](/blog/dependabot-security-updates-alerts-vulnerability-management-guide); here we design triage along three axes — **CVSS × EPSS × reachability** — to cut alert fatigue and focus on the **truly dangerous few.**

> **Rules for this article**: the EPSS/CVSS definitions follow **FIRST's primary sources**, and Dependabot's behavior follows the **GitHub official documentation (as of July 2026).** EPSS is a "probability," not a "certain prophecy." Always confirm the latest numbers and interpret them in your context (public vs. internal, regulated industry).

---

## 1. Why sorting by severity (CVSS) alone gets the priority wrong

**CVSS (Common Vulnerability Scoring System)** is a static score that expresses a vulnerability's **severity — the size of the impact — from 0 to 10.** The GitHub Advisory Database ingests the **CVSS v4.0 / v3.1 / v3.0** assigned by the maintainer and shows it as severity (Critical/High/Medium/Low) on Dependabot alerts.

CVSS is an excellent measure of "**how much it hurts if exploited**," but it's missing something decisive — "**will it actually be exploited?**" The world is full of CVSS 9.x vulnerabilities that are **almost never attacked in reality,** and conversely medium-CVSS ones for which **attacks are being observed.** Sort by descending severity and clear from the top, and you **melt effort on Criticals that are rarely attacked while deferring the ones under active attack** — this is the "severity-sort trap."

GitHub's analogy makes it clear: **CVSS is "how bad the damage if someone broke into your house," and EPSS is "how likely someone is actually going to try."** You can't paint the full picture of risk without both.

---

## 2. EPSS: measuring the "probability" of being attacked

**EPSS (Exploit Prediction Scoring System)** is a **data-driven machine-learning model** published by FIRST that estimates, from **0 to 1 (0–100%)**, the probability that "**a published CVE will be exploited in the wild within the next 30 days.**"

The key points (per FIRST's official docs):

- **Meaning**: the higher the score, the higher the probability the vulnerability will **actually be attacked in the near future.**
- **Update frequency**: **every CVE is updated every day** and published via CSV / API.
- **Percentile**: beyond the absolute probability, it also provides a "relative position among all CVEs."
- **Difference from CVSS**: where CVSS measures **subjective severity,** EPSS measures the "likelihood of exploitation" with **empirical signals from observed exploitation.** **Severity and likelihood are different things.**

In other words, EPSS answers, with a probability, the question CVSS can't: "**is this vulnerability actually going to be targeted this month?**" The two aren't competitors — they're **complements.**

---

## 3. Handle it with a CVSS × EPSS matrix

The implementation of ranking becomes unambiguous once you drop it into a **two-axis matrix.**

| | **High EPSS** (attacks are coming) | **Low EPSS** (no exploitation signs yet) |
| --- | --- | --- |
| **High CVSS** (large impact) | **Top priority**: patch & deploy immediately | Handle on a plan (monitor, roll into the next scheduled update) |
| **Low CVSS** (small impact) | Monitor / mitigate (often attacked, but limited impact) | Defer (mostly noise; an auto-triage dismiss candidate) |

GitHub itself illustrates this thinking with an example: a "**EPSS 85% / CVSS 9.8**" vulnerability should "**almost always**" take priority over an "**EPSS 0.5% / CVSS 9.0**" one. Both are Critical by severity, but the **probability of being attacked differs by orders of magnitude.** Look only at severity and these two line up as "the same Critical."

> **Why focusing on the few works**: EPSS research reports that **prioritizing by EPSS lets you cover the large majority of the vulnerabilities actually exploited while addressing only a small fraction of them.** "Fix the dangerous few for certain" rather than "fix everything" is far more cost-effective against finite engineering time — this is the economic basis of EPSS-based triage.

---

## 4. The third axis: reachability and dependency scope

CVSS × EPSS measures the "**danger in general.**" But a final question remains: "**can that vulnerability actually be reached in our app?**" This is **reachability.**

An important fact here: **Dependabot detects whether a vulnerable dependency "exists" in the dependency graph.** It **does not determine whether your code actually calls that vulnerable function.** A vulnerability in a code path that's present as a dependency but never actually reached can remain a **theoretical risk.**

Rigorous reachability analysis is the domain of other tools, but in practice you first use **dependency scope (dev / prod) as a proxy.**

- **Production dependencies (production scope)**: can process user input at runtime. Treat as **high reachability.**
- **Development dependencies (development scope)**: only at build/test time. Less exposed to the production attack surface, so **often low reachability** (protecting the CI environment itself is a separate concern).

So the final priority is decided on three axes — **CVSS (impact) × EPSS (probability) × reachability (does it run in production?).** "Production dependency × high CVSS × high EPSS" is top priority; "dev dependency × low CVSS × low EPSS" is an auto-triage auto-dismiss.

---

## 5. Putting it into practice on GitHub

### 5.1 Sort alerts by EPSS

GitHub has **shown EPSS scores on Dependabot alerts since February 2025** (GitHub Enterprise Server 3.17+). EPSS is **synced daily from FIRST.** **Sort the alert list by descending EPSS** and you pick up "the vulnerabilities under active attack" first. Combine it with the severity filter to gather **Critical/High and high EPSS** at the top — that's the basic move.

### 5.2 Cut noise "before notification" with auto-triage rules

`auto-triage rules` match alerts on metadata like **severity, EPSS, scope, package name, CVE, ecosystem, and manifest location,** and automatically dismiss / snooze them **before the notification fires.** Being able to use EPSS as a condition is powerful — you can mechanize policies like:

- "Auto-dismiss alerts that are **dev scope and low EPSS**" — don't even notify for things with low production reachability and low attack probability.
- "**Always keep high EPSS** regardless of severity" — never drop the high-probability ones.

Because rules **apply before notification,** you achieve "**don't raise it in the first place**" rather than "filter it later." Limit auto-dismiss to what you can **argue has no production impact,** and keep the **decision in the log.**

### 5.3 Inventory the "unaddressed danger" with the REST API

To keep it running you need measurement. Dependabot alerts can be fetched via the **REST API,** so dashboard **open × Critical/High** and detect SLA breaches early.

```bash
# Extract only unaddressed Critical / High alerts (starting point for inventory & observability)
gh api \
  -H "Accept: application/vnd.github+json" \
  "/repos/{owner}/{repo}/dependabot/alerts?state=open&severity=critical,high" \
  --jq '.[] | {number, severity: .security_advisory.severity, package: .dependency.package.name, ghsa: .security_advisory.ghsa_id}'
```

For an organization-wide view, use `/orgs/{org}/dependabot/alerts` and decide the human review order by descending EPSS. Being able to see at a glance whether **unaddressed high-EPSS items are piling up** is the last line of defense against a hollowed-out process. For designing the SLA itself, head to the [alerts & security-updates guide](/blog/dependabot-security-updates-alerts-vulnerability-management-guide).

---

## 6. Write down the prioritization policy

Triage runs on a **written policy,** not "gut feeling in the moment." If you're going to claim world-class, put these into words and share them across the team.

- **The ranking formula**: priority by production reachability × EPSS × CVSS (e.g., production × EPSS≥high × Critical at the very top).
- **The auto-dismiss boundary**: which scope / EPSS bands you drop via auto-triage, and the **rationale.**
- **Handling exceptions**: how you get past a high-EPSS vuln with no fix yet — mitigation (block the reachable path, disable the feature, WAF) or migrating to an alternative library.
- **Review cadence**: EPSS moves daily. **What was "low" yesterday can be "high" today,** so keep monitoring.

Triage means **leaving the decision on record,** not "leave it because it can't be fixed." Design ranking (this article) and "by when" — the SLA and automation ([production-operations guide](/blog/dependabot-production-guide) / [alerts & security-updates guide](/blog/dependabot-security-updates-alerts-vulnerability-management-guide)) — as separate roles.

---

## 7. Avoid the common misconceptions

- **"CVSS = risk" is false.** CVSS is just the one axis of **impact.** Risk ≒ impact × probability × reachability.
- **EPSS is a "probability," not a "prophecy."** An attack may not come even at EPSS 90%, and a low EPSS can suddenly spike (which is why it's updated daily). **Treat it as a probability and monitor continuously.**
- **Dependabot is SCA (known vulnerabilities in dependencies).** Vulnerabilities in your own code (SQLi/XSS/SSRF/broken authorization) are the domain of **SAST/DAST,** a different layer from the EPSS/CVSS discussion. The full picture is in the [web-app vulnerability-assessment guide](/blog/web-application-vulnerability-assessment-owasp-zap-sast-dast-guide).

**Stop "top-down by descending severity," and focus on the few that are under attack, cause large damage, and run in production.** That is, right now, the most cost-effective triage design for reducing the real supply-chain risk in the least time with finite effort.
