Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: cmd/go: improve ability to fetch insecure dependencies #32966

Open
witchard opened this issue Jul 6, 2019 · 14 comments

Comments

@witchard
Copy link

commented Jul 6, 2019

As discussed in #32104, #31741 and #27332; there is sometimes a need for users to fetch dependencies in an insecure manner (e.g. where dependencies are on servers with certificates that are not trusted by the system, or where the server is not https at all). The current go get command supports a -insecure flag for this use-case; however this is not supported by the new go mod commands. The -insecure flag is probably overkill in most cases and could lead to users fetching dependencies insecurely by accident.

I propose the addition of two new environment variables that would be used by all commands fetching dependencies. The first of these would provide the go tools with additional CA certificates to trust (in situations where the user is unable to modify the system trust, or where they only want to trust a certificate for the duration of the go command). The second would list servers where insecure fetching is allowed. For example, these could be:

  • GOTRUST=pathToCA1.pem,pathToCA2.pem - Defines a comma separated list of CA certificate files to trust along side the system ones.
  • GOINSECURE=foo.com,*.bar.com - Defines a comma separated list of hostnames (possibly with globs) where insecure fetches (I guess either over https due to untrusted authority, or over http) are allowed.

If this were implemented, then I would also propose the removal of the -insecure flag from go get.

I would be willing to work on this issue if it were accepted, but I don't really know where to start!

@gopherbot gopherbot added this to the Proposal milestone Jul 6, 2019

@gopherbot gopherbot added the Proposal label Jul 6, 2019

@bcmills bcmills added the modules label Jul 11, 2019

@bcmills

This comment has been minimized.

Copy link
Member

commented Jul 11, 2019

What's the use-case for GOTRUST? (Under what conditions would you want to build — and likely run — arbitrary source code signed by a CA that you don't trust enough to add to your system roots?)

@bcmills

This comment has been minimized.

Copy link
Member

commented Jul 11, 2019

@witchard

This comment has been minimized.

Copy link
Author

commented Jul 12, 2019

The only situation I can think of is if a user does not have permission to modify their system trust. Pythons pip tool has similar options (https://pip.pypa.io/en/stable/reference/pip/#general-options), trusted-host is similar to GO_INSECURE and cert similar to GO_TRUST.

@rsc rsc changed the title proposal: improve ability to fetch insecure dependencies proposal: cmd/go: improve ability to fetch insecure dependencies Jul 16, 2019

@ernestoaparicio

This comment has been minimized.

Copy link

commented Jul 30, 2019

Second this. Ran into an issue using Athens go proxy because it uses go mod download and that doesn't support --insecure.

@FiloSottile

This comment has been minimized.

Copy link
Member

commented Jul 31, 2019

I am in favor of GOINSECURE.

GOTRUST is complicated. On Windows, for example, we don't get to mix system and custom roots, because system verification is performed by calling the system API. We probably can get there by attempting two verifications in VerifyPeerCertificate.

I'd like to hear more support for the use case before introducing complexity for it. (But OTOH I don't want users reverting to GOINSECURE when unnecessary.)

@witchard

This comment has been minimized.

Copy link
Author

commented Jul 31, 2019

Ah interesting, I hadn’t appreciated that complexity. I wonder if GOTRUST could be of some form like host1:certfile1,host2:certfile2,... so you could then choose a custom cert for specific hosts; and then it would only use that cert for access to that host and not touch system ones? The env variable looks a bit more complex though.

I agree that forcing a users to use GOINSECURE to access a resource
that they just haven’t got a mechanism to trust a cert for is a bit odd.

@xrfang

This comment has been minimized.

Copy link

commented Aug 22, 2019

A usecase for GOINSECURE is that the package is hosted on an Intranet. Is it possible to add a switch to allow inscure fetch for ALL intranet hosted packages?

@witchard

This comment has been minimized.

Copy link
Author

commented Aug 22, 2019

@xrfang - If all the intranet module sources share a common domain, e.g foo.company.org, bar.company.org then you’d just set it to *.company.org.

@xrfang

This comment has been minimized.

Copy link

commented Aug 23, 2019

@witchard my suggestion is not based on domain matching, but by IP address, if any domain is resolved to internal IPs, or a specific CIDR range, then it is considered internal.

I personally think it is not hard to implement, and might be useful.

@witchard

This comment has been minimized.

Copy link
Author

commented Aug 23, 2019

@xrfang oh I see, I guess that could work - so you’d put something like 192.168.1.0/24 in GOINSECURE?

I wonder if anything similar has been considered for GONOSUMDB and GONOPROXY? I feel like the go team would probably want it to be consistent.

@FiloSottile

This comment has been minimized.

Copy link
Member

commented Aug 23, 2019

if any domain is resolved to internal IPs, or a specific CIDR range, then it is considered internal

That would not be secure. DNS resolution is ordinarily unsecured, so with such a configuration option enabled all an attacker would have to do to downgrade security for a package would be to fake its IP address. It's also unclear to me what use cases that addresses that can't be addressed with a GOINSECURE list.

@witchard

This comment has been minimized.

Copy link
Author

commented Aug 24, 2019

Based on the comments so far then, would it make sense to proceed with just GOINSECURE?

GOINSECURE would be defined as: a comma separated list of hostnames (with globs) where insecure fetches (either over https due to untrusted authority, or over http) are allowed. Example: GOINSECURE=foo.com,*.bar.com.

GOTRUST and anything based on ip subnets out of scope for now.

@xrfang

This comment has been minimized.

Copy link

commented Aug 24, 2019

@witchard this means, to achieve what I want, I just set GOTRUST=192.168.0.0/24, and leave GOINSECURE empty. Then any package repo that resolve to that ip range will be considered trusted, and allow an http fetch?

@FiloSottile yes it is insecure, but I don't think it will be even more insecure to specify ip range than to specify package names. Both relies on DNS anyway.

@witchard

This comment has been minimized.

Copy link
Author

commented Aug 24, 2019

@xrfang what @FiloSottile is saying is that a malicious actor on your network could modify DNS to point github.com at a local IP and then (if you had GOINSECURE for local IPs) they could get control of your packages from github.com. This wouldn’t be good and so having a blanket setting for local IPs is probably not a good idea. I.e. it is less secure to allow IP ranges in GOINSECURE.

GOINSECURE is essentially saying “I know packages from this domain are not coming to me over a trusted channel”. Therefore a malicious actor on your network could give you malicious packages for that domain, but for that domain only - and other packages from other domains are still protected.

As such the only way you’d achieve what you want would only be to put all the domains for your local packages in GOINSECURE I’m afraid.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants
You can’t perform that action at this time.