# Go Proxy Security, Part 1: A critical piece of infrastructure
Thursday, 29. June 2023


When pulling dependencies for Go via go mod, the dataflows are not obvious for the user. You `import` a `github.com/…`
and the rest happens automatically.

In the default settings, go pulls these dependencies from proxy.golang.org, not from github.com.

This solves one issue in Software Supply Chains: Vanishing dependencies.

When the [npm package left-pad was removed](https://www.theregister.com/2016/03/23/npm_left_pad_chaos/) from npm, this
led to failing builds around the globe. It was one of many supply chain disasters.

In Go, you have three major options to prevent the dependency on inaccessible packages:

- Use a `/vendor` folder and store the dependencies together with your source code
- [Selfhost a goproxy server](https://github.com/goproxy/goproxy)
- Use the proxy.golang.org proxy server

Let’s shine more light on the proxy.golang.org proxy server since it is the only option that is not under our control.

> With the command `go env` you can find the settings for GOPROXY, GOSUMDB and GOPRIVATE.

## Security considerations

An attacker on a proxy server is the classical man-in-the-middle. They can modify the content that is sent to clients
and they can send different versions of content to different clients for targeted attacks.

Without further protection, clients put their ultimate trust in the proxy.

The implementation of proxies in *go mod* is secured with gosumdb. The integrity of dependencies is verified with
multiple cryptographical secure hash sums that are stored in gosumdb.
Gosumdb has an API to provide the contents of the underlying data structure, which is a Merkle Tree.

Merkle Trees are append-only data structures. Once inserted, the data becomes immutable.
This can be cryptographically proven. Go locally verifies the integrity of each and every
dependency it pulls with the help of gosumdb.

A typical dependency request looks like this:

1. Client requests the dependency from the proxy server (Proxy server requests the dependency from the upstream server,
   if not cached already)
2. Client requests the checksums from gosumdb (Gosumdb will calculate the checksum on-the-fly if it is not stored
   already)
3. Client verifies parts of the Merkle Tree locally
4. If the cryptographic checks are successful, and the checksum of the dependency is valid too, the dependency is used

There is much more to say about the details of how go verifies the integrity of dependencies. In Part 2 of this series,
I'll explain the cryptographic concepts of gosumdb.


By Raphael Sprenger
