src/cmd/go/internal/modfetch/fetch.go | 15 ++++++++++++++- src/cmd/go/proxy_test.go | 17 +++++++++++++++++ src/cmd/go/testdata/script/mod_sum_absent.txt | 17 +++++++++++++++++ diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index 5d310ccbba90fa402d29b18db5d4fc93f4856dbe..41e02e72dab6f4317c0daaa0a533f19f1c37c2b8 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -851,7 +851,7 @@ 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 nil + 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, @@ -1058,6 +1058,19 @@ SECURITY ERROR This download does NOT match the one reported by the checksum server. The bits may have been replaced on the origin server, or an attacker may have intercepted the download attempt. + +For more information, see 'go help module-auth'. +` + +const sumdbAbsent = ` + +SECURITY ERROR +This download does NOT match one reported by the checksum server. +The checksum server has provided checksums, but the checksums do +not contain an entry for the download. +The checksum server may be malfunctioning, or an attacker may have +intercepted the checksum request. +The download cannot be verified. For more information, see 'go help module-auth'. ` diff --git a/src/cmd/go/proxy_test.go b/src/cmd/go/proxy_test.go index 5ff81361c9609aaf3e72cf4fe142a1fe95bc499a..2a8bacec1868199ec35bbc22e9cadd961b55d9b3 100644 --- a/src/cmd/go/proxy_test.go +++ b/src/cmd/go/proxy_test.go @@ -172,6 +172,23 @@ sumdbWrongServer.ServeHTTP(w, r) return } + // Request for $GOPROXY/sumdb-redirect/module@version:/lookup/... + // performs a lookup for module@version rather than the requested module. + if strings.HasPrefix(path, "sumdb-redirect/") { + redirect, rest, ok := strings.Cut(path[len("sumdb-redirect"):], ":") + if !ok { + w.WriteHeader(500) + return + } + if strings.HasPrefix(rest, "/lookup/") { + r.URL.Path = "/lookup" + redirect + } else { + r.URL.Path = rest + } + sumdbServer.ServeHTTP(w, r) + return + } + // Request for $GOPROXY/redirect//... goes to redirects. if strings.HasPrefix(path, "redirect/") { path = path[len("redirect/"):] diff --git a/src/cmd/go/testdata/script/mod_sum_absent.txt b/src/cmd/go/testdata/script/mod_sum_absent.txt new file mode 100644 index 0000000000000000000000000000000000000000..c2dd814542d671ffeff9326ad5841a73eea5ff79 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_sum_absent.txt @@ -0,0 +1,17 @@ +# When the sumdb returns a response which does not +# include a sum for the requested module, +# we should report an error. +# Verifies CVE-2026-42501. +env sumdb=$GOSUMDB +env proxy=$GOPROXY +env GOPROXY GONOPROXY GOSUMDB GONOSUMDB + +# /sumdb-redirect/ causes the sumdb to return /lookup/ responses +# for rsc.io/quote@v1.0.0, not for the requested module. +env GOSUMDB=$sumdb' '$proxy/sumdb-redirect/rsc.io/quote@v1.0.0: + +! go get rsc.io/fortune@v1.0.0 +stderr 'SECURITY ERROR' +! grep rsc.io go.sum +-- go.mod -- +module m