Safeguard
Developer Tools•

Does go.mod list everything in a Go build for your SBOM?

go.mod records required modules, but a binary only contains what the build used. Learn where each source helps and how to cross check a Go SBOM.

Safeguard Security Team
4 min read

For modern Go modules, go.mod lists a requirement for every module that provides a package imported by the main module, so it is a good source. It still describes the module graph, not what one binary contains. Cross check with the build information embedded in the compiled program.

What the Go reference says

The Go modules reference states that at go 1.17 and higher, go.mod includes an explicit require directive for each module that provides any package transitively imported by a package or test in the main module. Indirect dependencies are recorded in a separate block. That is why a recent go.mod is much more complete than an old one.

Two related files are easy to misread:

  • go.sum holds checksums used to verify module content. It is not a list of what your program uses.
  • vendor/modules.txt exists when you vendor dependencies. The reference says it lists vendored packages and the module versions they were copied from, and that the go command checks it for consistency with go.mod.

Module graph versus binary

A project can require modules that never end up in a particular binary. Test only packages, tools, or code behind a platform specific file are common examples. So a go.mod based SBOM can overstate a binary, while still being the right record of the source.

The runtime/debug package documents the other side. Its BuildInfo structure carries a list of dependency modules, described as all the dependency modules, both direct and indirect, that contributed packages to the build of the binary, along with the build settings. That is a record of one build, written by the toolchain itself.

SourceDescribesOverstates?Understates?
go.modRequired modules for the source treeCan include modules a binary never linksRarely, for go 1.17 and later
vendor/modules.txtModules copied into vendorSame as aboveIf vendor is stale
Binary build informationModules that contributed packages to one buildNoOnly if stripped or built with unusual flags

A cross check in four steps

  1. Generate the SBOM from go.mod for the source release.
  2. Build the binary the way you ship it.
  3. Read the module list from the compiled binary. The Go toolchain's version command with the module flag prints it.
  4. Diff the two lists. Expect the binary list to be a subset of the source list. A module in the binary but not in go.mod deserves an immediate look.

Things to flag when you publish

  • Replace directives. A replace line in go.mod swaps a module for another path or a local directory. Record that, because the source of the code is no longer the one the version suggests.
  • Pseudo versions. A version made from a commit timestamp and hash is valid but is not a tagged release. Vulnerability matching by version needs care.
  • Stripped binaries. If build information was removed, you lose the binary side of the cross check.

Where Safeguard fits

Safeguard produces SBOM and dependency scanning results from source and builds, and reachability analysis can show whether a vulnerable Go module's affected code is called. The free scan is at gold.safeguard.sh/scan.

Quick check

Is go.sum a dependency list?

No. It holds checksums for verification, and can contain entries that your code does not use.

Should the SBOM list modules the binary does not link?

A source SBOM can. A release binary SBOM should list what the binary contains, so say which one you are sharing.

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.