I love the Go programming language. It’s easy to use, concise and powerful. These characteristics appeal to the typical programmer’s mindset.
Yet, the brevity of the language can be a source of frustration. For example, the core “json” package converts JSON to Go structures yet does nothing to automate this process. If you have a large JSON document to consume, you’ll be writing the corresponding Go structures by hand.
Fortunately, Go makes it easy to develop ancillary packages and share them with the world. The build system understands Git repositories and Go source code refers directly to projects on Github and other sites. This means you can create a funky widget, upload it to github.com/yourname/funky, and Go programmers can start using it.
Thus to solve the problem above, I can turn to https://github.com/ChimeraCoder/gojson, which automatically generates Go data structures that match a JSON document. It’s got two thousand stars at the time of writing, which means it’s been useful to a lot of people.
Another example of a language deficit can be found in the crypto packages. Go provides the bare bones necessary to do symmetric encryption, but it doesn’t support adding padding to the plaintext. Other languages, such as Java, routinely offer this functionality. Fortunately, the community has plugged the gap, with packages such as https://github.com/fullsailor/pkcs7 offering missing pieces.
As a result of this lean-and-mean language approach, the average Go program relies on dozens of open-source projects to get things done. Each of those direct dependencies will rely on its own collection of open-source projects. Consequently, a huge web of third-party software underpins every non-trivial Go program.
This is a nightmare from a software-license perspective. You can check the license for the projects you import directly, but what about all the transitive dependencies? Is there something buried away that has a non-commercial license? Or what about having no license at all? That would probably worry the legal folks in your company. The Go community has developed some tools to help with this problem (such as https://github.com/mitchellh/golicense) but it remains more of an art than a science.
Another concern is reproducibility of builds. Go modules make this easier by tracking the minimum required version of dependencies and comparing hashes to maintain integrity. But this doesn’t solve the availability issue. If Johnny McLibrary decide to delete his Github account, what happens then? In the best case, someone uploads a fork and the community updates their dependencies, but that can get painful quickly. An alternative is to embrace vendoring, in which a project uploads copies of all its dependencies into version control and builds directly from that cache.
Finally, code quality should be considered. It becomes infeasible to vet the quality of imported packages as a project scales. As a result, testing (and fuzzing) of your resulting program becomes even more important to indirectly hunt for bugs in the supporting packages.
These problems exist in other programming languages. Nevertheless, the minimalist language design and the ease with which programmers can build and share composite packages means Go programs have unusually high dependencies on unvetted third-party software. This has impacts for software integrity and security, which need to be managed carefully.
For more information, please visit our Horizons research website. Horizons explores and prototypes new data security technologies and techniques, particularly in distributed cloud environments. Findings are shared publicly, whenever possible, to further the advancement of the information security community.