Safeguard
Software Supply Chain•

How do you generate an SBOM for a TypeScript project?

Use npm sbom or the CycloneDX npm tool on an installed or locked tree, omit dev dependencies for shipped builds, then validate and store the file per release.

Safeguard Security Team
4 min read

For a TypeScript project, generate the SBOM from the npm dependency tree, not from the TypeScript source. Run npm sbom or the CycloneDX npm tool against your lockfile or installed packages, omit dev dependencies if you want the shipped runtime view, then validate the file and store it with the release.

Why is TypeScript a special case?

TypeScript compiles to JavaScript. Your build output contains plain JavaScript, and the packages that ship are the ones npm resolved. The compiler, type definition packages and test tools are usually dev dependencies and may never reach production. An SBOM from the lockfile can therefore be broader than what you deploy, so decide up front which question you are answering: everything the project uses to build, or what runs in production.

What does npm sbom do?

npm has a built-in command, npm sbom, that generates a software bill of materials for the current project in either SPDX or CycloneDX format. Its documentation lists the options that matter:

  • sbom-format: choose cyclonedx or spdx.
  • sbom-type: library, application or framework, which sets the type field in the output.
  • omit: dependency types to leave out of the tree, such as dev.
  • package-lock-only: use only the lockfile and ignore node_modules.
  • workspaces: run across configured workspaces, useful in monorepos.

The documented example output records each component with a package URL, version, license and a SHA-512 hash, plus a dependency graph. With package-lock-only, details that come from a dependency's own package.json, such as description and homepage, are missing.

npm sbom --sbom-format cyclonedx --omit dev > bom.cdx.json

What does the CycloneDX tool add?

The CycloneDX npm tool is a separate package, installed as a development dependency or run through npx. Documented options include choosing the spec version and output format, writing to a file, validating the result before output, gathering license texts, working with workspaces, and a reproducible output mode. It can also use the lockfile only. It uses npm itself to collect evidence of installed packages, so if the same component is installed in several places, it appears several times.

Pick one tool for your pipeline so diffs between releases are meaningful.

Constructed example: a Node API written in TypeScript

The team deploys a Docker image built from compiled output. In CI they run npm ci, build, then generate two files. One omits dev dependencies and matches the production image. The other includes everything, for build-time review. The first is attached to the release and scanned before deploy. The second feeds a weekly review of build tooling.

If the image bundles code with a bundler, check whether the bundler inlines packages. The SBOM still lists them, because the package manager resolved them, which is usually what you want.

What can go wrong?

  • Generating from a tree with unresolved peer dependency errors. The CycloneDX tool has an option to ignore npm errors, which should be a deliberate choice.
  • Generating before install. Without package-lock-only, the tools read installed packages.
  • Missing system packages. Base image packages and the Node runtime are not in the npm tree. Scan the container image separately.
  • Stale files. An SBOM is a snapshot. Generate it on each release build.

What to do

  1. Decide: runtime view or full build view, and generate the one you need.
  2. Run npm ci so the tree matches the lockfile.
  3. Generate with npm sbom or the CycloneDX npm tool, choosing one format and spec version.
  4. Use omit for dev dependencies on the runtime file.
  5. Validate the output against the format schema.
  6. Attach the file to the release and keep it in an archive.
  7. Scan it for known vulnerabilities and licenses, and fail the build on your chosen policy.
  8. Scan the container image to cover operating system packages.

Safeguard can ingest the dependency inventory of a TypeScript repository and report vulnerabilities, license issues and reachability. The free scan at gold.safeguard.sh/scan covers 100 dependencies if you want a first look.

Open the full demo

Quick check

Does an SBOM from package-lock only include everything installed?

It describes the tree in the lockfile and ignores node_modules, so some package metadata such as descriptions will be missing, but the component list and hashes come from the lock.

Should the SBOM include dev dependencies?

For a production artifact, usually not. Generate a runtime file with dev omitted, and keep a full one separately if you review build tooling.

Sources

Last reviewed: 18 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.