In late 2023, the security team behind the Go programming language announced a serious vulnerability affecting how Go retrieves modules via go get. The issue has been cataloged as CVE-2023-45285, and it especially puts developers at risk if they’re not aware of how module fetching works behind the scenes.
Let’s take a closer look at what this bug means, how it can hurt your software, and concrete steps you should take to stay safe.
TL;DR
If you use go get to fetch a Go module with a .git suffix, and *if* the module cannot be fetched securely (via https:// or git+ssh://), Go automatically tries to fetch it using the insecure git:// protocol—even if you haven’t told it to (with things like GOINSECURE). This fallback *should not happen*, but it did, and attackers could abuse it, especially when you have GOPROXY=off and fetch modules directly from VCS systems.
Usually, Go prefers to fetch modules using secure protocols (HTTPS or SSH).
- When you go get example.com/repo.git, if Go can’t fetch over HTTPS or SSH, it tries to fetch using the unencrypted git:// protocol by default.
### Why Is git:// Bad?
The git:// protocol doesn’t support encryption or authentication. It's vulnerable to man-in-the-middle attacks, meaning someone on the network can intercept and change the code you’re downloading—even inject malware and supply chain attacks.
Suppose Alice sets GOPROXY=off and runs this command
go get evil.com/malicious.git
If Alice’s company firewall or the repo owner blocks HTTPS and SSH, Go will silently fall back to git://evil.com/malicious.git to try to get the code.
Now, if an attacker is on Alice’s network or able to hijack DNS, they can intercept this git:// connection and give Alice *their own malicious code*.
Set up your environment without a proxy
export GOPROXY=off
Now, try fetching a non-existing HTTPS server with a .git suffix
go get nonexist.example.com/repo.git
Check your network logs or use Wireshark: you’ll see that go get tries to connect to git://nonexist.example.com even if GOINSECURE is not set!
You fetch modules directly from VCS paths, especially those with a .git suffix
- The target module cannot be fetched over HTTPS or SSH, either due to config issues or deliberate blocking
- Most Go users fetch modules through the default proxy (proxy.golang.org), which is *safe* from this fallback issue.
The Technical Details
Here’s why this fallback happened, summarized from Go’s security advisory:
> The Go command falls back to the “git://” protocol if fetching a module from a repo with a ‘.git’ suffix fails over more secure protocols, even if this wasn’t allowed by GOINSECURE.
The code flow in Go's module fetch logic tried the following, in order
1. https://
2. git+ssh://
3. git:// (insecure, shouldn’t be used unless explicitly okay’d)
The bug: The fallback to git:// was triggered for .git URLs regardless of settings.
Upgrade your Go version:
- Fixed in Go 1.21.4 and 1.20.11 (release notes)
Fix Confirmation
After upgrading to a patched Go version, running the above go get commands will not fall back to git://.
References
- CVE-2023-45285 - NVD
- Go Security Advisory - November 2023
- Go Issue Tracker: go get fetches modules via git:// without warning
- Go Blog - Module Proxy
In Short
CVE-2023-45285 is a real risk for Go developers fetching modules directly, especially in CI/CD or behind firewalls. If you don’t use the module proxy and work with .git modules, you could be pulling code over an unencrypted connection. Make sure your Go install is up-to-date, and prefer secure fetching at all times.
Timeline
Published on: 12/06/2023 17:15:07 UTC
Last modified on: 01/20/2024 04:15:08 UTC