An SBOM (Software Bill of Materials) is a machine-readable list of every package, version, and license in your application. CycloneDX is the format most regulators and procurement teams ask for — it's an OWASP project, JSON or XML, and supported by every modern scanner. If you ship to enterprise or any EU market subject to the Cyber Resilience Act, you will need one.
Here's how to produce a clean CycloneDX 1.5 SBOM from a single package-lock.json in five minutes — without installing a CLI, signing up, or pushing your lockfile to a third-party SaaS.
What CycloneDX needs (the 80/20 view)
An auditor opening your SBOM looks at six things first:
bomFormat= CycloneDX andspecVersion= 1.5 (or 1.6)serialNumber— a unique URN per build (so two SBOMs from two builds are distinguishable)metadata.timestampandmetadata.tools(who generated it)metadata.component— the application itself (your project)components[]— every dependency withname,version,purl(Package URL), andtype: librarydependencies[]— the graph: which package depends on which (this is what makes the SBOM useful, not just a flat list)
The 5-minute workflow with DepTriage
- Open your project, find
package-lock.jsonat the repo root. - Drop the file into the DepTriage scanner. Nothing leaves your browser session — the lockfile is parsed in memory and discarded.
- DepTriage extracts every
name@versioninpackagesanddependencies, generates a Package URL likepkg:npm/lodash@4.17.21, and emits a CycloneDX 1.5 JSON document. - Click Export SBOM → save
deptriage-sbom.cdx.json. - Optional: validate it with the
cyclonedxCLI:cyclonedx validate --input-file deptriage-sbom.cdx.json.
⚠️ Lockfile, not package.json. A package.json only lists your direct dependencies and ranges (^4.17.0). An auditor wants the resolved versions actually installed, which only the lockfile contains. Always SBOM the lockfile.
What gets included — and what doesn't
A correct CycloneDX SBOM from a lockfile includes all transitive dependencies, not just the ones you imported directly. This is the whole point: a typical Node.js app declares 20 direct dependencies and ends up with 1,200 packages on disk. Auditors care about all 1,200.
What is not included by default:
- devDependencies — by convention, runtime SBOMs exclude them. CycloneDX has a
scope: optionalflag if you want to include them separately. - OS packages, compiled binaries, container images — those need a different scanner (Syft, Trivy).
- License text — only the SPDX identifier (
MIT,Apache-2.0) goes in. Full license text is normally shipped separately.
Common mistakes
| Mistake | Why it fails an audit |
|---|---|
SBOMing package.json instead of the lockfile | Versions are ranges, not resolved — non-reproducible |
No purl on components | Auditor cannot cross-reference with vulnerability databases |
Empty dependencies[] graph | Reachability/triage tools can't compute depth — every CVE looks identical |
Same serialNumber across builds | Cannot prove which build was shipped to which customer |
Generate a CycloneDX SBOM from your lockfile
Drop the file. Get the report. Export the SBOM. No account.
Open the scanner →FAQ
For dependency-risk SBOMs, CycloneDX wins on tooling and is the OWASP standard. SPDX is more common in license-compliance workflows and US federal procurement. DepTriage exports both — you don't have to choose.
Yes. The whole point is that the SBOM matches the artifact actually shipped. Generate it as part of your CI pipeline, attach it to the release, store it for the legally required retention period (10 years under the EU CRA).
Yes — Sigstore/Cosign and CycloneDX VEX are the most common approaches. For a micro-team starting out, a hash + Git tag is enough to prove provenance.
No. DepTriage parses lockfiles in memory only. Nothing is written to disk or sent to a third party. The risk report is yours alone.