Govulncheck

On September 7, 2022, the Go security team published the article “Vulnerability Management for Go” on the official Go blog, officially introducing all Gophers to Go’s tools and solutions for security vulnerability management.

In this article, the Go security team introduces a command line tool called govulncheck. This tool is essentially just a front-end to the Go vulnerability database, which scans the Go source code or compiled Go application executable binaries in your repository through the vulncheck package under the officially maintained vuln repository, forming a callgraph of the source code and callstack.

Go Security Vulnerability Solution Architecture

From Go official blog

You can also develop your own vulnerability inspection front-end based on the vulncheck package, client package, etc. under the vuln repository, or integrate it into your organization’s internal toolchain.

Like sumdb, proxy, etc., Go officially maintains a default vulnerability database, vuln.go.dev, as shown above, which accepts data from well-known vulnerability data sources, such as: NVD, GHSA, etc., vulnerabilities discovered and fixed by the Go security team, and vulnerabilities submitted by maintainers of the most extensive go open source projects.

If you are a maintainer of a well-known go open source project, when you find and fix a vulnerability in your project, you can find the submission/reporting portal for different types of vulnerabilities at Go Vulnerability Management Page, and the Go security team will review and confirm the public vulnerability information you report.

Well, as Gopher, we are more concerned about whether there are security vulnerabilities in the Go projects we are developing, either from the Go compiler or from vulnerable third-party packages that we rely on. We need to learn to use the govulncheck tool to scan our projects.

govulncheck is currently maintained under golang.org/x/vuln, and according to the official blog, it will be released with the Go installer at a later date, but it is not known if it will be integrated into the go command. To use govulncheck now, we have to install it manually with the following command.

1
$ go install golang.org/x/vuln/cmd/govulncheck@latest

Once successfully installed, you can run the following command in the root directory of your Go project to check the entire project for vulnerabilities.

1
$ govulncheck ./...

Here are the results of my scan of my own project (golang version is Go 1.18).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
$ govulncheck ./...
govulncheck is an experimental tool. Share feedback at https://go.dev/s/govulncheck-feedback.

Scanning for dependencies with known vulnerabilities...
Found 9 known vulnerabilities.

Vulnerability #1: GO-2022-0524
  Calling Reader.Read on an archive containing a large number of
  concatenated 0-length compressed files can cause a panic due to
  stack exhaustion.

  Call stacks in your code:
      raft/fsm.go:193:29: example.com/go/mynamespace/demo1/raft.updOnlyLinearizableSM.RecoverFromSnapshot calls io/ioutil.ReadAll, which eventually calls compress/gzip.Reader.Read

  Found in: compress/gzip@go1.18
  Fixed in: compress/gzip@go1.18.4
  More info: https://pkg.go.dev/vuln/GO-2022-0524

Vulnerability #2: GO-2022-0531
  An attacker can correlate a resumed TLS session with a previous
  connection. Session tickets generated by crypto/tls do not
  contain a randomly generated ticket_age_add, which allows an
  attacker that can observe TLS handshakes to correlate successive
  connections by comparing ticket ages during session resumption.

  Call stacks in your code:
      raft/raft.go:68:35: example.com/go/mynamespace/demo1/raft.NewRaftNode calls github.com/lni/dragonboat/v3.NewNodeHost, which eventually calls crypto/tls.Conn.Handshake

  Found in: crypto/tls@go1.18
  Fixed in: crypto/tls@go1.18.3
  More info: https://pkg.go.dev/vuln/GO-2022-0531

... ...

Vulnerability #6: GO-2021-0057
  Due to improper bounds checking, maliciously crafted JSON
  objects can cause an out-of-bounds panic. If parsing user input,
  this may be used as a denial of service vector.

  Call stacks in your code:
      cmd/demo1/main.go:352:23: example.com/go/mynamespace/demo1/cmd/demo1.main calls example.com/go/mynamespace/common/naming.Register, which eventually calls github.com/buger/jsonparser.GetInt

  Found in: github.com/buger/jsonparser@v0.0.0-20181115193947-bf1c66bbce23
  Fixed in: github.com/buger/jsonparser@v1.1.1
  More info: https://pkg.go.dev/vuln/GO-2021-0057

... ...
Vulnerability #9: GO-2022-0522
  Calling Glob on a path which contains a large number of path
  separators can cause a panic due to stack exhaustion.

  Call stacks in your code:
      service/service.go:45:12: example.com/go/mynamespace/demo1/service.NewPubsubService calls example.com/go/mynamespace/common/log.Logger.Fatal, which eventually calls path/filepath.Glob

  Found in: path/filepath@go1.18
  Fixed in: path/filepath@go1.18.4
  More info: https://pkg.go.dev/vuln/GO-2022-0522

=== Informational ===

The vulnerabilities below are in packages that you import, but your code
doesn't appear to call any vulnerable functions. You may not need to take any
action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
for details.

Vulnerability #1: GO-2022-0537
  Decoding big.Float and big.Rat types can panic if the encoded message is
  too short, potentially allowing a denial of service.

  Found in: math/big@go1.18
  Fixed in: math/big@go1.18.5
  More info: https://pkg.go.dev/vuln/GO-2022-0537

... ...

Vulnerability #9: GO-2021-0052
  Due to improper HTTP header santization, a malicious user can spoof their
  source IP address by setting the X-Forwarded-For header. This may allow
  a user to bypass IP based restrictions, or obfuscate their true source.

  Found in: github.com/gin-gonic/gin@v1.6.3
  Fixed in: github.com/gin-gonic/gin@v1.7.7
  More info: https://pkg.go.dev/vuln/GO-2021-0052

We see that the output of govulncheck is divided into two parts: one part is the scanned project with security vulnerabilities for which you must fix, while the other part (separated by “=== Informational ===”) is a list of packages with security vulnerabilities that you directly import or indirectly depend on, but you do not directly You do not call the functions or methods in the vulnerable packages, so no remedial action is required. Thus, we only need to focus on the first part of the information.

Depending on the host where the vulnerability is located, the information in the first section can also be divided into two categories: those introduced by the Go language itself (including the Go compiler, Go runtime, and Go standard library), and those introduced by third-party packages (including direct dependencies and indirect dependencies).

For these two types of vulnerabilities, our solution is different.

The solution for the first type of vulnerability is very simple, directly upgrade the Go version, for example, here I upgrade my Go version from Go 1.18 to the latest Go 1.18.6 (just released on 2022.9.7) to eliminate all the first type of vulnerabilities above.

The second type of vulnerability, that is, vulnerabilities introduced by third-party packages, is a little more troublesome to eliminate.

We also look at it in two cases.

  • Security vulnerabilities in direct dependency packages

    If there is a security vulnerability in the code of the project’s direct dependency package, it is easier to follow the fix tips of govulncheck and directly upgrade (go get) to the corresponding version.

  • Security vulnerabilities in indirect dependency packages

    Suppose our project depends on package A, and package A depends on package B, and govulncheck happens to scan package B for vulnerabilities, and the function/method where the vulnerability is located is called by our project through package A. How do we fix it?

    Can we just upgrade the B package version? Not sure! This is related to the dependency management mechanism of the go module. The correct management of the go module requires that all package versions are truly semver compliant. If package B does not fully comply with the semver specification, once package B is upgraded separately, it is likely that package A will not be able to use the upgraded package B and our project will not compile. In this case, we should first consider upgrading package A. If package A is a base library under our control, such as common, we should first eliminate the vulnerability of package A (by upgrading the version of package B), and then eliminate such a vulnerability by upgrading the version of package A.

    If package A is not a package under our control, but a public open source package, then we also need to find out if package A has released a new version that fixes the vulnerability in package B. If we find it, we can directly upgrade package A to the new version to solve the problem.

    If package A does not fix the vulnerability of package B, then the problem is slightly more complicated. We can try to upgrade package B to fix it, and if it still can’t be fixed, then we either give PR to package A, or fork a copy of A, fix it ourselves and depend directly on the forked A.

    If this indirect dependency chain is long, then fixing such a vulnerability is indeed tedious, and we must be patient and upgrade the dependency package version from the direct dependency package down layer by layer.

The introduction of the govulncheck tool has enriched our means of checking projects for security vulnerabilities. If your project is open source on github, you can also use the github weekly security alert to obtain security vulnerability information (as shown in the following figure).

github weekly security alert to obtain security vulnerability information

And github provides a very convenient one-click fix solution.

For private commercial projects in your company, no matter what tools you used before for security scanning of the software supply chain, now that we have govulncheck, it is recommended to scan with it regularly.

Reference