Supply-Chain Integrity — Specification¶
Table of Contents¶
- Introduction
- Where Supply-Chain Integrity Is Specified
go.sumFormat (Specified)- The Checksum Database Protocol
- Environment Variables:
GOSUMDB,GOPROXY,GOPRIVATE, and Friends go mod verifyandgo mod download(Specified Behavior)govulncheckInterface and Exit Codes- The OSV Schema (Go Ecosystem)
go version -mEmbedded Build Info Format- SLSA Build Levels (Specified)
- SBOM Formats: CycloneDX and SPDX
- Differences Across Go Versions
- References
Introduction¶
"Supply-chain integrity" is not one specification but a stack of them. The Go language specification (go.dev/ref/spec) says nothing about it — these are tooling, protocol, and ecosystem specifications. The authoritative sources, in decreasing formality:
- Go Modules Reference (
go.dev/ref/mod) —go.sum, the checksum database,GOSUMDB/GOPROXY/GOPRIVATE,go mod verify. - Go security documentation (
go.dev/security/,go.dev/doc/security/vuln/) —govulncheck, the vuln database. - OSV schema (
ossf.github.io/osv-schema/) — the vulnerability data format. - SLSA specification (
slsa.dev/spec) — build levels and provenance. - CycloneDX (
cyclonedx.org) and SPDX (spdx.dev) — SBOM formats.
This file separates "what each spec mandates" from convention and implementation. Where a spec is silent, the toolchain source is the de-facto reference.
Where Supply-Chain Integrity Is Specified¶
| Concern | Authoritative source |
|---|---|
go.sum format and verification | Go Modules Reference §"go.sum files" |
| Checksum database protocol | Go Modules Reference §"Checksum database"; golang.org/x/mod/sumdb |
GOSUMDB/GOPROXY/GOPRIVATE | Go Modules Reference §"Environment variables"; go help environment |
go mod verify | go help mod verify; Modules Reference |
govulncheck behavior | go.dev/doc/security/vuln/; golang.org/x/vuln docs |
| Vuln data format | OSV Schema spec |
| Embedded build info | runtime/debug.BuildInfo; go help version |
| Build provenance levels | SLSA specification |
| SBOM | CycloneDX spec; SPDX spec |
go.sum Format (Specified)¶
Per the Go Modules Reference, go.sum contains lines of the form:
<module>— the module path.<version>— a canonical semantic version (or pseudo-version).<hash>— an algorithm prefix and base64 digest, currentlyh1:(SHA-256 over a deterministic tree hash of the file list and their hashes).
Two lines per version are required: 1. The /go.mod line — a hash of only that module version's go.mod file. Used during module-graph construction, before downloading full content. 2. The plain line — a hash of the module's full file tree (the .zip content), computed via the dirhash algorithm (golang.org/x/mod/sumdb/dirhash).
Specified properties: - Every module version used by a build must have both hashes present and matching, or the build fails. - The file is append-only in practice but may contain entries for versions no longer needed (until go mod tidy prunes them). - Verification is mandatory and on by default; there is no per-build flag to skip an existing go.sum entry's check (only environment-level disabling of the database, not local go.sum).
The h1: hash is defined as SHA-256 of the sorted list of SHA-256(file) filename lines for every file in the module zip — making it independent of zip metadata and reproducible.
The Checksum Database Protocol¶
The checksum database (GOSUMDB, default sum.golang.org) is specified as a signed, append-only, Merkle-tree transparency log. The client protocol (Modules Reference §"Checksum database", implemented in golang.org/x/mod/sumdb):
- Endpoints (relative to the database URL):
/latest— a signed tree head (the current Merkle root and tree size)./lookup/<module>@<version>— returns thego.sumlines for that version, plus its leaf index, signed./tile/...— Merkle tree tiles for constructing inclusion/consistency proofs.- Signed note format. Tree heads are signed using the note format (
golang.org/x/mod/sumdb/note): the message plus one or more— <key-name> <base64-signature>lines. - Inclusion proof. On first lookup of a version, the client obtains the leaf and verifies it is included under a signed root.
- Consistency proof. The client verifies any new root is an append-only extension of previously observed roots.
- Caching. Verified results are stored in the module cache (
$GOMODCACHE/cache/download/sumdb/) so the database is contacted only on first encounter of a version.
A GOSUMDB value may include a public key (sum.golang.org+<hash>+<key>) and an optional URL, allowing alternative or mirrored databases with explicit key pinning.
When a module matches GONOSUMDB (or GOPRIVATE/GONOSUMCHECK), the database is not consulted for it; the local go.sum is still enforced if an entry exists.
Environment Variables: GOSUMDB, GOPROXY, GOPRIVATE, and Friends¶
Specified in the Modules Reference and go help environment:
| Variable | Default | Specified meaning |
|---|---|---|
GOPROXY | https://proxy.golang.org,direct | Comma/pipe-separated proxy list. direct = fetch from VCS. off = disallow downloads. , falls through on 404/410; \| falls through on any error. |
GOSUMDB | sum.golang.org | Checksum database name (optionally +key+url). off disables database verification entirely. |
GOPRIVATE | (empty) | Glob patterns of private modules. Sets the default for GONOPROXY and GONOSUMDB. |
GONOPROXY | (GOPRIVATE) | Patterns fetched direct, bypassing GOPROXY. |
GONOSUMDB | (GOPRIVATE) | Patterns not verified against GOSUMDB. |
GOINSECURE | (empty) | Patterns allowed over HTTP / without TLS verification. |
GOFLAGS | (empty) | Default flags applied to go commands (e.g. -mod=readonly). |
GOTOOLCHAIN | auto | local = never download a toolchain; path/version = selection policy. |
Pattern matching uses path.Match-style globs against module paths, matched per path element. GONOSUMCHECK is a legacy/obsolete control that disabled all sum checking; it is not a documented modern variable and should be avoided.
Precedence: an explicit GONOPROXY/GONOSUMDB overrides the value GOPRIVATE would otherwise imply.
go mod verify and go mod download (Specified Behavior)¶
go mod verify (per go help mod verify): checks that dependencies stored in the module cache have not been modified since download, by re-hashing them and comparing to the recorded go.sum. On success it prints all modules verified; on failure it reports each module whose cached files differ. It verifies the cache, not vendor/ and not your source.
go mod download (per go help mod download): downloads the named modules (or the build list) into the cache, applying go.sum verification and, for first encounters, checksum-database verification. With -x it prints the commands; with -json it emits structured records (Path, Version, Zip, Dir, Sum, GoModSum, Error). It does not modify go.mod unless adding missing go.sum entries is required and permitted by the current -mod mode.
Both commands honor GOPROXY, GOSUMDB, and the private-module variables.
govulncheck Interface and Exit Codes¶
govulncheck is distributed at golang.org/x/vuln/cmd/govulncheck (not in the standard toolchain; installed via go install). Specified surface (per its documentation):
patterns— Go package patterns (./...) for source mode, or with-mode=binary, a path to a compiled binary.-mode—source(default; full call-graph reachability, requires compilable code) orbinary(module-level detection from embedded build info).-scan—symbol(default),package, ormodule; controls reachability granularity.-format—text(default),json, orsarif.-show— additional output controls (e.g.traces,color,version,verbose).-db— vulnerability database URL (defaulthttps://vuln.go.dev).-C dir,-tags,-test— directory, build tags, and whether to include test code.
Exit codes (text mode): non-zero when one or more actionable vulnerabilities are found or an error occurs; zero when no actionable vulnerabilities are found. This makes a bare govulncheck ./... a valid CI gate. (In -json/-sarif modes the exit code may be zero regardless; callers parse the structured output to apply policy.)
Output sections: actionable findings (with call-stack traces) and an "Informational" section for vulnerabilities present but not reachable from a called function.
The OSV Schema (Go Ecosystem)¶
The Go vulnerability database publishes OSV-schema JSON (ossf.github.io/osv-schema). Required/relevant fields for the Go ecosystem:
id—GO-YYYY-NNNN.aliases— relatedCVE-.../GHSA-...identifiers.affected[]— per affected package:package.ecosystem—"Go".package.name— module path.ranges[].type—"SEMVER";ranges[].events[]withintroduced/fixedversions.ecosystem_specific.imports[]— the Go-specific extension: per importpath, the list of affectedsymbols(functions/methods). This field powersgovulncheck's symbol-level reachability.database_specific.url—https://pkg.go.dev/vuln/GO-YYYY-NNNN.
The symbols extension is what distinguishes the Go database from minimal OSV producers and enables call-graph filtering. Versions in events are canonical semver; introduced: "0" means "from the beginning."
go version -m Embedded Build Info Format¶
Every Go binary (since Go 1.13, expanded over time) embeds build information accessible via runtime/debug.ReadBuildInfo() and printed by go version -m <binary>. The line format:
<binary>: <go-version>
path <main package import path>
mod <main module> <version> <hash>
dep <module> <version> <hash>
=> <replacement> <version> <hash> # if replaced
build <key>=<value> # build settings
mod— the main module.dep— each dependency module baked into the binary, with version andh1:hash.=>— a replacement (from areplacedirective), recorded on the line after the replaceddep.build— settings such as-trimpath=true,CGO_ENABLED=...,vcs.revision=...,vcs.time=...,vcs.modified=...,GOARCH,GOOS.
This embedded data is the ground-truth inventory of what shipped and is the input consumed by govulncheck -mode=binary, cyclonedx-gomod bin, and syft.
SLSA Build Levels (Specified)¶
Per the SLSA specification (slsa.dev/spec, v1.0 "Build" track):
| Level | Requirement (paraphrased) |
|---|---|
| Build L0 | No guarantees. |
| Build L1 | The build process produces provenance describing how the artifact was built. Provenance may be unsigned. |
| Build L2 | The build runs on a hosted build platform that generates and signs the provenance, so it is authenticated and not forgeable by the package's own developers locally. |
| Build L3 | The build platform is hardened: builds run in isolated environments, and provenance is generated by the platform in a way the build's own steps cannot influence or forge. Resists tampering by a compromised build step. |
Provenance is expressed as an in-toto attestation (in-toto.io/Statement/v1) carrying the SLSA provenance predicate (slsa.dev/provenance/v1), binding an artifact digest (subject) to a builder identity (runDetails.builder.id) and build parameters (buildDefinition).
SLSA is a framework; it does not mandate specific tools. The Go ecosystem realizes it via the SLSA GitHub generator, cosign/sigstore signing, and reproducible builds.
SBOM Formats: CycloneDX and SPDX¶
Two specified, interoperable SBOM formats apply to Go:
- CycloneDX (
cyclonedx.org, ECMA-driven, OWASP) — JSON/XML;components[]withpurl(Package URL, e.g.pkg:golang/github.com/google/uuid@v1.6.0),hashes,licenses, and dependency graph. Security-oriented; supportsvulnerabilities[]. Generated for Go bycyclonedx-gomod. - SPDX (
spdx.dev, ISO/IEC 5962:2021, Linux Foundation) — tag-value or JSON;packages[]withSPDXID,versionInfo,licenseConcluded,checksums, andrelationships. License/compliance-oriented. Generated for Go bysyft -o spdx-json.
Both can be produced from a Go module's graph or, preferably for release artifacts, from the compiled binary's embedded build info, ensuring the SBOM reflects exactly what shipped. The Package URL (purl) pkg:golang/... is the cross-format canonical identifier for a Go module version.
Differences Across Go Versions¶
- Go 1.11 — Modules introduced;
go.sumappears. - Go 1.13 — Checksum database (
GOSUMDB,sum.golang.org) and module proxy (GOPROXY) become defaults;GOPRIVATE,GONOSUMDB,GONOPROXY,GOINSECUREintroduced. Binaries begin embedding module info. - Go 1.16 —
-mod=readonlybecomes the default; module mode on by default (GO111MODULE=on). - Go 1.18 —
go version -mbuild settings expanded (VCS info:vcs.revision,vcs.time,vcs.modified);-buildvcsflag. - Go 1.20–1.21 —
govulncheckmatures; symbol-level analysis and binary mode stabilized (govulncheckitself versioned independently undergolang.org/x/vuln).GOTOOLCHAINand thetoolchaindirective introduced (1.21), relevant to pinning the toolchain as a supply-chain input. - Go 1.21+ — Reproducible-build ergonomics and
-trimpathremain stable;govulncheckadds SARIF output and richer modes via thex/vulnmodule.
The core integrity primitives — go.sum, the checksum database, and the private-module variables — have been stable since Go 1.13. The principal additions since are the vulnerability tooling (govulncheck, the vuln DB), richer embedded build info, and toolchain pinning.
References¶
- Go Security — authoritative hub.
- Go Modules Reference —
go.sum, checksum database, environment variables. - Module checksum database
- Private modules
- Vulnerability Management for Go
- Govulncheck blog
- Go vulnerability database
- OSV Schema
- SLSA specification
- CycloneDX specification
- SPDX specification
- Source:
golang.org/x/mod/sumdb - Source:
golang.org/x/vuln
In this topic