Use the built-in npm sbom command when you want zero extra installs and either CycloneDX or SPDX output. Use a dedicated CycloneDX npm tool when you need more control, such as schema version choice, validation, license text gathering or reproducible output. Both read npm's own view of your dependencies.
What each one is
The npm command line has a built-in sbom command. Its documentation says it generates a software bill of materials listing the dependencies of the current project, in SPDX or CycloneDX format. You pick the format with the sbom-format setting and the described package type with sbom-type, which can be library, application or framework.
The CycloneDX project maintains a separate tool for npm projects. Its README describes it as creating CycloneDX SBOMs from npm projects, and it can be installed globally, run through npx, or added as a development dependency.
Side by side
| Question | Built-in command | CycloneDX npm tool |
|---|---|---|
| Install needed | None, ships with npm | Yes |
| Formats | CycloneDX or SPDX | CycloneDX, as JSON or XML |
| Package type setting | library, application, framework | application, firmware, library |
| Lockfile only mode | package-lock-only setting | Option to use the lockfile and ignore node_modules |
| Schema version choice | Fixed by the npm release | 1.2 to 1.6 selectable |
| Validation of output | Not documented | Optional validate step |
| License text gathering | Not documented | Experimental option |
| Reproducible output | Not documented | Option available |
The built-in documentation example shows CycloneDX spec version 1.5, produced by an npm 10 release, so what you get depends on your npm version.
Which to choose
Answer these in order.
- Does the consumer require SPDX? The built-in command can produce it directly. Pick it unless another tool in your chain converts.
- Do you need to control the CycloneDX schema version? Choose the dedicated tool.
- Do you want output validated in CI before it is stored? The dedicated tool has a validate option.
- Is the project simple, one package, no special requirements? The built-in command is the lower maintenance path, since there is nothing to pin or update separately.
- Do you run in an environment where adding packages is slow to approve? The built-in command avoids the review.
How to compare them on your repo
Run both on the same checkout with the same install state. Then check:
- The component count in each file.
- Whether dev dependencies appear. The omit setting behaves the same way for both, defaulting to omitting dev only when NODE_ENV is production.
- Whether the root component looks right: name, version, type.
- Whether duplicate packages appear. npm can install the same package in several places in the tree.
Differences usually come down to options, not accuracy. Fix the options first, then compare again.
A note on maintenance
Whichever you pick, record the tool and npm version in the build log. An SBOM that cannot be reproduced is harder to defend when a customer asks how it was made. If you choose the dedicated tool, pin its version in your dev dependencies, and re-check its minimum Node.js and npm requirements when you upgrade the build image.
Safeguard's SBOM and dependency scanning reads npm lockfiles and SBOM files either way. A free scan will show how your project looks to it.
Quick check
Is the built-in command less accurate?
There is no basis for saying so. Both rely on npm's view of the tree. Differences usually come from settings such as omitted dependency types, so align the options and compare.
Which one makes SPDX output?
The built-in npm sbom command can output SPDX. The CycloneDX tool produces CycloneDX only.
Sources
Last reviewed: 19 October 2026.