Go has indisputably the best package integrity story of any programming language ecosystem. The Go Checksum Database guarantees that every Go client in the world is using the same source for a given Go module and version, forever.
It works despite the decentralized nature of Go modules, which can be fetched directly from their origin based on the import path. (For example, you can fetch v1.2.3 of github.com/example/mod by cloning the git repository and exporting the v1.2.3 tag. GOPROXY=direct forces this.)
The Checksum Database stores the cryptographic hash of a module version the first time it is used across the ecosystem, and then provides that same checksum to every Go client going forward. If e.g. a git tag were force-pushed or a code host were to try to serve targeted versions to some clients, the go tool would notice the mismatch and fail the fetch.
This is vastly more practical than requiring module authors to manage keys, but provides comparable security, because the author themselves can verify the checksum in the Checksum Database matches the one they developed. Moreover, the Checksum Database is a transparency log, which prevents even the database operator (i.e. Google) from falsifying or hiding entries.
However, any time we read code directly from the code host we introduce a weak link in this chain. For example, there is no guarantee that the code displayed at https://github.com/example/mod/blob/v1.2.3/exp.go is the actual contents of exp.go from v1.2.3 of module github.com/example/mod : GitHub allows force-pushing git tags and even built its recommended GitHub Actions workflows on top of mutable tags.
Last year this was taken advantage of to make a classic typosquatting attack harder to identify. A fake BoltDB module was published with malicious code, and then innocent code was force-pushed to GitHub. Some commenters described this as exploiting the Go Modules Mirror’s cache, but it is better understood as exploiting the natural lack of verification in the GitHub web interface, which doesn’t show the authentic (and in this case malicious) source of a module version, as used by actual Go tooling.
The solution when reviewing modules locally is to use a command like
cd $(go mod download -json filippo.io/[email protected] | jq -r .Dir)
to fetch the correct source. We are also working on a go mod verify -tag command to verify the contents of a local git repository against the Go Checksum Database, which can also be used by module authors to check that the contents of the Checksum Database are correct.
However, pkg.go.dev still links to unverified code hosts, and clicking on pkg.go.dev source links is very convenient.
... continue reading