Skip to content

Commit e9d1273

Browse files
author
Bryan C. Mills
committed
cmd/go/internal/web: reject insecure redirects from secure origins
We rely on SSL certificates to verify the identity of origin servers. If an HTTPS server redirects through a plain-HTTP URL, that hop can be compromised. We should allow it only if the user set the -insecure flag explicitly. Fixes #29591 Change-Id: I00639541cca2ca034c01c464385a43b3aa8ee84f Reviewed-on: https://go-review.googlesource.com/c/go/+/156838 Run-TryBot: Bryan C. Mills <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent a8b4bee commit e9d1273

File tree

3 files changed

+25
-22
lines changed

3 files changed

+25
-22
lines changed

src/cmd/go/go_test.go

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3407,22 +3407,6 @@ func TestGoGetDotSlashDownload(t *testing.T) {
34073407
tg.run("get", "./pprof_mac_fix")
34083408
}
34093409

3410-
// Issue 13037: Was not parsing <meta> tags in 404 served over HTTPS
3411-
func TestGoGetHTTPS404(t *testing.T) {
3412-
testenv.MustHaveExternalNetwork(t)
3413-
switch runtime.GOOS {
3414-
case "darwin", "linux", "freebsd":
3415-
default:
3416-
t.Skipf("test case does not work on %s", runtime.GOOS)
3417-
}
3418-
3419-
tg := testgo(t)
3420-
defer tg.cleanup()
3421-
tg.tempDir("src")
3422-
tg.setenv("GOPATH", tg.path("."))
3423-
tg.run("get", "bazil.org/fuse/fs/fstestutil")
3424-
}
3425-
34263410
// Test that you cannot import a main package.
34273411
// See golang.org/issue/4210 and golang.org/issue/17475.
34283412
func TestImportMain(t *testing.T) {

src/cmd/go/internal/web/http.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ import (
2525
"cmd/internal/browser"
2626
)
2727

28-
// httpClient is the default HTTP client, but a variable so it can be
29-
// changed by tests, without modifying http.DefaultClient.
30-
var httpClient = http.DefaultClient
31-
3228
// impatientInsecureHTTPClient is used in -insecure mode,
3329
// when we're connecting to https servers that might not be there
3430
// or might be using self-signed certificates.
@@ -42,6 +38,18 @@ var impatientInsecureHTTPClient = &http.Client{
4238
},
4339
}
4440

41+
// securityPreservingHTTPClient is like the default HTTP client, but rejects
42+
// redirects to plain-HTTP URLs if the original URL was secure.
43+
var securityPreservingHTTPClient = &http.Client{
44+
CheckRedirect: func(req *http.Request, via []*http.Request) error {
45+
if len(via) > 0 && via[0].URL.Scheme == "https" && req.URL.Scheme != "https" {
46+
lastHop := via[len(via)-1].URL
47+
return fmt.Errorf("redirected from secure URL %s to insecure URL %s", lastHop, req.URL)
48+
}
49+
return nil
50+
},
51+
}
52+
4553
type HTTPError struct {
4654
status string
4755
StatusCode int
@@ -54,7 +62,7 @@ func (e *HTTPError) Error() string {
5462

5563
// Get returns the data from an HTTP GET request for the given URL.
5664
func Get(url string) ([]byte, error) {
57-
resp, err := httpClient.Get(url)
65+
resp, err := securityPreservingHTTPClient.Get(url)
5866
if err != nil {
5967
return nil, err
6068
}
@@ -87,7 +95,7 @@ func GetMaybeInsecure(importPath string, security SecurityMode) (urlStr string,
8795
if security == Insecure && scheme == "https" { // fail earlier
8896
res, err = impatientInsecureHTTPClient.Get(urlStr)
8997
} else {
90-
res, err = httpClient.Get(urlStr)
98+
res, err = securityPreservingHTTPClient.Get(urlStr)
9199
}
92100
return
93101
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# golang.org/issue/13037: 'go get' was not parsing <meta> tags in 404 served over HTTPS.
2+
# golang.org/issue/29591: 'go get' was following plain-HTTP redirects even without -insecure.
3+
4+
[!net] skip
5+
6+
env GOPROXY=
7+
8+
! go get -d vcs-test.golang.org/insecure/go/insecure
9+
stderr 'redirected .* to insecure URL'
10+
11+
go get -d -insecure vcs-test.golang.org/insecure/go/insecure

0 commit comments

Comments
 (0)