# Vulnerability Management

> Finds, prioritizes, and closes out vulnerabilities across code, dependencies, images, and infrastructure without drowning the team in unactionable findings. Use this whenever the user is deciding what to patch first, has a scanner producing hundreds of CVEs, is setting patch SLAs, is asking whether a vulnerability is actually exploitable, or is building a remediation process. For the scanners that produce these findings use `security-scanning`; for trusting the artifacts you patch use `supply-chain-security`.

- Skill: `arjunprabhulal/vulnerability-management` (Agent Skill)
- Install (CLI): `npx skillmds@latest add arjunprabhulal/vulnerability-management`
- Raw SKILL.md: https://api.skillmd.com/api/skills/arjunprabhulal/vulnerability-management/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- License: MIT
- Author: arjunprabhulal (https://skillmd.com/u/arjunprabhulal)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/arjunprabhulal/vulnerability-management

---


# Vulnerability Management

A raw scanner report is a list of theoretical problems, not a work plan. Every base image pulls
in hundreds of CVEs, most in code paths nobody calls, in packages exposed to nothing, behind
network boundaries that block the exploit. Treating every CVE as equally urgent trains the team
to ignore the report entirely, which is worse than not scanning at all.

The job is triage, not enumeration. A finding earns attention by being both exploitable and
reachable — not by having a high CVSS score in isolation.

**A vulnerability nobody can reach is a lower priority than a medium-severity one sitting on
your public ingress.**

## 1. Scan everywhere, but don't treat every scan the same

Code, dependencies, container images, IaC, and running infrastructure each need coverage, and
each surfaces different risk. A dependency CVE in a library you don't call is different from a
misconfigured security group actively exposing a database. Route each scan type to its own
queue with its own triage rules instead of one undifferentiated backlog. The scanning tools
themselves — SAST, dependency, image — belong to `security-scanning`; this skill is about what
happens to what they find.

**Done when:** every asset class (code, deps, images, infra) has an owner for its findings
queue.

## 2. Prioritize by exploitability and reachability, not raw CVSS

CVSS measures theoretical severity assuming the vulnerable code path is reachable and
unmitigated — it says nothing about your actual deployment. A critical CVE in a function your
code never calls is lower priority than a medium CVE in your internet-facing auth path.

| Signal | Raises priority | Lowers priority |
|---|---|---|
| Reachability | Vulnerable function is on a call path from user input | Package installed but code path unused |
| Exposure | Internet-facing, no auth | Internal-only, behind mTLS |
| Known exploitation | Actively exploited in the wild (KEV-listed) | No known public exploit |
| Compensating control | None | WAF rule or network policy already blocks the vector |

Use reachability analysis or SCA tooling that traces call graphs where available — it turns a
400-CVE report into a 12-item list.

**Done when:** the top of the remediation queue is sorted by exploitability and exposure, not
by CVSS number alone.

## 3. Set patch SLAs by severity tier, and hold to them

An SLA without enforcement is a suggestion. Tie tiers to the triage from step 2, not to raw
scanner severity, so the SLA clock only starts once something is actually confirmed exploitable
and reachable. Track SLA breaches visibly — a dashboard the team ignores is not a control, it's
decoration.

- **Critical + actively exploited**: patch or mitigate within a day, page if missed.
- **High + reachable**: patch within the sprint.
- **Everything else**: batch into normal dependency-update cadence.

**Done when:** every open finding has an SLA clock attached and a named owner.

## 4. Give the team a fix, not just a finding

"Upgrade log4j" is more actionable than "CVE-2021-44228 detected." Where possible, the report
should include the target version, whether it's a drop-in upgrade or a breaking change, and a
compensating control if the fix isn't immediate. Findings without a clear next action rot in
the backlog and erode trust in the whole program.

**Done when:** a developer can act on a finding without first researching what the CVE means.

## 5. Suppress deliberately, not by ignoring

Some findings are accepted risk — no fix exists, the path is unreachable, a compensating
control covers it. Suppress those explicitly with a reason and a review date, rather than
letting them sit unacknowledged. An unreviewed suppression list is how a real exploitable
finding hides in noise for a year.

- **Time-box every suppression** and revisit it, since "unreachable today" can become reachable
  after a refactor.

**Done when:** every suppressed finding has a documented reason and an expiry for re-review.

## Report

State the current open-finding count by severity tier, the SLA for each tier, and how many are
currently past SLA. Name the class of finding still triaged by raw CVSS alone rather than
reachability — that's where the noise is still winning, and admitting it is more useful than a
clean-looking dashboard.

