You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
chore(claude): update audit-dependencies skill with lockfile strategy and override rules (#16106)
# Overview
Updates the audit-dependencies skill to include a lockfile-update
strategy as an intermediate fix between direct dependency bumps and pnpm
overrides. Also adds documentation for common pnpm override pitfalls
learned from recent audit work.
## Key Changes
- **Added lockfile update as a fix strategy**
- When a transitive dependency's parent uses a semver range that already
includes the fixed version, `pnpm update --recursive` is enough. No
`package.json` changes needed. The workflow now checks pinned vs ranged
before falling back to overrides.
- **Documented pnpm override syntax rules**
- Added guidance on using `^` ranges instead of `>=` (which can cross
major versions), single-level parent scoping limitations, unsupported
version selectors in keys, and risks of global overrides across multiple
major versions.
- **Added user confirmation step before applying fixes**
- The workflow now requires presenting a summary table of proposed fixes
and getting user confirmation before making changes. This prevents
wasted effort from incorrect fix strategies.
## Design Decisions
The fix priority order is now: direct bump > lockfile update > override.
The lockfile update step was added because several audit vulnerabilities
were resolvable without any `package.json` changes — the parent's semver
range already covered the fix, but the lockfile had a stale resolution.
Recognizing this case avoids unnecessary overrides that add long-term
maintenance burden.
The override syntax rules were added because pnpm's override behavior
has non-obvious edge cases (e.g., `>=` crossing majors, no nested
scoping) that caused issues in practice.
## Overall Flow
```mermaid
flowchart TD
A[Run audit script] --> B[Group by package]
B --> C[Trace dependency chain]
C --> D{Can bump direct dep?}
D -->|yes| E[Research breaking changes]
D -->|no| F{Pinned or ranged?}
E --> G{Breaking changes ok?}
G -->|yes| H[Apply direct bump]
G -->|no| F
F -->|ranged, fix in range| I[Lockfile update]
F -->|pinned| J[Apply pnpm override]
H --> K{More packages?}
I --> K
J --> K
K -->|yes| C
K -->|no| L[Present plan to user]
L --> M[Install and verify]
M --> N[Build and verify]
N --> O[Commit and create PR]
```
Copy file name to clipboardExpand all lines: .claude/skills/audit-dependencies/SKILL.md
+64-21Lines changed: 64 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,14 +3,14 @@ name: audit-dependencies
3
3
description: Use when fixing dependency vulnerabilities, running pnpm audit, or when the audit-dependencies CI check fails
4
4
user-invocable: true
5
5
disable-model-invocation: true
6
-
argument-hint: "critical|high|moderate|low"
6
+
argument-hint: 'critical|high|moderate|low'
7
7
---
8
8
9
9
# Audit Dependencies
10
10
11
11
## Overview
12
12
13
-
Fix dependency vulnerabilities reported by `.github/workflows/audit-dependencies.sh`. Always prefer direct dependency bumps over pnpm overrides. Every override requires justification for why a direct bump isn't feasible.
13
+
Fix dependency vulnerabilities reported by `.github/workflows/audit-dependencies.sh`. Prefer fixes in this order: direct dependency bump > lockfile update > pnpm override. Every override requires justification for why simpler approaches aren't feasible.
14
14
15
15
## Core Workflow
16
16
@@ -23,8 +23,11 @@ digraph audit {
23
23
"Research breaking changes" [shape=box];
24
24
"Breaking changes acceptable?" [shape=diamond];
25
25
"Apply direct bump" [shape=box];
26
+
"Is version pinned or ranged?" [shape=diamond];
27
+
"Lockfile update" [shape=box];
26
28
"Apply pnpm override" [shape=box];
27
29
"More packages?" [shape=diamond];
30
+
"Present plan to user" [shape=box];
28
31
"Install and verify" [shape=box];
29
32
"Build and verify" [shape=box];
30
33
"Commit and create PR" [shape=box];
@@ -33,14 +36,18 @@ digraph audit {
33
36
"Group by package" -> "Trace dependency chain";
34
37
"Trace dependency chain" -> "Can bump direct dep?";
35
38
"Can bump direct dep?" -> "Research breaking changes" [label="yes"];
"More packages?" -> "Install and verify" [label="no"];
49
+
"More packages?" -> "Present plan to user" [label="no"];
50
+
"Present plan to user" -> "Install and verify";
44
51
"Install and verify" -> "Build and verify";
45
52
"Build and verify" -> "Commit and create PR";
46
53
}
@@ -87,29 +94,59 @@ For transitive deps, walk up the chain to find the nearest package you control:
87
94
88
95
**Parallelize research**: When multiple packages need breaking change analysis, dispatch parallel agents (one per package) to research simultaneously.
89
96
97
+
#### Check if a lockfile update is sufficient
98
+
99
+
Before reaching for an override, check whether the parent's version specifier is **pinned** (exact version like `3.10.3`) or **ranged** (like `^2.3.1`, `~4.0.3`):
100
+
101
+
```bash
102
+
pnpm view <parent> dependencies.<vulnerable-pkg>
103
+
```
104
+
105
+
If the range already includes the fixed version, a lockfile update is all that's needed:
106
+
107
+
```bash
108
+
pnpm update <vulnerable-pkg> --recursive
109
+
```
110
+
111
+
No `package.json` changes required — the lockfile was just stale.
112
+
90
113
#### Fall back to override only when justified
91
114
92
-
Add a scoped pnpm override in root `package.json` only when:
115
+
Add a pnpm override in root `package.json` only when:
93
116
117
+
- The parent pins an exact version that doesn't satisfy the fix
94
118
- No version of the parent package fixes the vulnerability
95
119
- The parent bump has high breaking change risk (major API changes, no test coverage, requires code changes across many files)
96
120
- The user explicitly decides to defer the parent bump to a separate PR
- Use `^` ranges, not `>=`. `>=` can cross major versions and cause unexpected resolutions (e.g., `"picomatch": ">=2.3.2"` can resolve to 4.x).
127
+
- pnpm only supports single-level parent scoping: `"parent>pkg"` works, `"grandparent>parent>pkg"` does not.
128
+
- pnpm does not support version selectors in override keys: `"pkg@^2"` does not work.
129
+
- If the same vulnerable package appears through many transitive paths, a global override may be needed. Be careful that it doesn't affect unrelated consumers on a different major version — use parent-scoped overrides when the package spans multiple major versions across the tree.
130
+
- pnpm only honors `overrides` in the root workspace `package.json`. Overrides in workspace packages are ignored.
99
131
100
132
Before adding any override, verify the target version exists:
101
133
102
134
```bash
103
135
pnpm view <pkg>@<version> version
104
136
```
105
137
106
-
### 3. Apply Fixes
138
+
### 3. Present Plan to User
139
+
140
+
Before applying fixes, present a summary table to the user showing each vulnerability, the proposed fix strategy (direct bump / lockfile update / override), and justification. Get confirmation before proceeding.
141
+
142
+
### 4. Apply Fixes
107
143
108
144
- Edit `package.json` files for direct bumps
145
+
- Run `pnpm update <pkg> --recursive` for lockfile-only fixes
109
146
- Edit root `package.json``pnpm.overrides` for overrides (keep alphabetical)
110
147
- If a direct bump changes behavior, update consuming code (e.g., adding `allowOverwrite: true` when an API default changes)
111
148
112
-
### 4. Install and Verify
149
+
### 5. Install and Verify
113
150
114
151
```bash
115
152
pnpm install
@@ -129,7 +166,7 @@ Then re-run the audit script with the same severity:
129
166
130
167
The audit script must exit 0. If vulnerabilities remain, check for additional instances of the same dependency in other workspace packages.
131
168
132
-
### 5. Build and Verify
169
+
### 6. Build and Verify
133
170
134
171
```bash
135
172
pnpm run build:core
@@ -141,7 +178,7 @@ For packages with changed dependencies, also run their specific build:
141
178
pnpm run build:<package-name>
142
179
```
143
180
144
-
### 6. Look Up CVEs
181
+
### 7. Look Up CVEs
145
182
146
183
For each fixed vulnerability, find the GitHub Security Advisory (GHSA):
147
184
@@ -152,7 +189,7 @@ For each fixed vulnerability, find the GitHub Security Advisory (GHSA):
152
189
153
190
**Parallelize CVE lookups**: Dispatch parallel agents to search for CVEs across all packages simultaneously.
154
191
155
-
### 7. Commit and Create PR
192
+
### 8. Commit and Create PR
156
193
157
194
Commit with conventional commit format:
158
195
@@ -171,7 +208,7 @@ Create PR using `gh pr create` with this body structure:
| Jumping straight to overrides | Always check if bumping the parent resolves it first |
187
-
| Not checking all workspace packages | Same dep may appear in multiple `package.json` files (e.g., `changelogen` in both `tools/releaser` and `tools/scripts`) |
188
-
| Overriding with a nonexistent version | Verify the target version exists with `pnpm view` before installing |
189
-
| Not falling back to `--ignore-scripts`| Pre-existing native build failures block `pnpm install`; use `--ignore-scripts` to get lockfile updated |
190
-
| Missing code changes for breaking bumps | If a bump changes API defaults, update the calling code |
191
-
| Forgetting advisory links in PR | Always look up and include GHSA links for each vulnerability |
| Jumping straight to overrides | Check: can you bump the parent? If not, does the semver range already allow the fix (lockfile update)? Only then override. |
224
+
| Using `>=` in override ranges | Use `^` to stay within the same major version. `>=2.3.2` can resolve to 4.x. |
225
+
| Not checking pinned vs ranged |`pnpm view <parent> dependencies.<pkg>` — if ranged and the fix is in range, just `pnpm update`. |
226
+
| Nested override scoping (`a>b>c`) | pnpm only supports single-level: `"parent>pkg"`. For deeper chains, override the direct parent or use a global override. |
227
+
| Version selectors in override keys (`pkg@^2`) | Not supported by pnpm. Use parent-scoped or global overrides instead. |
228
+
| Global override affecting multiple major versions |`"picomatch": ">=4.0.4"` forces all picomatch to 4.x, breaking consumers that need 2.x. Scope overrides to the parent when a package spans multiple majors. |
229
+
| Not checking all workspace packages | Same dep may appear in multiple `package.json` files (e.g., `changelogen` in both `tools/releaser` and `tools/scripts`) |
230
+
| Overriding with a nonexistent version | Verify the target version exists with `pnpm view` before installing |
231
+
| Not falling back to `--ignore-scripts`| Pre-existing native build failures block `pnpm install`; use `--ignore-scripts` to get lockfile updated |
232
+
| Missing code changes for breaking bumps | If a bump changes API defaults, update the calling code |
233
+
| Forgetting advisory links in PR | Always look up and include GHSA links for each vulnerability |
234
+
| Applying fixes without user confirmation | Present the full plan (strategy per vuln + justification) and get confirmation before making changes |
0 commit comments