security2025-05-25·8·54/348

npm audit 취약점 수정 방법

How to use npm audit to find and fix security vulnerabilities in your Node.js project dependencies.

npm audit 취약점 수정 방법

Introduction

Security vulnerabilities in npm packages are discovered daily. The npm audit command is your first line of defense, but understanding its output and choosing the right fix strategy requires experience. In this post, I will walk through the complete audit workflow.

Environment

node --version
# v20.11.0

npm --version
# 10.2.4

npm audit --version
# (built-in)

Problem

Running npm audit on a typical project reveals numerous vulnerabilities:

npm audit

# found 247 vulnerabilities (142 low, 58 moderate, 34 high, 13 critical)

The detailed output shows issues like:

# npm audit report

lodash  <=4.17.20
Severity: critical
Prototype Pollution in lodash
https://github.com/advisories/GHSA-jf85-cpcp-j695

xml2js  <0.5.0
Severity: high
xml2js Prototype Pollution Vulnerability
https://github.com/advisories/GHSA-776f-mx2g-3qc2

express  <4.19.2
Severity: moderate
Open Redirect in express
https://github.com/advisories/GHSA-rv95-896h-c2v1

The challenge is that many vulnerabilities come from deep transitive dependencies, and simply running npm audit fix does not resolve all of them.

Analysis

Understanding the severity levels is critical:

critical: Remote code execution, complete system compromise
high: Data exposure, authentication bypass
moderate: Denial of service, limited data exposure
low: Information disclosure, minor issues

Here is how to interpret the dependency tree:

my-app@1.0.0
├─┬ express@4.18.0
│ └─┬ send@0.18.0
│   └── mime@2.6.0 (vulnerable)
└─┬ axios@0.27.0
  └─┬ follow-redirects@1.15.0
    └── debug@4.3.0 (vulnerable)

The vulnerability might be in a package three levels deep, which makes direct fixes difficult.

Solution

Step 1: Run a full audit

npm audit

Step 2: Try automatic fixes first

npm audit fix

This fixes vulnerabilities that can be resolved by updating to a patched version within the semver range.

Step 3: Use --force for breaking changes

npm audit fix --force

Warning: This may update packages to new major versions that have breaking changes.

Step 4: Review remaining vulnerabilities

npm audit --json > audit-report.json
// analyze-audit.js
const report = require('./audit-report.json');

const critical = report.vulnerabilities
  ? Object.values(report.vulnerabilities)
      .filter(v => v.severity === 'critical')
  : [];

console.log('Critical vulnerabilities:', critical.length);
critical.forEach(v => {
  console.log(`  - ${v.name}: ${v.via.map(i => i.title || i).join(', ')}`);
});

Step 5: Manual fixes for deep vulnerabilities

# Check what depends on the vulnerable package
npm ls lodash

# Find the package that brings in the vulnerability
npm ls --all | grep lodash
// package.json - use overrides for deep dependencies
{
  "overrides": {
    "lodash": "^4.17.21",
    "debug": "^4.3.4"
  }
}

Step 6: Generate an audit report for compliance

# Human-readable report
npm audit > AUDIT_REPORT.md

# Machine-readable report
npm audit --json > audit-report.json

# Open the audit dashboard
npm audit --json | node -e "
  const data = JSON.parse(require('fs').readFileSync(0, 'utf8'));
  console.log('Total vulnerabilities:', data.metadata?.vulnerabilities || 'N/A');
  console.log(JSON.stringify(data.metadata, null, 2));
"

Step 7: Add 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: '20'
      - run: npm ci
      - run: npm audit --audit-level=high

Lessons Learned

  1. Run npm audit in CI/CD - Do not wait for manual checks
  2. Set audit-level based on your risk tolerance - high is a good default
  3. Use overrides for transitive dependency vulnerabilities you cannot directly fix
  4. Monitor GitHub Dependabot alerts for ongoing vulnerability notifications
  5. Keep dependencies updated regularly - Do not let them accumulate for months

This blog does not accept any external sponsorships, affiliate marketing, or ad revenue.