toolhq.io

skills / security

dependency-triage

Turn a vulnerability scan into an ordered list of actions by working out which findings are actually reachable.

SKILL.md

Save as .claude/skills/dependency-triage/SKILL.md in a repository, or under ~/.claude/skills/dependency-triage/SKILL.md to have it everywhere. The copy button takes the whole file, frontmatter included.

---
name: dependency-triage
description: Turn a vulnerability scan into an ordered list of actions by working out which findings are actually reachable. Use when triaging npm audit, Dependabot alerts, a CVE list, or deciding which dependency upgrades matter.
---

# Dependency triage

A scanner reports what is installed, not what is exploitable. In a typical
report most findings are not reachable in your application, and a few are
urgent. Treating them as one undifferentiated list means the urgent ones wait
behind the irrelevant ones.

The job is ranking, not patching everything.

## For each finding, establish four things

### 1. Is the vulnerable code reachable
The question that removes most of the list.

- Is the package a direct dependency or pulled in transitively.
- Is the vulnerable *function* called, directly or by something you call. A
  vulnerability in a package's CLI does not affect you if you import its
  library.
- Can attacker controlled input reach it. A parser vulnerability matters when
  you parse untrusted input and usually does not when you parse your own
  config at boot.

### 2. Where does it run
- Production server code: highest concern.
- Client side code: concern depends on whether the attacker is the user.
- Build time or development only: usually low, with one exception below.
- Test only: normally not urgent.

A `devDependencies` finding is not automatically safe. Build tooling runs with
repository access and often with credentials, so a compromised build package
is a supply chain problem even though it never ships.

### 3. What does exploitation need
Network access, authentication, a specific configuration, a user action, or a
malicious input you would have to accept. A critical score that needs local
root access is less pressing than a medium one that needs an HTTP request.

### 4. What does fixing cost
A patch release is minutes. A major version bump across a framework is a
project. That difference belongs in the ranking.

## Do not rank by severity score alone

The score describes the worst case for anyone using the package. It knows
nothing about your application. A critical finding in a package you import but
never invoke is lower priority than a medium one on your login path.

Say this explicitly when reporting, because the score is what everyone else is
looking at.

## Fixing

Prefer, in order:

1. Upgrade the direct dependency to a patched version.
2. Upgrade the parent that pins the vulnerable transitive dependency.
3. Override or resolve the transitive version, and record why, because
   overrides rot silently.
4. Remove the dependency. Often realistic for a small package, and it removes
   the whole class of future findings.
5. Mitigate in your own code, and document the mitigation next to the finding
   so nobody removes it later.
6. Accept the risk, with a written reason and a date to revisit.

Accepting is a legitimate outcome. Accepting silently is not.

## Traps

- **Do not bulk upgrade everything to clear the report.** A clean report
  bought with an untested major version bump trades a theoretical risk for a
  real outage.
- **Check whether the advisory applies to your version range.** Reports
  sometimes flag versions that were never affected.
- **A withdrawn or disputed advisory is still a finding to explain**, not one
  to action.
- **Look at the fix, not just the version number.** Occasionally the patched
  release changes behaviour you depend on.

## Report back

1. Act now: reachable, exploitable, on a sensitive path. With the fix.
2. Schedule: real but not urgent, or expensive to fix.
3. Not applicable: with one line each on why, so nobody re triages them.
4. Anything you could not determine, named rather than assumed safe.

what it needs

Nothing. This skill is instructions only, so it works in any agent that reads SKILL.md with nothing installed and no account. Save the file and it is live in the next session.

the instructions, in full

Dependency triage

A scanner reports what is installed, not what is exploitable. In a typical report most findings are not reachable in your application, and a few are urgent. Treating them as one undifferentiated list means the urgent ones wait behind the irrelevant ones.

The job is ranking, not patching everything.

For each finding, establish four things

1. Is the vulnerable code reachable

The question that removes most of the list.

2. Where does it run

A devDependencies finding is not automatically safe. Build tooling runs with repository access and often with credentials, so a compromised build package is a supply chain problem even though it never ships.

3. What does exploitation need

Network access, authentication, a specific configuration, a user action, or a malicious input you would have to accept. A critical score that needs local root access is less pressing than a medium one that needs an HTTP request.

4. What does fixing cost

A patch release is minutes. A major version bump across a framework is a project. That difference belongs in the ranking.

Do not rank by severity score alone

The score describes the worst case for anyone using the package. It knows nothing about your application. A critical finding in a package you import but never invoke is lower priority than a medium one on your login path.

Say this explicitly when reporting, because the score is what everyone else is looking at.

Fixing

Prefer, in order:

  1. Upgrade the direct dependency to a patched version.
  2. Upgrade the parent that pins the vulnerable transitive dependency.
  3. Override or resolve the transitive version, and record why, because overrides rot silently.
  4. Remove the dependency. Often realistic for a small package, and it removes the whole class of future findings.
  5. Mitigate in your own code, and document the mitigation next to the finding so nobody removes it later.
  6. Accept the risk, with a written reason and a date to revisit.

Accepting is a legitimate outcome. Accepting silently is not.

Traps

Report back

  1. Act now: reachable, exploitable, on a sensitive path. With the fix.
  2. Schedule: real but not urgent, or expensive to fix.
  3. Not applicable: with one line each on why, so nobody re triages them.
  4. Anything you could not determine, named rather than assumed safe.