Introduction
Go's module system verifies downloaded modules against hashes stored in go.sum. When the downloaded module's hash does not match the expected hash in go.sum, Go refuses to use it. This protects against supply chain attacks but can also break legitimate builds when modules are republished (which should not happen but does in practice), when the proxy serves different content, or when go.sum is out of sync.
Symptoms
go: github.com/example/lib@v1.2.3: checksum mismatchverifying github.com/example/lib@v1.2.3: checksum mismatchsecurity: checksum mismatch for github.com/example/lib- Build works on one machine but fails on another
- CI fails after developer updates
go.modbut notgo.sum
``` go: github.com/example/lib@v1.2.3: verifying module: checksum mismatch downloaded: h1:abc123def456... go.sum: h1:xyz789ghi012...
SECURITY ERROR This download does NOT match the one recorded in go.sum. The download may have been tampered with. ```
Common Causes
go.sumnot committed to version control- Module author republished a version (violates Go module immutability)
- GOPROXY returning different content than direct download
- Switching between GOPROXY and direct fetching
- Private modules not in the sum database
go.modupdated butgo.sumnot regenerated
Step-by-Step Fix
- 1.Regenerate go.sum from scratch:
- 2.```bash
- 3.# Remove existing sum file
- 4.rm go.sum
# Re-download and regenerate go mod download go mod verify
# Or in one step go mod tidy ```
- 1.Configure GONOSUMCHECK for private modules:
- 2.```bash
- 3.# Skip checksum verification for private repos
- 4.go env -w GONOSUMCHECK="github.com/myorg/*,gitlab.com/company/*"
# Or combined with GOPRIVATE go env -w GOPRIVATE="github.com/myorg/*" # This automatically sets GONOSUMCHECK and GONOSUMDB ```
- 1.Use consistent GOPROXY across all environments:
- 2.```bash
- 3.# Set proxy explicitly
- 4.go env -w GOPROXY="https://proxy.golang.org,direct"
# Or use corporate proxy go env -w GOPROXY="https://artifactory.company.com/api/go/go-proxy,https://proxy.golang.org,direct" ```
- 1.Verify module integrity:
- 2.```bash
- 3.# Verify all modules against go.sum
- 4.go mod verify
# Shows: all modules verified # Or: github.com/example/lib@v1.2.3: tampered check
# Check specific module go list -m -json github.com/example/lib@v1.2.3 ```
- 1.Handle module republishing (rare):
- 2.```bash
- 3.# If a module was legitimately republished by the author
- 4.# Update to a new version instead
- 5.go get github.com/example/lib@v1.2.4
# Or if you must use the republished version rm go.sum go mod tidy # Commit the new go.sum ```
Prevention
- Always commit
go.sumto version control - Run
go mod tidybefore committing dependency changes - Use
go mod verifyin CI pipeline as a security check - Pin dependency versions to specific commits if needed:
- ```bash
- go get github.com/example/lib@abc123def
`- Use
GOPROXYconsistently across development and CI - For private modules, always set
GOPRIVATEto skip sum checks - Monitor
go mod verifyoutput in CI for supply chain integrity