Skip to content

Commit c018eec

Browse files
committed
cmd/go: add GOVCS setting to control version control usage
The go command runs commands like git and hg to download modules. In the past, we have had problems with security bugs in version control systems becoming security bugs in “go get”. The original modules draft design removed use of these commands entirely, saying: > We want to move away from invoking version control tools such as bzr, > fossil, git, hg, and svn to download source code. These fragment the > ecosystem: packages developed using Bazaar or Fossil, for example, are > effectively unavailable to users who cannot or choose not to install > these tools. The version control tools have also been a source of > exciting security problems. It would be good to move them outside the > security perimeter. The removal of these commands was not possible in the end: being able to fetch directly from Git repos is too important, especially for closed source. But the security exposure has not gone away. We remain vulnerable to problems in VCS systems, especially the less scrutinized ones. This change adds a GOVCS setting to let users control which version control systems are allowed by default. It also changes the default allowed version control systems to git and hg for public code and any version control system for private code (import path or module path matched by the GOPRIVATE setting). See the changes in alldocs.go for detailed documentation. See #41730 for proposal and discussion. Fixes #41730. Change-Id: I1999ddf7445b36a7572965be5897c7a1ff7f4265 Reviewed-on: https://go-review.googlesource.com/c/go/+/266420 Trust: Russ Cox <[email protected]> Run-TryBot: Russ Cox <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Jay Conrod <[email protected]>
1 parent 63fd764 commit c018eec

File tree

12 files changed

+642
-56
lines changed

12 files changed

+642
-56
lines changed

src/cmd/go/alldocs.go

Lines changed: 128 additions & 49 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cmd/go/internal/cfg/cfg.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ var (
268268
GONOPROXY = envOr("GONOPROXY", GOPRIVATE)
269269
GONOSUMDB = envOr("GONOSUMDB", GOPRIVATE)
270270
GOINSECURE = Getenv("GOINSECURE")
271+
GOVCS = Getenv("GOVCS")
271272
)
272273

273274
var SumdbDir = gopathDir("pkg/sumdb")

src/cmd/go/internal/envcmd/env.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ func MkEnv() []cfg.EnvVar {
8787
{Name: "GOSUMDB", Value: cfg.GOSUMDB},
8888
{Name: "GOTMPDIR", Value: cfg.Getenv("GOTMPDIR")},
8989
{Name: "GOTOOLDIR", Value: base.ToolDir},
90+
{Name: "GOVCS", Value: cfg.GOVCS},
9091
}
9192

9293
if work.GccgoBin != "" {

src/cmd/go/internal/help/helpdoc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,7 @@ General-purpose environment variables:
526526
Comma-separated list of glob patterns (in the syntax of Go's path.Match)
527527
of module path prefixes that should always be fetched directly
528528
or that should not be compared against the checksum database.
529-
See 'go help module-private'.
529+
See 'go help private'.
530530
GOROOT
531531
The root of the go tree.
532532
GOSUMDB

src/cmd/go/internal/modfetch/fetch.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -848,16 +848,16 @@ the checksum database is not consulted, and all unrecognized modules are
848848
accepted, at the cost of giving up the security guarantee of verified repeatable
849849
downloads for all modules. A better way to bypass the checksum database
850850
for specific modules is to use the GOPRIVATE or GONOSUMDB environment
851-
variables. See 'go help module-private' for details.
851+
variables. See 'go help private' for details.
852852
853853
The 'go env -w' command (see 'go help env') can be used to set these variables
854854
for future go command invocations.
855855
`,
856856
}
857857

858-
var HelpModulePrivate = &base.Command{
859-
UsageLine: "module-private",
860-
Short: "module configuration for non-public modules",
858+
var HelpPrivate = &base.Command{
859+
UsageLine: "private",
860+
Short: "configuration for downloading non-public code",
861861
Long: `
862862
The go command defaults to downloading modules from the public Go module
863863
mirror at proxy.golang.org. It also defaults to validating downloaded modules,
@@ -898,6 +898,11 @@ be used for downloading both public and private modules, because
898898
GONOPROXY has been set to a pattern that won't match any modules,
899899
overriding GOPRIVATE.
900900
901+
The GOPRIVATE variable is also used to define the "public" and "private"
902+
patterns for the GOVCS variable; see 'go help vcs'. For that usage,
903+
GOPRIVATE applies even in GOPATH mode. In that case, it matches import paths
904+
instead of module paths.
905+
901906
The 'go env -w' command (see 'go help env') can be used to set these variables
902907
for future go command invocations.
903908
`,

src/cmd/go/internal/modget/get.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,82 @@ Usage: ` + CmdGet.UsageLine + `
176176
` + CmdGet.Long,
177177
}
178178

179+
var HelpVCS = &base.Command{
180+
UsageLine: "vcs",
181+
Short: "controlling version control with GOVCS",
182+
Long: `
183+
The 'go get' command can run version control commands like git
184+
to download imported code. This functionality is critical to the decentralized
185+
Go package ecosystem, in which code can be imported from any server,
186+
but it is also a potential security problem, if a malicious server finds a
187+
way to cause the invoked version control command to run unintended code.
188+
189+
To balance the functionality and security concerns, the 'go get' command
190+
by default will only use git and hg to download code from public servers.
191+
But it will use any known version control system (bzr, fossil, git, hg, svn)
192+
to download code from private servers, defined as those hosting packages
193+
matching the GOPRIVATE variable (see 'go help private'). The rationale behind
194+
allowing only Git and Mercurial is that these two systems have had the most
195+
attention to issues of being run as clients of untrusted servers. In contrast,
196+
Bazaar, Fossil, and Subversion have primarily been used in trusted,
197+
authenticated environments and are not as well scrutinized as attack surfaces.
198+
199+
The version control command restrictions only apply when using direct version
200+
control access to download code. When downloading modules from a proxy,
201+
'go get' uses the proxy protocol instead, which is always permitted.
202+
By default, the 'go get' command uses the Go module mirror (proxy.golang.org)
203+
for public packages and only falls back to version control for private
204+
packages or when the mirror refuses to serve a public package (typically for
205+
legal reasons). Therefore, clients can still access public code served from
206+
Bazaar, Fossil, or Subversion repositories by default, because those downloads
207+
use the Go module mirror, which takes on the security risk of running the
208+
version control commands, using a custom sandbox.
209+
210+
The GOVCS variable can be used to change the allowed version control systems
211+
for specific packages (identified by a module or import path).
212+
The GOVCS variable applies both when using modules and when using GOPATH.
213+
When using modules, the patterns match against the module path.
214+
When using GOPATH, the patterns match against the import path
215+
corresponding to the root of the version control repository.
216+
217+
The general form of the GOVCS setting is a comma-separated list of
218+
pattern:vcslist rules. The pattern is a glob pattern that must match
219+
one or more leading elements of the module or import path. The vcslist
220+
is a pipe-separated list of allowed version control commands, or "all"
221+
to allow use of any known command, or "off" to allow nothing.
222+
The earliest matching pattern in the list applies, even if later patterns
223+
might also match.
224+
225+
For example, consider:
226+
227+
GOVCS=github.com:git,evil.com:off,*:git|hg
228+
229+
With this setting, code with an module or import path beginning with
230+
github.com/ can only use git; paths on evil.com cannot use any version
231+
control command, and all other paths (* matches everything) can use
232+
only git or hg.
233+
234+
The special patterns "public" and "private" match public and private
235+
module or import paths. A path is private if it matches the GOPRIVATE
236+
variable; otherwise it is public.
237+
238+
If no rules in the GOVCS variable match a particular module or import path,
239+
the 'go get' command applies its default rule, which can now be summarized
240+
in GOVCS notation as 'public:git|hg,private:all'.
241+
242+
To allow unfettered use of any version control system for any package, use:
243+
244+
GOVCS=*:all
245+
246+
To disable all use of version control, use:
247+
248+
GOVCS=*:off
249+
250+
The 'go env -w' command (see 'go help env') can be used to set the GOVCS
251+
variable for future go command invocations.
252+
`,
253+
}
254+
179255
var (
180256
getD = CmdGet.Flag.Bool("d", false, "")
181257
getF = CmdGet.Flag.Bool("f", false, "")

src/cmd/go/internal/modload/help.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,7 @@ list if the error is a 404 or 410 HTTP response or if the current proxy is
365365
followed by a pipe character, indicating it is safe to fall back on any error.
366366
367367
The GOPRIVATE and GONOPROXY environment variables allow bypassing
368-
the proxy for selected modules. See 'go help module-private' for details.
368+
the proxy for selected modules. See 'go help private' for details.
369369
370370
No matter the source of the modules, the go command checks downloads against
371371
known checksums, to detect unexpected changes in the content of any specific

0 commit comments

Comments
 (0)