Safeguard
Developer Tools•

Do you need a separate Go SBOM for each build target?

Go build constraints such as GOOS, GOARCH and tags change which modules compile in. The CycloneDX gomod tool says to generate one SBOM per target.

Safeguard Security Team
4 min read

If you ship one Go application for several platforms, yes, generate one SBOM per build target. Build constraints such as GOOS, GOARCH, CGO_ENABLED and build tags change which modules end up in the binary, and the CycloneDX gomod tool says an SBOM should be generated for each target in the build matrix.

Why one SBOM may not fit all

Go selects files and packages at build time using constraints. A file marked for Windows is not compiled on Linux. A package behind a build tag may be left out of the default build. Since packages pull in modules, the set of modules in your binary can differ between targets.

A single SBOM from a default build on a Linux machine might therefore list a module that your Windows binary never contains, or miss one that only the Windows build pulls in.

The two subcommands

The gomod README describes two main modes and explains who each is for.

SubcommandWhat it includesTypical user
appOnly modules the target application actually depends on; tests and unimported packages excluded; build constraints evaluatedDistributors who ship binaries
modAggregate of modules required by all packages in the module; build constraints not evaluatedMaintainers tracking inventory, licenses and monitoring

A third subcommand, bin, produces rudimentary SBOMs from binaries built with Go modules.

The README adds a practical example: a module may contain a server and a client, of which only the client is distributed. With the app mode you give users an SBOM only for what they receive.

How to set up the matrix

For app mode, the tool reads build constraints from environment variables, and these should mimic what you pass to the build. The README lists GOARCH, GOOS, CGO_ENABLED and GOFLAGS, which can carry build tags. The applicable constraints are recorded as properties of the main component, so each file says what it describes.

An example from the README:

GOARCH=arm64 GOOS=linux GOFLAGS="-tags=foo,bar" cyclonedx-gomod app -output linux-arm64.bom.xml

Steps:

  1. List every combination you actually release, such as linux amd64, linux arm64 and windows amd64.
  2. For each, set the same environment variables your release build uses.
  3. Run the app command with the main package path and an output name that includes the target.
  4. Attach each file to the binary it describes.
  5. Check the recorded constraint properties match the target.

When a single mod SBOM is enough

Use mod when the audience is internal, you want the whole picture, and a handful of extra modules is acceptable. It suits inventory and continuous monitoring, where over reporting is safer than missing something. It is the wrong file to send to a customer who runs one binary, since it may list modules that binary does not contain.

The cost of getting this wrong

Over reporting creates findings against code that is not in the product. Under reporting is worse, since a module compiled into one target is invisible to the file used for matching. A matrix of files costs a few CI minutes and removes both problems.

Related checks

Cgo changes things too: setting CGO_ENABLED differently can pull in different packages. Treat it as part of the target definition, not an afterthought.

Safeguard's SBOM and dependency scanning reads Go modules and SBOM files, and reachability analysis helps show which vulnerable functions your build actually calls. Try the free scan.

Quick check

Is mod or app better for customers?

The README says distributors of applications typically use app, so users get an SBOM only for the artifacts they use.

Do I need to rebuild the binary to make the SBOM?

The app command evaluates build constraints from the environment, so you set the same variables as your build. Check the tool documentation for what it needs installed.

Sources

Last reviewed: 19 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.