If your usual workflow is "check Slack, panic, ask the senior engineer, then panic some more," this is a playbook to replace that — written for the founder or engineering lead at a 5–50 person B2B SaaS who just got the email.
An SBOM — Software Bill of Materials — is a list of every third-party software component your product ships with, along with each component's version, license, and (sometimes) source URL. The request usually comes through a customer's procurement, security, or legal team, often as part of a broader vendor-due-diligence checklist alongside SOC 2 reports, pen-test summaries, and so on.
Procurement teams aren't trying to trip you up. They're trying to answer two questions for their own auditors:
The first one is the license question. That's what this article is about.
Most procurement teams will accept any of these three formats:
If the request doesn't specify, send a CycloneDX JSON plus a PDF summary. The JSON satisfies the technical reviewer; the PDF satisfies the lawyer.
The most common mistake is to read package.json or pyproject.toml and call it done. Those files list direct dependencies. Your SBOM has to include transitive dependencies — the libraries your libraries depend on. A typical Express app has 5–10 direct deps and 200+ transitive ones.
The lockfiles to read instead, by ecosystem:
| Ecosystem | Lockfile |
|---|---|
| npm | package-lock.json |
| pnpm | pnpm-lock.yaml |
| yarn | yarn.lock |
| pip / uv | uv.lock or requirements.txt with pinned versions |
| poetry | poetry.lock |
| Cargo | Cargo.lock |
| Go modules | go.sum |
Most lockfiles record the license per package, but the format varies. The right answer for any package falls into three buckets:
MIT, Apache-2.0. List it.(MIT OR Apache-2.0) for dual-licensed packages, or GPL-3.0-or-later. List the expression as-is; do not collapse it to one license without checking the upstream's intent.LICENSE file but no license field in package.json. Flag for manual review. Don't guess.Procurement teams are mostly worried about copyleft licenses — those that require derivative works to be released under the same license. The big three to flag:
The vast majority of what's in your tree — MIT, Apache-2.0, BSD-2/3-Clause, ISC, MPL-2.0 — is fine for closed-source SaaS use. List them, but you don't need to defend them.
Send three things:
If you've never done it before: 2–3 days, mostly because you're learning what the formats look like and second-guessing the edge cases.
If you have a tool that walks lockfiles, maps to SPDX, surfaces ambiguity, and exports a CycloneDX + PDF: about an hour.
That tool is what we're building. The CLI is on GitHub; the procurement-ready PDF export ships in v0.0.2.