First-party Software Bill of Materials generation, supporting CycloneDX and SPDX
I shipped my first contribution to pnpm: a native pnpm sbom command. PR #10592 is merged and should be available in an upcoming release.
A Software Bill of Materials is an ingredient list for your software. Every library, every dependency, every version; documented and traceable. Think of it as a nutrition label, but for code.
Regulations caught up
The concept of a software bill of materials has been around for over a decade. What changed is that regulators started paying attention.
The EU Cyber Resilience Act mandates vulnerability handling and software transparency for products sold in the EU. US Executive Order 14028 requires SBOMs for software sold to the federal government. These aren't future plans. They're actively being enforced.
Beyond compliance, SBOMs are a practical security tool. When a vulnerability like React2Shell (CVE-2025-55182, CVSS 10.0) drops and is being actively exploited within hours, organizations with SBOMs can answer "are we affected?" in minutes. Without one, it's days of manual investigation across every service, every deployment, every transitive dependency tree.
And as software supply chain attacks grow more sophisticated (compromised packages, typosquatting, dependency confusion), knowing exactly what's in your dependency tree is a fundamental practice.
The gap
npm has had npm sbom since v9. pnpm users had to rely on external tools: Trivy, cdxgen, Syft. Each with their own quirks around pnpm support. Incomplete dependency trees, issues with workspaces, devDependencies showing up where they shouldn't.
The feature request had been open since February 2025. Users needed SBOMs for Dependency-Track pipelines, JFrog audits, and general SCA workflows. All the information was already there in pnpm-lock.yaml. It just needed a proper command to extract and format it.
Getting it right
I initially used npm sbom as a reference implementation. That turned out to be a mistake, but I learned something new.
Jan Kowalleck, OWASP CycloneDX Project Co-Lead, reviewed the PR and pointed out that npm sbom "does not respect the CycloneDX specification" and "just follows some uneducated ideas and tries to be JSON schema valid." Specifically, npm puts registry integrity hashes directly on components when they're actually distribution metadata (they belong in externalReferences), and silently drops licenses it can't parse instead of falling back to license.name.
After the review, the CycloneDX pnpm plugin was archived in favor of this native implementation. And Jan opened a new issue on the CycloneDX library to better support pnpm's use case going forward.
Usage
pnpm sbom --sbom-format cyclonedx
pnpm sbom --sbom-format spdxBoth major industry standards are supported: CycloneDX 1.7 and SPDX 2.3. Output is validated against the official JSON schemas.
Filter by dependency type:
pnpm sbom --sbom-format cyclonedx --prod
pnpm sbom --sbom-format spdx --dev
pnpm sbom --sbom-format cyclonedx --no-optionalIf you only have the lockfile available and no store, --lockfile-only skips reading package metadata from the content-addressable store entirely. The resulting SBOM will be missing license details and author information, so treat this as a fallback, not the default:
pnpm sbom --sbom-format cyclonedx --lockfile-onlyWorkspace support with --filter:
pnpm sbom --sbom-format spdx --filter my-packagePipe to a file for your compliance tooling:
pnpm sbom --sbom-format cyclonedx > sbom.jsonThe command should land in an upcoming pnpm release. If you're running compliance workflows or vulnerability management pipelines, this gives you first-party SBOM generation without external tooling dependencies.