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 7c9280f1d090bdf26297d0dcd9f46403bface6eb..ed384c3c43fb755d8a52eec97cae4a5b98130d19 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -870,7 +870,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, @@ -1076,6 +1076,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