Dependency Audit
Periodically inventory every dependency: what's used, what's unused, what's risky, what's outdated.
Why
Your dependency tree is a liability surface you didn't write — every package is code that runs with your privileges, maintained by someone you don't know, with bugs you can't see. An audit converts this opaque blob into a managed inventory: you learn you have 1200 transitive deps (not 40), that 3 are unmaintained, that 1 has a known CVE, that 12 are unused. Without periodic audits, node_modules grows monotonically — each addition is a one-way ratchet that's never removed, and the attack surface only grows. Audits are how you shrink it back.
When
Quarterly at minimum. Immediately when a high-severity CVE is announced in any dependency.
How
1. Generate the full tree: npm ls --all (or pnpm why) — capture direct + transitive counts 2. Find unused: npx depcheck (or knip) — lists deps in package.json but never imported 3. Find outdated: npm outdated — shows current vs wanted vs latest per package 4. Find vulnerabilities: npm audit (or pnpm audit, or Snyk/OSV-Scanner) 5. Find license issues: license-checker --production — flag GPL/incompatible licenses 6. Triage: remove unused, upgrade outdated with CVEs, file tickets for risky-but-needed 7. Record the audit in DEPS_AUDIT.md with date, counts, and actions taken
Example
# Full audit in one script npm ls --all > deps-tree.txt npx depcheck --json > unused.json npm outdated > outdated.txt npm audit --json > audit.json npx license-checker --production --json > licenses.json # Knip (finds unused files, exports, AND deps) npx knip --include dependencies # OSV-Scanner (Google's vuln DB, covers npm + pip + cargo) npx @google/osv-scanner --lockfile package-lock.json # Triage output: # - 12 unused deps -> remove from package.json # - 3 high CVEs -> upgrade immediately # - 2 GPL licenses -> legal review (or replace with MIT alt)
Common Problems
- ⚠Auditing only direct deps and ignoring the 1000+ transitive ones — that's where the CVEs and supply-chain attacks live.
- ⚠Running npm audit once and ignoring the 47 low-severity findings — they compound, and a future minor turns one into critical.
- ⚠Removing a dep that depcheck flagged as unused, but it's a peer dep or dynamically imported — production breaks.
Best Practices
- ✓Automate the audit in CI on every PR and fail on high/critical CVEs — don't wait for a quarterly manual run.
- ✓Use knip instead of depcheck — it understands dynamic imports, peer deps, and type-only imports, so fewer false positives.
- ✓Record every audit in DEPS_AUDIT.md so you can see the trend: is node_modules growing or shrinking quarter over quarter?