# Fix NPM Vulnerability

> Fix a pnpm/npm security advisory in a pnpm monorepo. First attempts to update the head dependency; falls back to a pnpm override with a tracking GitHub issue. Use when pnpm audit or Dependabot surfaces a vulnerability.

- Skill: `thunder-id/fix-npm-vulnerability` (Agent Skill)
- Install (CLI): `npx skillmds@latest add thunder-id/fix-npm-vulnerability`
- Raw SKILL.md: https://api.skillmd.com/api/skills/thunder-id/fix-npm-vulnerability/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: thunder-id (https://skillmd.com/u/thunder-id)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/thunder-id/fix-npm-vulnerability

---


# 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 the `pnpm audit` output 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:

```bash
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

```bash
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 flaw
- **`patchedVersions`** — the version range that fixes it (e.g. `>=4.0.6`)
- **`via`** — the dependency chain showing which head (direct workspace) dep pulls it in
- **`advisoryId`** — CVE or GHSA identifier
- **`severity`** — high / critical

---

## Step 3 — Traverse the dependency chain

Use `pnpm why` to confirm the full chain from the workspace to the vulnerable package:

```bash
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:

```bash
# 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:

```bash
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**:

```bash
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:

```bash
pnpm update <head-package>@latest
```

Verify the vulnerable package is now at the patched version:

```bash
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:`:

```yaml
  # 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:

```yaml
  <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`. Running `pnpm install` now will regenerate
> `pnpm-lock.yaml` to match — that can also shift unrelated transitive versions. Shall I proceed?

Wait for confirmation, then run:

```bash
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>`:

```bash
grep -rl '"<head-package>"' --include='package.json' . | grep -v node_modules
```

**Changelog / breaking changes** — fetch release notes:

```bash
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:

```bash
git remote get-url origin 2>/dev/null
```

```bash
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 `security` or `maintenance` labels don't exist in the repo, omit `--label` rather 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 run `pnpm install && pnpm audit --audit-level=high`"

