Detecting Vulnerabilities in Go Code
When writing software, one might, accidentally (or not), ship the software with vulnerabilities, which are broadly defined as flaws or weaknesses in code that can be exploited by an attacker. We do not want to have those in our Go code so we need some way of minimizing the number of vulnerabilities our code has. Fortunately there are tools built by the Go community and team that can be leveraged for this.
CWEs and CVEs
Before introducing Go tools to make your code more secure, it is important to clarify two concepts that are commonly used in the infosec industry: CWE and CVE. The first stands for Common Weakness Enumeration and refers to a catalog of weaknesses in software components. It is important to keep in mind that this does not refer to specific instances of vulnerabilities, but rather types of weaknesses that are usually found in software, hardware or firmware. The second term stands for Common Vulnerabilities and Exposures, and is a standard for identifying and distributing information on vulnerabilities on specific instances of products or systems.
gosec
A popular Go tool that is sometimes ran as a linter, gosec
scans your code’s abstract syntax tree for security problems. Since this works by examining an AST and is programmed as a set of rules, it is limited in its detection scope. In fact, at the time of writing this article, it can only detect 34 issues. Moreover, each of these possible detections is mapped into a CWE, as described in gosec
’s GitHub repository.
govulncheck
Created by the Go security team, govulncheck
is a bit more sophisticated than gosec
. The Go security team gather data on known CVEs from multiple sources, puts these through a curation process, and makes this information publicly available. Moveover, this team also built the govulncheck
tool, which allows us to check for these known vulnerabilities via source code inspection. However, if we really want to, it can also analyse binaries, but at the expense of information on call stacks.
Why you should run both these tools
gosec
looks for known CWEs, which may or may not result in CVEs, while govulncheck
looks for known CVEs, making this pair a powerful stack to improve the security of you code. Let us craft an example where we can see these tools in action and how they differ. Create a new Go project, with version 1.19 (this is important, otherwise you will not be able to reproduce this), and place the following code in your main.go
file:
|
|
This will be our test subject. At a glance, there seems to be nothing wrong with our code, but let us see what gosec
and govulncheck
have to say about that. After following the documentation and installing these tools, they are fairly easy to run. Let us start by looking for CWEs with gosec
, which can be done via the following command:
|
|
When we run this, we get the following output:
|
|
This tool immediately flagged the piece of code we were using to display a random number. Of course, for what the code does, this is a false positive result, but that isn’t always the case (and this is for illustrative purposes only). We can just as easily run govulncheck
with:
|
|
Which, in turn, outputs the following report:
|
|
Not only does it inform us on a vulnerability our code has, but it also informs us on vulnerabilities that our code might end up having due the existence of known CVEs in functions of the packages we are importing but not reached by our call stack. In this case, we can also see when the vulnerability our code has was fixed, which was in Go v1.20.5.
While we are running these tools out-of-the-box in our terminal, note that they also support several output formats that are more easily processed by other programs and also have amazing integrations with popular IDEs and text editors, so you can ran these tools every time you save a file instead of waiting for some CI build to perform these detections for you, which is pretty neat.
References
gosec
- https://github.com/securego/gosecgovulncheck
- https://go.googlesource.com/vuln