Required Reading
~5 min

Incident Playbooks

Step‑by‑step actions for common npm threat scenarios.

Postinstall downloads a binary

CRITICAL
  1. Block PR/update. Capture the tarball and diff recent versions.
    Stops propagation while you verify what changed and whether payload is legitimate.
  2. Verify host: must be trusted GitHub Releases/CDN. If unknown, treat as malicious.
    Attackers commonly host payloads on throwaway domains to avoid scrutiny.
  3. Look for obfuscation and child_process launches. Remove the dependency if non‑essential.
    Hidden behavior plus shell execution is a strong indicator of malware.
  4. Quarantine build containers; rotate tokens if any env secrets were accessible.
    If the payload ran, credentials may be compromised; rotate to be safe.

Prevent this from recurring

  • Default CI to npm ci --ignore-scripts; allowlist only packages with a documented, legitimate reason to run lifecycle scripts.
  • Require checksum or signature verification for any binary a lifecycle script downloads.
  • Restrict install-time egress to the registry and trusted GitHub Releases/CDN hosts.

Suspected typosquat

HIGH
  1. Check maintainers and repo; confirm legitimate lineage.
    Typosquats often have unknown maintainers or no real upstream project.
  2. Inspect README and code size; tiny or empty repos are red flags.
    Malicious packages minimize content and hide behavior in postinstall.
  3. Replace with the intended package; add allow‑lists to prevent recurrence.
    Prevents future accidents in CI and developer machines.

Prevent this from recurring

  • Pin dependencies by exact version in lockfiles and review new dependency additions during PR review, not just at install time.
  • Run new/unfamiliar package names through search_packages' possibleTyposquatOf check before adding them.
  • Have engineers copy package names from npmjs.com search results rather than typing from memory or a chat message.

Supply‑chain compromise

CRITICAL
  1. Pin to last known‑good version; block auto‑upgrades.
    Freezes to a safe state while investigation proceeds.
  2. Audit changes in the compromised release: look for obfuscation, network I/O, or env access.
    These are common attacker behaviors in compromised releases.
  3. Run builds with --network=none and scrubbed HOME until confidence restored.
    Limits blast radius and stops exfil while you assess.
  4. Monitor maintainer activity; require two‑person review for re‑adoption.
    Adds friction and oversight for future releases.

Prevent this from recurring

  • Require --provenance and two-person review before adopting the first re-published version after any ownership or maintainer change.
  • Run first-adoption builds in a container with --network=none and a scrubbed HOME until confidence is restored.
  • Subscribe to GitHub Security Advisories (or npmscan's get_latest_advisories) for every direct and transitive dependency, not just at upgrade time.

child_process in install scripts

HIGH
  1. Assume high risk. Identify exact command and purpose.
    Shell commands during install can touch filesystem, network, and secrets.
  2. If purely build‑related and host chain is trusted, isolate and whitelist.
    Some native builds need compilers; whitelist only after verification.
  3. Otherwise, remove or replace the dependency; report to registry/security teams.
    Prevents propagation and helps the ecosystem respond quickly.

Prevent this from recurring

  • Default npm_config_ignore_scripts=true in CI; allowlist specific packages with a documented native-build reason.
  • Block outbound network access during install (--network=none) so a shell-piped download can't complete even if a script runs.
  • Alert on any new child_process/exec/spawn usage a dependency bump introduces, not just at first install.

Unexpected network activity during install

MODERATE
  1. Capture logs; identify which package initiates outbound connections.
    Pinpoints the source for targeted mitigation.
  2. Run with --network=none; confirm build still succeeds.
    Proves whether network access is truly required.
  3. Allowlist domains if needed and verify checksums/signatures.
    Minimizes exposure when network dependency is legitimate.

Prevent this from recurring

  • Run installs with --network=none in CI to prove which dependencies actually require network access.
  • Allowlist only the registry and known trusted hosts for install-time egress; alert on anything else.
  • Treat a newly introduced network call in a lifecycle script (see diff_dependencies' installScriptIntroduced) as a blocking review item, not routine.

Maintainer change flagged

HIGH
  1. Freeze to last known‑good version; audit diffs of latest release.
    Stabilizes while you verify new ownership.
  2. Check repo activity and communication; look for transparency.
    Legitimate handovers are usually documented.
  3. Require two‑person review for first re‑adopted versions.
    Adds oversight during the riskiest period.

Prevent this from recurring

  • Alert on any maintainer-list change or repository transfer/archival for production dependencies, not just at upgrade time.
  • Require two-person review for the first version published under a changed maintainer list.
  • Prefer packages published via npm trusted publishing (OIDC) over long-lived personal publish tokens where the option exists.

Publish‑provenance mismatch

HIGH
  1. Freeze to the last version whose provenance/source‑diff came back clean.
    A mismatched build attestation or an install script/dependency absent from source is the signature of a stolen‑token publish that bypassed CI.
  2. Diff the flagged version's install scripts and dependencies against the git source at the attested commit yourself.
    Confirms exactly what was added outside the normal release process before deciding how far the compromise reaches.
  3. Rotate the npm publish token and any CI secrets with access to it for this package.
    A bypassed‑CI publish means the legitimate publish credential itself may be compromised, not just the install-time environment.
  4. Require --provenance and a second maintainer's review before trusting a new release from this package again.
    Adds a verifiable build trail and oversight so the same bypass can't recur silently.

Prevent this from recurring

  • Prefer dependencies published with --provenance, and treat a package missing it while its scope/maintainer peers consistently have it as worth checking.
  • Verify the attested source commit/repository matches package.json's declared repository before trusting a new release.
  • Rotate npm publish tokens on a schedule and scope them to trusted CI environments only, not long-lived personal tokens.