Overview

Dependency audits match your resolved versions against advisory databases. Run one before every deploy and on a schedule, because new advisories appear for versions you already ship. This guide covers npm, pnpm, and pip, triages findings by whether they are reachable in production, and adds CI jobs. Deeper Python hardening: python-security.

Prerequisites

  • A lockfile: package-lock.json, pnpm-lock.yaml, or a pinned requirements.txt. npm refuses to audit without one unless you pass --no-package-lock, which makes results vary between runs.
  • Write access to open a fix PR.

Steps

1. Run the audit

npm audit                       # human-readable
npm audit --omit=dev            # production dependencies only
npm audit --json > audit.json
pnpm audit --prod               # pnpm; --dev for dev dependencies only
pip install pip-audit && pip-audit -r requirements.txt

npm and pnpm report severity (low, moderate, high, critical). pip-audit reports vulnerability IDs and fix versions but no severity score, and it has no --fail-on option; it exits 1 when it finds anything. For Poetry, export first: poetry export -f requirements.txt --without-hashes -o requirements.txt.

2. Triage

FindingAction
Critical or high, reachable in productionFix before the next deploy
Moderate in a direct dependencyFix this sprint
Deep transitive, or dev-only tooling that never runs in productionSchedule; accept with a written reason
LowBatch with routine upgrades

Read the advisory: whether the vulnerable function is called decides priority more than the label does.

3. Fix

npm audit fix                   # semver-compatible updates
npm audit fix --force           # allows major bumps; review the lockfile diff first
pnpm audit --fix                # adds overrides to pnpm-workspace.yaml
pnpm audit --fix=update         # updates the lockfile instead
pip-audit -r requirements.txt --fix

Package-manager notes: pnpm 11 and later read settings such as overrides from pnpm-workspace.yaml, not the pnpm field of package.json, and delay installing versions published in the last 24 hours by default (minimumReleaseAge), which can hide a just-released fix.

4. Override a stuck transitive dependency

When the fix exists upstream but your parent package has not adopted it:

{ "overrides": { "vulnerable-package": ">=2.1.0" } }

In npm this goes in package.json; in pnpm 11+, under overrides: in pnpm-workspace.yaml. Override only to a drop-in compatible version, test the result, and add a comment saying why. Re-run the audit afterwards, since an override can pull in a different advisory.

5. Re-test

An upgrade that clears the audit can still break the app. Run the full suite (npm test or pytest -x) before merging.

6. Gate pull requests and run weekly

# .github/workflows/audit.yml
name: Dependency audit
on:
  pull_request:
  schedule: [{ cron: "0 8 * * 1" }]   # Mondays 08:00 UTC
jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with: { node-version: 22 }
      - run: npm ci
      - run: npm audit --audit-level=high

For Python, replace the last three steps with pip install pip-audit and pip-audit -r requirements.txt, or use the pypa/gh-action-pip-audit action. To ignore a reviewed advisory in pip-audit, pass --ignore-vuln <ID>; in pnpm, --ignore <GHSA-id>.

Verify it worked

npm audit --audit-level=high; echo "exit=$?"     # 0: nothing at high or above
pip-audit -r requirements.txt; echo "exit=$?"    # 0: no known vulnerabilities

Common errors

  • Dev-only noise. Audit production separately with --omit=dev and use a lower bar for dev dependencies.
  • npm audit fix leaves findings. The fix needs a major bump or the parent has not updated; use --force after review, or an override.
  • Audit is clean locally but red in CI. CI installs from the lockfile; commit the updated lockfile.
  • pip-audit cannot resolve a package. It was yanked or renamed on PyPI; pin the previous release or replace the dependency.
  • Registry errors on locked-down networks. Allow the registry’s advisory endpoint, or the job fails for network reasons rather than findings.

FAQ

Does pip-audit have a severity threshold like npm audit?

No. pip-audit reports vulnerability IDs and fix versions but no severity score and has no --fail-on option; it exits 1 whenever it finds anything.

Do I have to fix every vulnerability npm audit reports?

No. Fix critical or high findings reachable in production before the next deploy and moderate ones in direct dependencies this sprint; schedule or accept deep transitive and dev-only findings with a written reason.

Is it safe to run npm audit fix —force?

Only after review. It allows major version bumps, so read the lockfile diff and run the full test suite before merging.

How do I patch a vulnerable transitive dependency the parent has not updated?

Add an overrides entry pinning it to a drop-in compatible fixed version, in package.json for npm or pnpm-workspace.yaml for pnpm 11 and later, then test and re-run the audit.

Why does pnpm not install a security fix that was just released?

pnpm 11 and later delay installing versions published in the last 24 hours by default (minimumReleaseAge), which can hide a just-released fix.