npm: Security, Auditing & Best Practices
npm audit
# Check for known vulnerabilities
npm audit # full report
npm audit --production # only production dependencies
npm audit --json # JSON output for CI parsing
npm audit --audit-level high # exit 1 only for high/critical
# Fix automatically (safe fixes — no semver range violations)
npm audit fix
# Fix including breaking changes (review carefully)
npm audit fix --force
# Ignore specific vulnerability in CI
# Add to package.json:
# "auditConfig": { "ignore": ["GHSA-xxxx-xxxx-xxxx"] }
# Or use: https://github.com/quinnluke/npm-audit-resolverSupply Chain Security
Typosquatting: npm install lodash (ok) vs npm install loadash (malicious). Always double-check package names.
Lock file poisoning: attacker modifies lock file in PRs. Review lock file diffs in code review.
Dependency confusion: internal package names can be hijacked on public registry. Use scoped packages (@myorg/...) and registry overrides.
Script injection: package install scripts (preinstall/postinstall) can run arbitrary code. Use --ignore-scripts when auditing.
Provenance: npm now supports provenance attestations — cryptographic proof of where a package was built.
Token Management
# Create tokens
npm token create # full publish token (avoid)
npm token create --read-only # install-only token
npm token create --cidr-whitelist=10.0.0.0/8 # IP restricted
# List tokens
npm token list
# Revoke a token
npm token revoke <token-id>
# Enable 2FA for publishing (strongly recommended)
npm profile enable-2fa auth-and-writes # require OTP for publish
npm profile enable-2fa auth-only # OTP for login only
# CI: use CIDR-restricted or granular access tokens, not your personal full token.npmrc Configuration
# Project-level .npmrc (commit this)
# Specify registry
registry=https://registry.npmjs.org/
# Use specific Node.js engine
engine-strict=true
# Don't run package install scripts (safer for CI)
ignore-scripts=false # set to true if you trust your deps
# Scoped package registry
@myorg:registry=https://registry.myorg.com/
//registry.myorg.com/:_authToken=${MY_REGISTRY_TOKEN}
# System-level ~/.npmrc (DON'T commit this — has tokens)
//registry.npmjs.org/:_authToken=npm_abc123...npm-check-updates
# Check what can be updated (doesn't modify anything)
npx npm-check-updates
# Update package.json with new ranges
npx npm-check-updates -u
# Update only minor/patch
npx npm-check-updates --target minor -u
# Exclude specific packages
npx npm-check-updates --reject react,typescript -u
# After updating package.json
npm install # installs new versions and updates lock fileWorkspaces (Monorepos)
// Root package.json
{
"name": "my-monorepo",
"private": true,
"workspaces": ["packages/*", "apps/*"]
}# Install all workspace dependencies
npm install
# Run script in specific workspace
npm run build --workspace packages/ui
npm run test --workspace apps/web
# Run script in all workspaces
npm run build --workspaces
# Add dependency to specific workspace
npm install lodash --workspace packages/utils
# Add dependency from one workspace to another
npm install @myorg/ui --workspace apps/webBest Practices
Always commit package-lock.json — reproducible builds are critical
Use npm ci in CI pipelines — faster, strict, never modifies lock file
Run npm audit in CI and fail builds on high/critical vulnerabilities
Enable 2FA on your npm account — supply chain attacks target maintainer accounts
Use scoped package names (@yourorg/pkg) — prevents dependency confusion attacks
Keep devDependencies separate from dependencies — don't bloat production installs
Review lock file diffs in PRs — large unexpected changes are a red flag
Set "engines" field — documents and optionally enforces Node.js version requirements
Use "files" whitelist in package.json — never accidentally publish .env or secrets
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free