# How to generate an SBOM from package-lock.json or NuGet in 10 minutes

Canonical: https://craguard.eu/blog/how-to-generate-an-sbom-in-10-minutes
Language: en
Last updated: 2026-09-02

- [CRAguard](https://craguard.eu/)/
- [Blog](https://craguard.eu/blog)/
- How to generate an SBOM from package-lock.json or NuGet in 10 minutes

18 Aug 2026 · CRAguard

Summary You don't write an SBOM by hand — you generate it from your lock file with a single command. We show concrete commands for Syft, Trivy, `npm sbom` and CycloneDX .NET, output in both CycloneDX and SPDX, and what the CRA (Annex I Part II) actually requires: at least top-level dependencies in a common machine-readable format. It's not rocket science and you don't need a consultant.

An SBOM sounds like a big compliance task, but in practice it is one command and a few minutes. The Cyber Resilience Act requires it in **Annex I, Part II, point 1** as part of the vulnerability-handling process — and prescribes no expensive tool for it. This guide is purely practical: exactly what to run for a Node.js and a .NET project so you end up with an SBOM in both common formats.

## What the CRA asks of an SBOM (in brief)

So you know when you're done: Regulation (EU) 2024/2847 talks about **at least the top-level (direct) dependencies** in a *commonly used, machine-readable format*. It does not prescribe a specific standard — in practice this means **CycloneDX or SPDX**, the two established formats. You do **not publish** the SBOM: it is part of the technical documentation and is provided to a market surveillance authority on request. [SBOM for small vendors](https://craguard.eu/blog/sbom-for-small-vendors-what-the-cra-requires) covers this in detail; here we go straight to the commands.

## Node.js / npm project

If you have a `package-lock.json`, you have three easy routes. The fastest is the built-in npm command (from npm 10):

- **Built into npm:** `npm sbom --sbom-format cyclonedx > sbom.cdx.json` — produces CycloneDX directly from the lock file, with nothing extra to install. For SPDX use `--sbom-format spdx`.
- **Syft** (open source, Apache-2.0): `syft scan dir:. -o cyclonedx-json=sbom.cdx.json -o spdx-json=sbom.spdx.json` — produces both formats in a single run. It can also read the lock file directly: `syft scan file:package-lock.json -o cyclonedx-json`.
- **Trivy** (open source, Apache-2.0): `trivy fs --format cyclonedx --output sbom.cdx.json .` — Trivy can additionally compare that same scan against vulnerability databases right away.

Scope-checker

### Find out whether the CRA applies to you

Six questions, two minutes, no account. Get your product class and first steps.

[Start the scope-checker](https://craguard.eu/checker)

## .NET / NuGet project

For .NET, the most direct route is the official CycloneDX tool:

- **Install:** `dotnet tool install --global CycloneDX` (once).
- **Generate:** `dotnet CycloneDX MyApp.sln -j -o .` — walks the solution or project and produces CycloneDX (`-j` = JSON) into the current folder.
- **Syft alternative:** `syft scan dir:. -o cyclonedx-json=sbom.cdx.json` also works over `packages.lock.json` (if you have `RestorePackagesWithLockFile` enabled).

If you don't yet have a lock file, in .NET you enable it via `RestorePackagesWithLockFile` in the `.csproj` and `dotnet restore` creates one — thanks to it your SBOM will contain exact resolved versions, not just manifest ranges.

## A few habits so the SBOM actually serves you

Generating the file is the start; it earns its keep when it is current and traceable:

- **Version the SBOM with every release.** Each product version has its own component list — otherwise you can't tell which shipped version is vulnerable.
- **Put generation in CI.** One pipeline step that emits `sbom.cdx.json` as a build artifact means you never forget.
- **Keep it with the documentation.** Under the CRA, technical documentation is retained for at least 10 years from placing on the market (or for the support period, if longer) — the SBOM belongs with it.
- **Don't stop at top-level.** The minimum is direct dependencies, but Syft and Trivy also capture transitive ones — and those are what most often surprise you during the first incident.

## What an SBOM alone does not solve

An SBOM is a list, not a guard. On its own it won't tell you a new vulnerability appeared in a component — you learn that only when you **compare it against databases** (OSV.dev, NVD, CISA KEV). And that comparison is recurring, not one-off work: new CVEs appear daily. How to read the acronyms (CVE, CVSS, EPSS, KEV) is covered in a [separate article](https://craguard.eu/blog/cve-cvss-epss-kev-explained).

## FAQ

- **CycloneDX or SPDX?** The CRA doesn't prescribe; both are "commonly used, machine-readable". Syft and Trivy can produce both at once, so make both.
- **Is package.json / .csproj enough?** No — a manifest lacks exact resolved versions and transitive dependencies. Generate from the lock file or build.
- **How often to regenerate the SBOM?** At every release; ideally automatically in CI so you don't forget.
- **Must we publish the SBOM?** No — it's part of the technical documentation and is provided to an authority on request.

## What to watch out for

Two mistakes recur. First: generating an SBOM once "for show" and letting it go stale — at the first incident it then doesn't match the shipped version. Second: relying on the manifest instead of the lock file, so the SBOM lacks exact versions and monitoring against databases is unreliable. Both are solved by one habit: generate the SBOM from the lock file automatically at build time and version it with the release. Then the SBOM is always current and usable for the most important thing — a fast "does this new CVE affect us?".

## Bottom line

An SBOM isn't mountains of paperwork but one command and a few minutes. **Annex I Part II** asks for it as part of vulnerability handling — at least top-level dependencies in a common machine-readable format (CycloneDX or SPDX). Node.js project: `npm sbom`, Syft or Trivy from the lock file. .NET: `dotnet CycloneDX` or Syft over `packages.lock.json`. Container or monorepo? Same tools, different scan target. Key habits: generate from the **lock file** (not the manifest), put it in CI and **version the SBOM with every release**. But an SBOM is just a list, not a guard — it earns its keep only when you continuously compare it against databases (OSV, KEV, EPSS). That's recurring work, because new CVEs arrive daily — and automating that comparison is what decides whether the "does it affect us?" answer takes moments or hours.

## Key point

An SBOM isn't a mountain of paperwork — it's one command and a few minutes. **Annex I, Part II** requires it as part of vulnerability handling — at minimum the top-level dependencies in a common machine-readable format (CycloneDX or SPDX). Node.js: `npm sbom`, Syft or Trivy from the lock file. .NET: `dotnet CycloneDX` or Syft over `packages.lock.json`. A container or monorepo? Same tools, a different scan target. Key habits: generate from the **lock file** (not the manifest), put it in CI, and **version the SBOM with every release**. But an SBOM is only a list, not a guard — it earns its keep once you continuously compare it against databases (OSV, KEV, EPSS). That's recurring work, because new CVEs appear daily — and automating that comparison is what decides whether the answer to "does this affect us?" takes seconds or hours.

## How CRAguard helps

CRAguard takes your lock file, generates an SBOM from it (both CycloneDX and SPDX), keeps it versioned with every release, and compares it **daily** against OSV, KEV and EPSS — so the answer to "does this new CVE affect us?" is ready before the 24-hour Article 14 clock starts. [Find out whether the CRA applies to you](https://craguard.eu/checker), or [join the waitlist](https://craguard.eu/#waitlist) — we'll let you know at launch.

*This article is informational and not legal advice. It is based on Regulation (EU) 2024/2847 (Annex I Part II) and the European Commission's guidance of 27 July 2026. The tools named are third-party; verify commands against the current version of each tool.*

Scope-checker

### Find out whether the CRA applies to you

Six questions, two minutes, no account. Get your product class and first steps.

[Start the scope-checker](https://craguard.eu/checker)

## Sources

- [EUR-Lex — Regulation (EU) 2024/2847 (Cyber Resilience Act)](https://eur-lex.europa.eu/eli/reg/2024/2847/oj)
- [ENISA — Single Reporting Platform](https://www.enisa.europa.eu/)

---
Source: CRAguard — https://craguard.eu
