Scope: any time ~/.npmrc, a NPM_TOKEN env var, or a CI npm token was readable by malware.

Authoritative references

Do this first (60 seconds)

Open npmjs.com/settings/tokens and click Delete on every token. All of them. Even ones you think you need.

This stops an attacker from publishing malicious versions of your packages — the exact pattern of Shai-Hulud and the qix compromise.

Triage

What could the attacker do?

With a valid npm publish token:

  • Publish new versions of every package you maintain with a payload. ← How Shai-Hulud spread.
  • Read your private packages (if the token has read access).
  • Add themselves as a maintainer on packages (if the token is classic / not granular).

Find every place the token lives

# User-level
cat ~/.npmrc

# Project-level
find . -name ".npmrc" -not -path "*/node_modules/*"

# Env vars in shell rc files
grep -E "NPM_TOKEN|npm_token" ~/.zshrc ~/.bashrc ~/.profile ~/.envrc 2>/dev/null

# CI/CD secrets
gh secret list -R YOUR_OWNER/YOUR_REPO

Rotate

  1. Delete every token at npmjs.com/settings/tokens.
  2. Enable hardware 2FA: npm profile enable-2fa auth-and-writes.
  3. Switch to granular tokens. Classic tokens have broad scope; granular tokens (npm 2024+) scope to specific packages and have expirations.
  4. For CI: migrate to npm Trusted Publishing. GitHub Actions / GitLab CI publish via OIDC — no token in secrets, ever. Requires npm CLI ≥11.5.1. How to migrate (Phil Nash).
  5. Replace tokens in .npmrc files, then chmod 600 ~/.npmrc.

Verify nothing was published in your name

# What did you publish recently?
npm whoami
npm access list packages

# For any package you maintain, check recent versions
npm view <pkg> time --json | jq 'to_entries | sort_by(.value) | reverse | .[:5]'

# Also check npm's GHSA feed for advisories naming you
gh api '/advisories?ecosystem=npm&per_page=20' --jq '.[] | select(.identifiers[]?.value | test("YOUR_PACKAGE"))'

If there's a version you didn't publish:

  1. Deprecate it immediately: npm deprecate <pkg>@<version> "compromised, do not use".
  2. Contact npm security: security@npmjs.com. Provide token leak details so they can unpublish.
  3. Open a security advisory on your GitHub repo so downstream users find it. (GitHub Docs — Repository security advisories)
  4. Publish a clean version with a bumped patch, plus a SECURITY.md note.
  5. Add the incident to advisories/ (PR welcome).

Prevention going forward