golang/go · critical · module.VersionError
verifying %s: checksum mismatch\n\tdownloaded: %v\n\t%s: %v\
Error message
verifying %s: checksum mismatch\n\tdownloaded: %v\n\t%s: %v\n\nSECURITY ERROR\nThis download does NOT match the one reported by the checksum server.\nThe bits may have been replaced on the origin server, or an attacker may\nhave intercepted the download attempt.\n\nFor more information, see 'go help module-auth'.\n
What it means
SECURITY-ERROR path: sumdb returned a line for the requested module+version but its hash differs from the locally computed h1 hash. The full message spells out that bits may have been replaced on the origin server or an attacker intercepted the download. The download is rejected outright.
Source
Thrown at src/cmd/go/internal/modfetch/fetch.go:870
noun := "module"
if before, found := strings.CutSuffix(mod.Version, "/go.mod"); found {
noun = "go.mod"
modWithoutSuffix.Version = before
}
db, lines, err := lookupSumDB(mod)
if err != nil {
return module.VersionError(modWithoutSuffix, fmt.Errorf("verifying %s: %v", noun, err))
}
have := mod.Path + " " + mod.Version + " " + h
prefix := mod.Path + " " + mod.Version + " h1:"
for _, line := range lines {
if line == have {
return nil
}
if strings.HasPrefix(line, prefix) {
return module.VersionError(modWithoutSuffix, fmt.Errorf("verifying %s: checksum mismatch\n\tdownloaded: %v\n\t%s: %v"+sumdbMismatch, noun, h, db, line[len(prefix)-len("h1:"):]))
}
}
return module.VersionError(modWithoutSuffix, fmt.Errorf("verifying %s: checksum missing from sumdb response"+sumdbAbsent, noun))
}
// Sum returns the checksum for the downloaded copy of the given module,
// if present in the download cache.
func Sum(ctx context.Context, mod module.Version) string {
if cfg.GOMODCACHE == "" {
// Do not use current directory.
return ""
}
ziphash, err := CachePath(ctx, mod, "ziphash")
if err != nil {
return ""
}
data, err := lockedfile.Read(ziphash)View on GitHub (pinned to b6b368adc5)
Solutions
- Do NOT bypass: investigate which proxy served the bytes (GOPROXY, GONOPROXY).
- Clear the local modcache so a fresh download occurs: go clean -modcache.
- Force download direct from VCS via GOPROXY=direct for the affected module to compare.
- If upstream retagged legitimately, wait for sum.golang.org to update or pin a different version; never use GONOSUMDB to suppress this signal.
Defensive patterns
Strategy: validation
Try / catch
// Do NOT catch-and-ignore. Treat as fatal, then quarantine the module and
// fetch directly from VCS to triage.
if err := modfetch.Download(...); err != nil {
if strings.Contains(err.Error(), "SECURITY ERROR") {
// alert; pin a known-good version; never bypass with GONOSUMDB
panic(err)
}
} Prevention
- Never use GONOSUMDB/GONOSUMCHECK to silence this — it indicates tampering.
- Pin module versions explicitly in go.mod so a retagged upstream is visible.
- Prefer HTTPS proxies you control and audit proxy logs for unexpected retagging.
When it happens
Trigger: checkSumDB iterates lines; one matches the prefix `path version h1:` but its hash differs from local. module.VersionError is returned with the formatted mismatch including the sumdbMismatch SECURITY ERROR block.
Common situations: A compromised or misconfigured module proxy returning tampered content; an upstream tag that was force-pushed after sum.golang.org recorded it; a corporate caching proxy serving stale/corrupt bytes; build-machine clock skew combined with caching middleware.
Related errors
- verifying %s: checksum missing from sumdb response\n\nSECURI
- SHA-256 hash of %s is %s, want %s (from %s)
- verifying %v
- verifying %s: %v
- checksum database disabled by GOSUMDB=off
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/dbfc6f6989bf545f.
Report an issue: GitHub.