Skip to main content

npm Security Checklist

This page is a practical distillation of the OWASP NPM Security Cheat Sheet, organized by workflow phase. For the why — attack vectors, incident history, and defense rationale — read npm Supply Chain Attacks first; this page is the what to do reference, with particular emphasis on publisher-side hygiene.

Before You Install — Vet the Package

Spend two minutes on the registry page before adding a dependency. Most recently compromised packages showed at least one red flag under cursory review.

Signals worth checking:

  • Weekly downloads — a package with thousands of downloads is not automatically safe, but one with a few hundred downloads and no recognizable consumers deserves scrutiny.
  • Last publish date — packages that haven't been updated in years may still be fine, but sudden activity after long dormancy is a known takeover pattern.
  • Maintainer count — single-maintainer packages are single points of failure.
  • Repository link — open it. Does the repo actually exist? Does the code match what's on npm? Watch for starjacking, where a package's repository field points at an unrelated popular repo to borrow its star count.
  • Dependency count — every transitive dependency is attack surface. Prefer lean packages.
  • OpenSSF Scorecard — rates the project's security practices (branch protection, signed releases, CI tests, etc.).
  • Socket report — analyzes actual package behavior (network calls, filesystem writes, install scripts) rather than just known CVEs.

Typosquatting (crossenv vs cross-env, electorn vs electron) is the most common way unvetted installs go wrong. See the attack-vector breakdown on the supply-chain page.

Consider npq as a drop-in wrapper for npm install — it prompts before installing with a risk summary (downloads, age, install scripts, known vulnerabilities).

tip

Copy install commands from the package's official documentation page, not from a search-engine snippet or a Stack Overflow answer. Typosquats rank in search results too.

When You Install — Lock It Down

These practices are covered in depth on the supply-chain page and listed here for checklist completeness:

  • Always commit package-lock.json and use npm ci in CI — deterministic installs that fail on drift. See Lock Files and npm ci.
  • Set ignore-scripts=true in .npmrc to neutralize preinstall, install, and postinstall — the most common payload location. See Ignore Install Scripts.
  • Publish internal packages under an npm scope (@yourorg/name) to prevent dependency-confusion attacks. See Scoped Packages.
  • Set min-release-age=7 in .npmrc to quarantine newly published versions for 7 days — blocks compromised packages before they reach your project. Requires npm 11+. See npm min-release-age.

Run a Local npm Proxy (For Teams)

A self-hosted registry proxy sits between your developers (and CI) and the public npm registry. Beyond security, it adds resilience:

  • Cache against upstream outages — builds don't break when npmjs.com is down or a package is unpublished (remember left-pad).
  • Allow-list enforcement — reject installs of packages not on your approved list.
  • Audit trail — record every package that has entered your build environment.
  • Private-package hosting — publish internal packages without exposing them publicly.
ToolNotes
VerdaccioLightweight, open source, easy to self-host. Good starting point.
Sonatype NexusEnterprise-grade, multi-format (npm, Maven, Docker, PyPI).
JFrog ArtifactoryEnterprise, strong policy/compliance tooling.
GitHub PackagesTight integration with GitHub Actions; npm-scope-based.

Keep Your Project Healthy

npm outdated

Lists dependencies that have newer versions available, grouped by how far behind each one is.

$ npm outdated
Package Current Wanted Latest Location
eslint 8.57.0 8.57.0 9.15.0 my-app
react 18.2.0 18.3.1 19.0.0 my-app

npm doctor

Runs a diagnostic on your npm installation, registry connectivity, cache integrity, and permissions. Useful as a sanity check when npm install behaves strangely.

npm audit and npm audit signatures

npm audit checks installed packages against the GitHub Advisory Database. npm audit signatures (npm v9.5+) verifies that packages were published through npm's signing pipeline. See npm audit for the caveats.

Automate updates

Use Dependabot or Renovate to receive automated update PRs. Outdated dependencies accumulate known vulnerabilities. See Security Tooling.

If You Publish Packages

The rest of this page covers publisher responsibilities — where most projects get the defaults subtly wrong.

Use a files allow-list (don't rely on .npmignore)

The files field in package.json is an allow-list: only the paths listed are included in the published tarball. This is the opposite of .npmignore, which is a deny-list — and deny-lists fail open. Miss a pattern and secrets leak.

package.json
{
"files": ["dist/", "README.md", "LICENSE"]
}
danger

Multiple real incidents have leaked AWS credentials, .env files, and entire .git/ directories to the public npm registry through a missing .npmignore entry. Once a version is published, assume it is compromised: rotate every credential that was in the tarball, publish a patch version, and — if needed — deprecate the leaked version. Unpublishing is restricted on npm and does not remove copies that have already been downloaded or mirrored.

Verify the contents of your tarball before publishing:

npm publish --dry-run
npm pack # creates the tarball locally; inspect with `tar tf <file>.tgz`

Never ship:

  • .env, .env.local, and any other .env* file
  • .git/
  • node_modules/
  • Test fixtures with real data
  • CI configuration (.github/, .circleci/, etc.) unless intentional
  • IDE settings (.vscode/, .idea/)
  • Build and debug logs

Protect .npmrc and CI secrets

Reference tokens through environment variables, never literal strings:

.npmrc
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
caution

Never commit a literal publish token, even temporarily. Git history is forever, and bots scan public repositories for npm tokens within seconds. If a token is ever exposed, revoke it immediately on the npm tokens page and rotate the secret in your CI.

Keep NPM_TOKEN in your CI provider's secret store (GitHub Actions secrets, GitLab CI variables, etc.) and inject it only into publish jobs.

Enable 2FA on your npm account

npm supports two 2FA modes:

  • auth-only — 2FA is required to log in and change account settings, but not to publish or modify packages.
  • auth-and-writes — 2FA is required for login and for every write action, including npm publish.

For any account that publishes packages used by others, use auth-and-writes. Prefer a WebAuthn security key (hardware token, Touch ID, platform authenticator) over TOTP apps — WebAuthn is phishing-resistant. npm now enforces 2FA for maintainers of high-impact packages, but you should enable it regardless of package size.

Use granular access tokens for automation

Classic npm tokens grant full account access. Granular access tokens let you scope what a token can do:

  • Limit to specific packages or organization scopes
  • Read-only vs read-and-publish
  • Expiration date (recommended: ≤ 90 days)
  • IP/CIDR allow-list

Use granular tokens for CI publishing, and rotate them on a schedule.

tip

Do a quarterly token audit: open npm account settings, revoke anything you don't recognize or no longer need, and shorten expiries where possible.

Review your own npm scripts in PRs

A single malicious pull request can add a postinstall script that later ships to every one of your users on the next publish. Treat changes to the scripts block of package.json — and to any file those scripts invoke — with the same scrutiny you'd apply to a Dockerfile or a GitHub Actions workflow change.

Publish with provenance

npm provenance (npm v9.5+) links each published version to the source commit and build workflow that produced it, signed through Sigstore. Consumers can verify provenance with npm audit signatures. See the Security Tooling table for details.

Responsible Disclosure

For your own packages

  • Publish a SECURITY.md with a private contact or link to GitHub Security Advisories.
  • Coordinate privately via a GitHub Security Advisory — collaborate on a fix in a private fork, request a CVE, and publish the advisory with the fix release.
  • Don't merge a public fix or push a descriptive commit message before the advisory is live.

For packages you depend on

  • Contact the maintainer privately first (check SECURITY.md, package.json, or npm).
  • Report outright malware via npm's reporting malware flow.
  • 90 days is a reasonable disclosure window before publishing details.
caution

Publicly filing a GitHub issue titled "RCE in some-package" with a working proof of concept is not responsible disclosure — it is a zero-day announcement. Give maintainers a chance to patch before you publish details.

Quick-Reference Checklist

Copy into your team's onboarding doc or PR template.

Before install

  • Checked weekly downloads, last publish, maintainer count, repo link
  • Inspected transitive dependency count
  • Reviewed OpenSSF Scorecard or Socket report for anything unusual
  • Copied the install command from official docs, not a search result

When installing

  • package-lock.json is committed
  • CI uses npm ci, not npm install
  • ignore-scripts=true in .npmrc (or install scripts reviewed for exceptions)
  • min-release-age=7 in .npmrc (npm 11+) — quarantine window for new releases
  • Internal packages are published under an npm scope

Ongoing

  • npm audit runs in CI
  • Dependabot or Renovate is configured
  • npm outdated reviewed at least monthly
  • Unused dependencies removed (npx depcheck)

If publishing

  • files allow-list in package.json
  • npm publish --dry-run inspected before release
  • No literal tokens in .npmrc; NPM_TOKEN lives in CI secrets
  • 2FA is auth-and-writes with a WebAuthn key
  • CI uses a granular access token with expiry and package scope
  • Provenance enabled on publish workflow

Disclosure

  • SECURITY.md published with a private contact
  • Private coordination via GitHub Security Advisory, not public issues

Further Reading