What Is npm audit? Dependency Security for AI Coders

When AI adds npm packages to your project, it's also adding their dependencies' dependencies. Any of those could have a known security vulnerability. npm audit is how you find out — and what to do about it.

TL;DR

npm audit scans your project's packages for known security vulnerabilities. Run it after AI adds any package to your project. It outputs a table showing vulnerable packages, severity (low/moderate/high/critical), and fix instructions. Fix critical and high severity issues in production dependencies immediately. Low/moderate in dev-only packages can wait. Add npm audit --audit-level=high to your CI/CD pipeline to block deployments when critical issues exist.

Why AI Coders Need to Run npm audit

When you ask AI to "add authentication" or "set up file uploads," it installs npm packages. Each package can have dozens of sub-dependencies. Any of these could have a known security vulnerability (CVE — Common Vulnerabilities and Exposures).

AI doesn't check for vulnerabilities before recommending packages. It suggests the most commonly-used solution, which is usually correct — but "commonly used" and "currently secure" aren't the same thing.

High-profile supply chain incidents show this isn't theoretical. Packages used by millions of developers have been compromised, updated to contain malicious code, or found to have serious CVEs. npm audit is your first line of defense.

Running npm audit

# Run from your project directory (where package.json is)
npm audit

# Example output:
# found 3 vulnerabilities (1 moderate, 2 high)
#
# ┌─────────────────────────────────────────────────────────────────┐
# │                          === npm audit ===                      │
# │                    === npm audit security report ===            │
# └─────────────────────────────────────────────────────────────────┘
#
# High            Prototype Pollution
# Package         lodash
# Patched in      >=4.17.21
# Dependency of   my-lib
# Path            my-app > my-lib > lodash
# More info       https://npmjs.com/advisories/1523
#
# High            Regular Expression Denial of Service
# Package         minimatch
# Patched in      >=3.0.5
# Dependency of   glob
# Path            my-app > glob > minimatch
# More info       https://npmjs.com/advisories/1564
#
# Moderate        Inefficient Regular Expression Complexity
# Package         semver
# Patched in      >=7.5.2
# Dependency of   node-semver
# Path            my-app > node-semver > semver
# More info       https://npmjs.com/advisories/1694
#
# 3 vulnerabilities found
# Run `npm audit fix` to fix them, or `npm audit fix --force` if updates are
# breaking changes

Reading the Output

Severity Levels

LevelMeaningAction
CriticalRemote code execution, auth bypass — can completely compromise your appFix immediately, before next deployment
HighData exposure, significant security impactFix within days
ModerateLimited impact, usually requires specific conditionsFix in next sprint/cycle
LowMinimal impact, often theoreticalFix when convenient, or acknowledge

The Dependency Path

# This tells you HOW you're using the vulnerable package:
# Path: my-app > my-lib > lodash

# my-app installed my-lib (a direct dependency)
# my-lib uses lodash internally (a transitive dependency)
# lodash has the vulnerability

# You didn't install lodash directly — my-lib brought it in.
# The fix: update my-lib to a version that uses a safe lodash version.

Fixing Vulnerabilities

# Fix automatically (only applies safe, backward-compatible updates):
npm audit fix

# Fix with breaking changes allowed (updates major versions):
npm audit fix --force
# ⚠️ --force can break your app. Review changes with git diff before committing.

# See what would change without applying it:
npm audit fix --dry-run

# Ignore a specific advisory (if you've evaluated it and it's not exploitable):
npm audit --ignore=1523

# Get JSON output for scripts/CI:
npm audit --json

Context Matters: Not All Vulnerabilities Are Equal

devDependencies vs. dependencies

// package.json

{
  "dependencies": {
    "express": "^4.18.2",  // Used in PRODUCTION — vulnerabilities here matter
    "lodash": "^4.17.21"   // Used in PRODUCTION — vulnerabilities here matter
  },
  "devDependencies": {
    "jest": "^29.0.0",     // Only used during development/testing
    "eslint": "^8.0.0",    // Only used locally — can't be exploited by users
    "webpack": "^5.0.0"    // Build tool — never runs in production
  }
}

# Vulnerabilities in devDependencies cannot be exploited by your app's users
# They're still worth fixing, but not emergency-level

Exploitability Depends on Usage

A vulnerability in lodash.merge() that enables prototype pollution only matters if your code uses lodash.merge() with user-controlled data. If you use lodash only for _.chunk() and _.uniq(), the vulnerability may not be exploitable in your specific context.

npm audit flags the package — it can't know how you use it. You need to evaluate whether your actual usage triggers the vulnerable code path.

Adding npm audit to CI/CD

# .github/workflows/security.yml
name: Security Audit

on: [push, pull_request]

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'

      - run: npm ci

      # Fail the build only if high or critical vulnerabilities exist in production deps
      - run: npm audit --audit-level=high --omit=dev
      # --omit=dev skips devDependencies (which can't be exploited by users)
      # --audit-level=high fails on high or critical only (ignores moderate/low)

AI-Specific Risk: Package Suggestions

AI tools have training data cutoffs. A package that was the best choice in 2023 might have a known CVE discovered in 2025. AI doesn't know this. Always:

  • Run npm audit after AI adds any new package
  • Check the package's npm page for download count and last publish date
  • Prefer packages with active maintenance (recent commits, timely CVE responses)
  • Prefer fewer, well-established packages over many niche ones
  • Be skeptical when AI suggests packages you've never heard of

What to Learn Next

Frequently Asked Questions

What does npm audit do?

npm audit checks all packages in your project (including their transitive dependencies) against a database of known security vulnerabilities. It reports which packages have vulnerabilities, how severe they are (low/moderate/high/critical), the dependency path showing how the vulnerable package entered your project, and often suggests a fix command.

Should I always run npm audit fix?

Not automatically. npm audit fix only applies safe, non-breaking updates — run this freely. npm audit fix --force applies breaking changes that may change APIs your code depends on — always review with --dry-run first, then test thoroughly after. In CI/CD, use npm audit --audit-level=high to fail builds only on serious issues.

Are all npm audit vulnerabilities dangerous?

No — context matters. A vulnerability in a devDependency (build tools, test runners) can't be exploited by your app's users. A vulnerability in a package that processes user input server-side is critical. Focus on high/critical vulnerabilities in production dependencies. Evaluate whether your actual usage triggers the vulnerable code path before panicking about moderate/low issues.

What is a supply chain attack?

A supply chain attack happens when malicious code is injected into a legitimate package you depend on — by compromising the package author's account, publishing a typosquatted package (similar name), or through a dependency chain. npm audit only catches known CVEs; it won't detect brand-new malicious packages. Minimize dependency count and prefer actively-maintained, well-known packages.

How often should I run npm audit?

Run npm audit after every npm install (especially when AI adds new packages), in your CI/CD pipeline on every build, and manually at least monthly on active projects. New CVEs are published constantly for existing packages — something safe last month may have a critical vulnerability reported today.