Fix npm Vulnerability
You are resolving a security advisory in a pnpm monorepo.
Step 0 — Gather the advisory details
Ask the user for one or both of:
What vulnerability do you want to fix? Provide a CVE ID (e.g.
CVE-2026-44705), GHSA slug (e.g.GHSA-w7jw-789q-3m8p), or vulnerable package name. Optionally paste thepnpm auditoutput line for it.
Wait for the answer before proceeding.
Step 1 — Locate the workspace root
Find the directory containing pnpm-workspace.yaml, starting from the current directory and walking up:
dir=$(pwd); while [ "$dir" != "/" ]; do [ -f "$dir/pnpm-workspace.yaml" ] && echo "$dir" && break; dir=$(dirname "$dir"); done
If nothing is found, ask the user to navigate to the monorepo root first.
All subsequent commands run from this root.
Step 2 — Get the full audit picture
pnpm audit --json 2>/dev/null | jq '.advisories // .vulnerabilities // .' 2>/dev/null | head -400
Identify for each advisory matching the user's input:
vulnerablePackage— the transitive package that contains the flawpatchedVersions— the version range that fixes it (e.g.>=4.0.6)via— the dependency chain showing which head (direct workspace) dep pulls it inadvisoryId— CVE or GHSA identifierseverity— high / critical
Step 3 — Traverse the dependency chain
Use pnpm why to confirm the full chain from the workspace to the vulnerable package:
pnpm why <vulnerable-package> 2>&1 | head -60
This shows every head dep that transitively depends on it. Record:
- The head package(s) (direct workspace deps) pulling in the vulnerable version
- The current version of those head packages
Step 4 — Check if updating the head dep resolves the issue
For each head package, inspect what version of the vulnerable package its latest release ships:
# Latest available version of the head dep
npm info <head-package> version
# Its full dependency tree for the vulnerable package
npm info <head-package>@latest dependencies --json 2>/dev/null | jq '.<vulnerable-package> // "not direct"'
# If it's deeper, check peer dependencies too
npm info <head-package>@latest peerDependencies --json
For transitive chains deeper than one level, check the registry manifest:
npm pack <head-package>@latest --dry-run --json 2>/dev/null | head -50
Decision:
A. If the latest <head-package> ships <vulnerable-package> at a version satisfying <patchedVersions>:
→ The update resolves the issue. Continue to Step 5a.
B. If the latest <head-package> still ships the vulnerable version (fix not yet released upstream):
→ An override is required. Continue to Step 5b.
Step 5a — Update the head dependency
Check whether this is a major version bump:
current=$(node -p "require('./node_modules/<head-package>/package.json').version" 2>/dev/null)
latest=$(npm info <head-package> version)
echo "current=$current latest=$latest"
If it IS a major bump, before touching any files, generate testing guidance (Step 6) and show it to the user. Ask:
This is a major version upgrade for
<head-package>(<current>→<latest>). I've listed the affected workspaces and test commands above. Shall I proceed with the upgrade?
Wait for confirmation.
Update the dep:
pnpm update <head-package>@latest
Verify the vulnerable package is now at the patched version:
pnpm why <vulnerable-package> 2>&1 | grep -E "version|<vulnerable-package>"
pnpm audit --audit-level=high 2>&1 | grep -c "high\|critical" && echo "ISSUES REMAIN" || echo "CLEAN"
If clean, skip Steps 5b, 7, and 8. Report the upgrade (and testing checklist if it was a major bump).
Step 5b — Add the pnpm override
First create the GitHub issue (Step 7) so you have the URL to embed in the comment.
Then open pnpm-workspace.yaml and add under overrides::
# JUSTIFICATION: Fixes <CVE/GHSA-slug> — <one-line description of the flaw>.
# Added <YYYY-MM-DD>. Remove once <head-dep> ships a release containing <vulnerable-package>@<patchedVersions>.
# Tracking: <github-issue-url>
<vulnerable-package>: '<patchedVersion>'
Use scoped syntax when the vulnerability is only reachable through one specific head dep:
<head-package>><vulnerable-package>: '<patchedVersion>'
Match the comment and formatting style of existing entries in the file.
The override needs pnpm install to take effect in the lockfile — that regenerates resolutions
for the whole tree, not just the pinned package, so it can pull in unrelated drift (a transitive
dep bumping a patch version elsewhere). Ask before running it:
I've added the override to
pnpm-workspace.yaml. Runningpnpm installnow will regeneratepnpm-lock.yamlto match — that can also shift unrelated transitive versions. Shall I proceed?
Wait for confirmation, then run:
pnpm install
pnpm audit --audit-level=high 2>&1 | grep -c "high\|critical" && echo "ISSUES REMAIN" || echo "CLEAN"
Make sure pnpm-lock.yaml ends up staged/committed together with the pnpm-workspace.yaml edit —
don't leave the lockfile change uncommitted for a later, unrelated commit to pick up.
Step 6 — Testing guidance (major version bumps only)
When the head dep crosses a major version, output a checklist before applying the change.
Affected workspaces — every workspace that depends on <head-package>:
grep -rl '"<head-package>"' --include='package.json' . | grep -v node_modules
Changelog / breaking changes — fetch release notes:
npm info <head-package>@latest 2>/dev/null | grep -A5 "homepage\|repository"
Then WebSearch for "<head-package> v<major> migration guide" or its changelog.
Test commands to run after the upgrade:
- For each affected workspace:
pnpm --filter <workspace> test - If the workspace has a dev server:
pnpm --filter <workspace> dev— note which URLs or UI flows exercise this package - Run the full audit:
pnpm audit --audit-level=high
Present this as a numbered checklist the developer can follow manually after the PR lands.
Step 7 — Create the tracking GitHub issue (override path only)
Detect the remote:
git remote get-url origin 2>/dev/null
gh issue create \
--title "[Dependency Management 🔒] Remove Pnpm Override for <vulnerable-package> Once <head-dep> Ships the Fix" \
--label "security,maintenance" \
--body "$(cat <<'EOF'
## Tracking Override Added on <YYYY-MM-DD>
| Field | Value |
|---|---|
| Advisory | <CVE/GHSA-slug> |
| Vulnerable package | `<vulnerable-package>` |
| Fix requires | `<vulnerable-package>@<patchedVersions>` |
| Blocked by | `<head-dep>` — fix not yet released upstream |
| Override location | `pnpm-workspace.yaml` |
## How to Remove
Once `<head-dep>` publishes a release that includes `<vulnerable-package>@<patchedVersions>`:
1. Delete the override line from `pnpm-workspace.yaml`
2. Run `pnpm install`
3. Run `pnpm audit --audit-level=high` to confirm it is clean
EOF
)"
Capture the returned issue URL. Use it in the # Tracking: comment in Step 5b.
If
securityormaintenancelabels don't exist in the repo, omit--labelrather than failing.
Step 8 — Final report
If upgraded:
- Package upgraded and the fix confirmed clean
- Testing checklist (if major bump)
If overridden:
- Exact lines added to
pnpm-workspace.yaml - GitHub issue URL
- When to revisit: "Once
<head-dep>releases with<vulnerable-package>@<patchedVersions>, delete the override line and runpnpm install && pnpm audit --audit-level=high"