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 pinnedrequirements.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.txtnpm 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
| Finding | Action |
|---|---|
| Critical or high, reachable in production | Fix before the next deploy |
| Moderate in a direct dependency | Fix this sprint |
| Deep transitive, or dev-only tooling that never runs in production | Schedule; accept with a written reason |
| Low | Batch 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 --fixPackage-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=highFor 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 vulnerabilitiesCommon errors
- Dev-only noise. Audit production separately with
--omit=devand use a lower bar for dev dependencies. npm audit fixleaves findings. The fix needs a major bump or the parent has not updated; use--forceafter review, or an override.- Audit is clean locally but red in CI. CI installs from the lockfile; commit the updated lockfile.
pip-auditcannot 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.