Skip to content

Commit

Permalink
[release-branch.go1.20] cmd/go/internal/vcs: error out if the request…
Browse files Browse the repository at this point in the history
…ed repo does not support a secure protocol

Updates golang#63845.
Fixes golang#63972.

Change-Id: If86d6b13d3b55877b35c087112bd76388c9404b8
Reviewed-on: https://go-review.googlesource.com/c/go/+/539321
Reviewed-by: Michael Matloob <matloob@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Auto-Submit: Bryan Mills <bcmills@google.com>
(cherry picked from commit be26ae1)
Reviewed-on: https://go-review.googlesource.com/c/go/+/540335
Auto-Submit: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
  • Loading branch information
Bryan C. Mills authored and rcrozean committed Dec 7, 2023
1 parent 35ddbd5 commit 2043cf7
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 16 deletions.
110 changes: 94 additions & 16 deletions src/cmd/go/internal/vcs/vcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ package vcs

import (
"bytes"
"cmd/go/internal/cfg"
"cmd/go/internal/search"
"cmd/go/internal/str"
"cmd/go/internal/web"
"errors"
"fmt"
"internal/lazyregexp"
"internal/singleflight"
"io/fs"
"log"
urlpkg "net/url"
Expand All @@ -22,10 +24,8 @@ import (
"sync"
"time"

"cmd/go/internal/cfg"
"cmd/go/internal/search"
"cmd/go/internal/str"
"cmd/go/internal/web"
"internal/lazyregexp"
"internal/singleflight"

"golang.org/x/mod/module"
)
Expand Down Expand Up @@ -60,6 +60,22 @@ type Status struct {
Uncommitted bool // Required.
}

var (
// VCSTestRepoURL is the URL of the HTTP server that serves the repos for
// vcs-test.golang.org.
//
// In tests, this is set to the URL of an httptest.Server hosting a
// cmd/go/internal/vcweb.Server.
VCSTestRepoURL string

// VCSTestHosts is the set of hosts supported by the vcs-test server.
VCSTestHosts []string

// VCSTestIsLocalHost reports whether the given URL refers to a local
// (loopback) host, such as "localhost" or "127.0.0.1:8080".
VCSTestIsLocalHost func(*urlpkg.URL) bool
)

var defaultSecureScheme = map[string]bool{
"https": true,
"git+ssh": true,
Expand Down Expand Up @@ -1151,21 +1167,38 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths
if !srv.schemelessRepo {
repoURL = match["repo"]
} else {
scheme := vcs.Scheme[0] // default to first scheme
repo := match["repo"]
if vcs.PingCmd != "" {
// If we know how to test schemes, scan to find one.
for _, s := range vcs.Scheme {
if security == web.SecureOnly && !vcs.isSecureScheme(s) {
continue
var ok bool
repoURL, ok = interceptVCSTest(repo, vcs, security)
if !ok {
scheme, err := func() (string, error) {
for _, s := range vcs.Scheme {
if security == web.SecureOnly && !vcs.isSecureScheme(s) {
continue
}

// If we know how to ping URL schemes for this VCS,
// check that this repo works.
// Otherwise, default to the first scheme
// that meets the requested security level.
if vcs.PingCmd == "" {
return s, nil
}
if err := vcs.Ping(s, repo); err == nil {
return s, nil
}
}
if vcs.Ping(s, repo) == nil {
scheme = s
break
securityFrag := ""
if security == web.SecureOnly {
securityFrag = "secure "
}
return "", fmt.Errorf("no %sprotocol found for repository", securityFrag)
}()
if err != nil {
return nil, err
}
repoURL = scheme + "://" + repo
}
repoURL = scheme + "://" + repo
}
rr := &RepoRoot{
Repo: repoURL,
Expand All @@ -1177,6 +1210,51 @@ func repoRootFromVCSPaths(importPath string, security web.SecurityMode, vcsPaths
return nil, errUnknownSite
}

func interceptVCSTest(repo string, vcs *Cmd, security web.SecurityMode) (repoURL string, ok bool) {
if VCSTestRepoURL == "" {
return "", false
}
if vcs == vcsMod {
// Since the "mod" protocol is implemented internally,
// requests will be intercepted at a lower level (in cmd/go/internal/web).
return "", false
}

if scheme, path, ok := strings.Cut(repo, "://"); ok {
if security == web.SecureOnly && !vcs.isSecureScheme(scheme) {
return "", false // Let the caller reject the original URL.
}
repo = path // Remove leading URL scheme if present.
}
for _, host := range VCSTestHosts {
if !str.HasPathPrefix(repo, host) {
continue
}

httpURL := VCSTestRepoURL + strings.TrimPrefix(repo, host)

if vcs == vcsSvn {
// Ping the vcweb HTTP server to tell it to initialize the SVN repository
// and get the SVN server URL.
u, err := urlpkg.Parse(httpURL + "?vcwebsvn=1")
if err != nil {
panic(fmt.Sprintf("invalid vcs-test repo URL: %v", err))
}
svnURL, err := web.GetBytes(u)
svnURL = bytes.TrimSpace(svnURL)
if err == nil && len(svnURL) > 0 {
return string(svnURL) + strings.TrimPrefix(repo, host), true
}

// vcs-test doesn't have a svn handler for the given path,
// so resolve the repo to HTTPS instead.
}

return httpURL, true
}
return "", false
}

// urlForImportPath returns a partially-populated URL for the given Go import path.
//
// The URL leaves the Scheme field blank so that web.Get will try any scheme
Expand Down
28 changes: 28 additions & 0 deletions src/cmd/go/testdata/script/mod_insecure_issue63845.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Regression test for https://go.dev/issue/63845:
# If 'git ls-remote' fails for all secure protocols,
# we should fail instead of falling back to an arbitrary protocol.
#
# Note that this test does not use the local vcweb test server
# (vcs-test.golang.org), because the hook for redirecting to that
# server bypasses the "ping to determine protocol" logic
# in cmd/go/internal/vcs.

[!net] skip
[!git] skip
[short] skip 'tries to access a nonexistent external Git repo'

env GOPRIVATE=golang.org
env CURLOPT_TIMEOUT_MS=100
env GIT_SSH_COMMAND=false

! go get -x golang.org/nonexist.git@latest
stderr '^git ls-remote https://golang.org/nonexist$'
stderr '^git ls-remote git\+ssh://golang.org/nonexist'
stderr '^git ls-remote ssh://golang.org/nonexist$'
! stderr 'git://'
stderr '^go: golang.org/nonexist.git@latest: no secure protocol found for repository$'

-- go.mod --
module example

go 1.19

0 comments on commit 2043cf7

Please sign in to comment.