Vulnerable Components and Supply-Chain Security: npm audit, Lockfiles and SBOM

Intermediate
13 min

Vulnerable Components and Supply-Chain Security: npm audit, Lockfiles and SBOM

A typical Node.js application contains a few thousand lines you wrote and a few hundred thousand lines you downloaded. OWASP lists "Vulnerable and Outdated Components" (A06) because attackers do not care who wrote the buggy function, and because a single popular package with a flaw gives them thousands of targets at once. The supply chain adds a second risk: the package may have been malicious from the moment you installed it.

In this lesson you will learn how to know what you run, find and fix known vulnerabilities, make installs reproducible with lockfiles, produce an SBOM, and defend against typosquatting, dependency confusion and malicious install scripts.

Know What You Run

You cannot patch what you cannot list. Two commands give the inventory:

bash
npm ls --all # full tree including transitive dependencies npm outdated # installed vs latest, with the semver range you allow

For anything you ship to customers or run in regulated environments, generate a Software Bill of Materials (SBOM): a machine-readable list of every component and version. npm sbom --sbom-format cyclonedx (or spdx) produces one; store it with each release so that when the next major vulnerability is announced you can answer "are we affected?" in seconds instead of days. The same inventory discipline applies to the runtime: a Node.js version past its end-of-life receives no security fixes.

Find and Fix Known Vulnerabilities

npm audit compares your lockfile with a database of published advisories:

bash
npm audit # report, grouped by severity npm audit --audit-level=high # non-zero exit only for high or critical (use in CI) npm audit fix # apply compatible updates automatically

When the fix requires a version your direct dependency has not adopted yet, force the transitive version with overrides in package.json:

json
{ "overrides": { "semver": "^7.5.4" } }

Treat audit results with judgement: a "critical" issue in a build-time tool that never sees user input is not a critical issue for you, but document that decision rather than silencing the alert. Automate updates with Dependabot or Renovate so patches arrive as small, reviewable pull requests instead of a painful yearly upgrade.

Lockfiles and Reproducible Installs

package.json says "any 4.x"; package-lock.json says "exactly 4.18.2, with this integrity hash". Without the lockfile, two installs a day apart can produce different code, and a compromised release published overnight lands in production silently.

  • Commit the lockfile and use npm ci, which installs exactly what the lockfile lists and fails if it disagrees with package.json.
  • The integrity field in the lockfile is a SHA-512 hash; npm refuses a tarball that does not match, so a swapped package is caught.
  • npm audit signatures verifies registry signatures and, for packages published with provenance, the attestation linking the package to its source repository and build.

Supply-Chain Attacks and Defenses

| Attack | How it works | Defense | |---|---|---| | Typosquatting | lodahs instead of lodash, published with malware | Check the name and download count; copy names from the official README | | Dependency confusion | A public package with the same name as your private one, at a higher version | Use a scope (@company/pkg) and pin the registry for that scope in .npmrc | | Malicious install scripts | postinstall runs code at install time | npm ci --ignore-scripts in CI; review scripts of new packages | | Maintainer account takeover | A trusted package's new version contains a backdoor | Lockfiles, delayed adoption of brand-new releases, provenance checks |

Before adding a dependency, ask whether you need it at all. A ten-line utility copied into your code has no supply chain.

Quick Quiz
Question 1 of 2

Why is `npm ci` preferred over `npm install` in CI pipelines?

Key Takeaways

  • Most of your application is third-party code; inventory it with npm ls, npm outdated and an SBOM per release.
  • Run npm audit --audit-level=high in CI, fix with updates or overrides, and automate patches with Dependabot or Renovate.
  • Commit the lockfile and install with npm ci; integrity hashes and npm audit signatures catch swapped or unsigned packages.
  • Defend against typosquatting, dependency confusion and install scripts with scopes, registry pinning and --ignore-scripts.
  • The safest dependency is the one you did not add.

Next lesson: Authentication Failures: Brute Force, Credential Stuffing and MFA — protecting the login flow itself.

Vulnerable Components and Supply-Chain Security: npm audit, Lockfiles and SBOM - Cyber Security | CodeYourCraft | CodeYourCraft