NodeJSDependency Vulnerability Scanning

Dependency Vulnerability Scanning

The average Node.js app depends on hundreds of packages — and each one is a potential attack vector. Known vulnerabilities are published to the npm Advisory Database and NVD (National Vulnerability Database), assigned a CVE, and rated by severity. Supply-chain attacks (malicious packages, typosquatting, maintainer account takeovers) are increasingly common. This page covers the scanning tools, how to interpret results, update strategies, and how to evaluate whether a vulnerability actually affects you.

npm audit — built-in scanning

Bash
npm audit                   # check all dependencies against the advisory database
npm audit --audit-level high  # exit non-zero only for high/critical
npm audit fix                 # auto-update to non-breaking patched versions
npm audit fix --force         # also update major versions (test carefully)
found 3 vulnerabilities (1 moderate, 2 high)

# run npm audit fix to fix them, or npm audit for more details

  High severity vulnerability
  Package: jsonwebtoken
  Patched in: >=9.0.0
  Dependency of: your-app
  Path: your-app > jsonwebtoken
  More info: https://github.com/advisories/GHSA-...
`npm audit` queries against the npm advisory database on every `npm install`
Running `npm audit` is free, fast, and built-in. It compares your resolved dependency tree against a database of known vulnerabilities and reports each finding with severity, the vulnerable version range, and what version fixes it. Integrate it into CI: `npm audit --audit-level high` exits with a non-zero code if any high or critical vulnerabilities are found, failing the build. This doesn't find unknown vulnerabilities, but it reliably catches the known ones.
Third-party scanners

Tool

What it adds over npm audit

snyk test

Deeper analysis, license checks, fix PRs, runtime monitoring

socket.dev

Supply-chain analysis — detects malicious packages, not just CVEs

GitHub Dependabot

Automatic PRs when vulnerabilities are patched upstream

Renovate

Automated dependency update PRs with configurable policy

Bash
npx snyk test              # test for vulnerabilities
npx snyk monitor           # continuously monitor in Snyk dashboard
npx socket report package-lock.json  # supply-chain analysis
Evaluating a vulnerability — not all are equal

Text
For each vulnerability, ask:

1. REACHABILITY — does your app actually call the vulnerable code path?
   (A vulnerability in a package you import but don't use may not matter)

2. CONTEXT — the attack requires X (user input, network access, specific config)?
   (A server-side prototype pollution in a client-only lib may be theoretical)

3. SEVERITY — Critical/High vs Low/Moderate: how much damage if exploited?

4. FIX AVAILABLE — is there a patched version?
   (If yes, update. If not: mitigate, or find an alternative package)
All critical/high vulnerabilities with a fix available should be patched — no exceptions
For critical and high findings with a patch: **update immediately**. These represent the most likely exploitation targets. For moderate findings without a reachable code path, document the reasoning ("this only affects server-side rendering, and we don't call the vulnerable function"). For informational/low findings in deep transitive dependencies with no patch, track them and re-evaluate periodically. Never ignore — acknowledge every finding and record your decision.
Keeping dependencies current

Bash
# See what's outdated:
npm outdated

# Update a specific package:
npm install package@latest

# Interactive update with npx:
npx npm-check-updates    # shows all available updates
npx npm-check-updates -u # writes latest versions to package.json (then npm install)
Regular updates are the cheapest vulnerability fix
Most vulnerabilities are patched quickly by maintainers. Keeping dependencies reasonably current means you're rarely more than a patch version away from a fix, and updates involve less churn than letting packages fall years behind. A good cadence: review `npm outdated` monthly, apply patch/minor updates freely, and treat major updates as a short project with testing. Automated tools like Dependabot or Renovate turn this into automatic PRs your CI validates.
Supply-chain hygiene
  • Commit package-lock.json — pins the exact resolved versions; prevents silent upgrades.

  • Use npm ci in CI/CD — installs exactly from the lockfile; fails if it's out of sync.

  • Audit new packages before adding — check download count, GitHub activity, maintainer reputation.

  • Watch for typosquattinglodash is safe; 1odash (with a 1) is not.

  • Avoid installing packages with --ignore-scripts in automated contexts to prevent postinstall malware.

  • Pin exact versions for critical packages in package.json where drift risk is high.

Supply-chain attacks via malicious npm packages are a real and growing threat
In a supply-chain attack, a legitimate package is compromised (maintainer account stolen, malicious update published, or a typosquatted package tricking developers) and the malicious code runs in your build pipeline or production environment. Defences: inspect new transitive dependencies with socket.dev or similar, use `npm ci` from a locked lockfile, enable two-factor auth on your npm account (to protect your own packages), and monitor for unexpected network calls during the build.
In CI: fail on vulnerabilities

.github/workflows/security.yml (GitHub Actions)

YAML
- name: Run security audit
  run: npm audit --audit-level high
  # Exits non-zero on high/critical → fails the CI check
Next
Secure the transport layer: [TLS/HTTPS & Secure Transport](/nodejs/https-security).