Safeguard
Developer Tools•

NPM SBOM: build it from package-lock.json or node_modules?

For npm projects, the lockfile shows what should install and node_modules shows what did. Learn which source to trust and when to compare both.

Safeguard Security Team
4 min read

Use package-lock.json when you want a repeatable record of the intended dependency tree, and node_modules when you want proof of what a specific build installed. For releases, generate from the lockfile in CI and spot check against an installed tree. Disagreement between the two is a finding.

What each source really tells you

The npm documentation says package-lock.json describes the exact tree that was generated, so later installs can produce identical trees regardless of intermediate dependency updates. It also notes that, as of npm v7, lockfiles carry enough information to give a complete picture of the package tree. That makes the lockfile a strong source for a "should be" SBOM.

The node_modules folder is the "is" side. It reflects what was installed on one machine at one time, including anything a developer added by hand or any install that ignored the lockfile.

QuestionLockfilenode_modules
Is it repeatable across machines?YesOnly if installed from the lockfile
Does it include packages never installed on this platform?Yes, including optional onesNo
Does it reveal local tampering or stray installs?NoYes
Can you generate it before a build?YesNo, needs an install first
Does it mark dev and optional packages?Yes, with dev and optional flagsNot directly

Dev and optional packages

The lockfile format marks a package as dev when it is strictly part of the devDependencies tree, and as optional when it is strictly part of the optionalDependencies tree. A good SBOM keeps that distinction rather than flattening everything into one list. A runtime consumer cares about what ships. A build auditor cares about what touched the pipeline. Both questions deserve an answer, so look for a scope or similar field in the output.

When the two disagree

Run a simple comparison: list name and version pairs from the lockfile, list them from an installed tree, and diff. Differences usually have one of these causes.

  1. Optional packages that did not install on this operating system. Expected, not a problem.
  2. A hand installed package not saved to the lockfile. Fix the process.
  3. A lockfile out of date after someone edited package.json without installing. Regenerate and commit.
  4. A workspace or linked package that appears once in one source and twice in the other. Check how your tool treats links.

Cause 2 is the one that matters for security: a package on disk that no review ever saw.

A practical rule

  • Generate the release SBOM from the lockfile, in CI, from a clean checkout.
  • Install with the lockfile enforced, then compare installed names and versions to the lockfile as a periodic check.
  • Fail the build when the install changes the lockfile, so drift is visible at the time it happens.
  • Keep dev dependencies in the document but marked, rather than dropping them silently.

Try it yourself

Click through it at your own pace, or open it full screen. Look at how direct and transitive packages are listed, and whether dev scope is visible.

Where Safeguard fits

Safeguard reads your dependency manifests and lockfiles for dependency scanning and SBOM output, and applies reachability analysis to show which vulnerable packages your code actually calls. The free scan is at gold.safeguard.sh/scan.

Quick check

Is a lockfile SBOM enough for compliance?

It is a sound basis for a source SBOM. If a customer asks what shipped in an image, add a second SBOM from the built artifact.

Should the SBOM include devDependencies?

Include them, marked as dev, so readers can filter. Dropping them hides build time risk.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.