1
0
mirror of https://github.com/golang/go synced 2024-11-19 18:54:41 -07:00

cmd/go: fix command injection in VCS path

Fixes #23867, CVE-2018-7187

Change-Id: I5d0ba4923c9ed354ef76290e149c182447f9dfe2
Reviewed-on: https://go-review.googlesource.com/94656
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
Arthur Khashaev 2018-02-12 03:28:12 +03:00 committed by Ian Lance Taylor
parent c941e27e70
commit 1102616c77
2 changed files with 29 additions and 45 deletions

View File

@ -809,7 +809,7 @@ func repoRootForImportDynamic(importPath string, security web.SecurityMode) (*re
} }
} }
if err := validateRepoRootScheme(mmi.RepoRoot); err != nil { if err := validateRepoRoot(mmi.RepoRoot); err != nil {
return nil, fmt.Errorf("%s: invalid repo root %q: %v", urlStr, mmi.RepoRoot, err) return nil, fmt.Errorf("%s: invalid repo root %q: %v", urlStr, mmi.RepoRoot, err)
} }
rr := &repoRoot{ rr := &repoRoot{
@ -824,33 +824,16 @@ func repoRootForImportDynamic(importPath string, security web.SecurityMode) (*re
return rr, nil return rr, nil
} }
// validateRepoRootScheme returns an error if repoRoot does not seem // validateRepoRoot returns an error if repoRoot does not seem to be
// to have a valid URL scheme. At this point we permit things that // a valid URL with scheme.
// aren't valid URLs, although later, if not using -insecure, we will func validateRepoRoot(repoRoot string) error {
// restrict repoRoots to be valid URLs. This is only because we've url, err := url.Parse(repoRoot)
// historically permitted them, and people may depend on that. if err != nil {
func validateRepoRootScheme(repoRoot string) error { return err
end := strings.Index(repoRoot, "://") }
if end <= 0 { if url.Scheme == "" {
return errors.New("no scheme") return errors.New("no scheme")
} }
// RFC 3986 section 3.1.
for i := 0; i < end; i++ {
c := repoRoot[i]
switch {
case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
// OK.
case '0' <= c && c <= '9' || c == '+' || c == '-' || c == '.':
// OK except at start.
if i == 0 {
return errors.New("invalid scheme")
}
default:
return errors.New("invalid scheme")
}
}
return nil return nil
} }

View File

@ -417,45 +417,46 @@ func TestMatchGoImport(t *testing.T) {
} }
} }
func TestValidateRepoRootScheme(t *testing.T) { func TestValidateRepoRoot(t *testing.T) {
tests := []struct { tests := []struct {
root string root string
err string ok bool
}{ }{
{ {
root: "", root: "",
err: "no scheme", ok: false,
}, },
{ {
root: "http://", root: "http://",
err: "", ok: true,
}, },
{ {
root: "a://", root: "git+ssh://",
err: "", ok: true,
}, },
{ {
root: "a#://", root: "http#://",
err: "invalid scheme", ok: false,
},
{
root: "-config",
ok: false,
}, },
{ {
root: "-config://", root: "-config://",
err: "invalid scheme", ok: false,
}, },
} }
for _, test := range tests { for _, test := range tests {
err := validateRepoRootScheme(test.root) err := validateRepoRoot(test.root)
if err == nil { ok := err == nil
if test.err != "" { if ok != test.ok {
t.Errorf("validateRepoRootScheme(%q) = nil, want %q", test.root, test.err) want := "error"
if test.ok {
want = "nil"
} }
} else if test.err == "" { t.Errorf("validateRepoRoot(%q) = %q, want %s", test.root, err, want)
if err != nil {
t.Errorf("validateRepoRootScheme(%q) = %q, want nil", test.root, test.err)
}
} else if err.Error() != test.err {
t.Errorf("validateRepoRootScheme(%q) = %q, want %q", test.root, err, test.err)
} }
} }
} }