iTranslated by AI
Official Go Vulnerability Management System
Go Vulnerability Management
While browsing my Twitter timeline, I discovered that there is an official Go vulnerability report page.
When I posted about this here:
I received some information as shown here:
Thank you very much! 🙇
Looking at the page in question, it seems they manage vulnerabilities like this:
via “Go Vulnerability Management - The Go Programming Language”
The explanations for each number are as follows:
- A data pipeline that populates the vulnerability database. Data about new vulnerabilities come directly from Go package maintainers or sources such as MITRE and GitHub. Reports are curated by the Go Security team.
- A vulnerability database that stores all information presented by govulncheck and can be consumed by other clients.
- A client library (golang.org/x/vuln/client), which reads data from the Go vulnerability database. This is also used by pkg.go.dev to surface vulnerabilities.
- A vulncheck API (golang.org/x/vuln/vulncheck), which is used to find vulnerabilities affecting Go packages and perform static analysis. This API is made available for clients that do not want to run the govulncheck binary, such as VS Code Go.
- The govulncheck command (golang.org/x/vuln/cmd/govulncheck, a wrapper around the vulncheck library for use on the command line.
- A web portal that presents information about vulnerabilities, hosted at pkg.go.dev/vuln.
I suspect those involved in static analysis for Go would be interested in things like the client library or the vulncheck API, but for this article, I would like to try out the govulncheck command-line tool for its ease of use.
Trying out govulncheck
To install govulncheck, first prepare a Go build environment and run:
$ go install golang.org/x/vuln/cmd/govulncheck@latest
go: downloading golang.org/x/vuln v0.0.0-20220810233855-e1dd057bf2a3
...
The build result will be output to the $GOPATH/bin or $GOBIN directory[1]. Let's try displaying the help using the -h option for now.
$ govulncheck -h
govulncheck: identify known vulnerabilities by call graph traversal.
Usage:
govulncheck [flags] {package pattern...}
govulncheck [flags] {binary path} (if built with Go 1.18 or higher)
Flags:
-json Print vulnerability findings in JSON format.
-html Generate HTML with the vulnerability findings.
-tags Comma-separated list of build tags.
-tests Boolean flag indicating if test files should be analyzed too.
govulncheck can be used with either one or more package patterns (i.e. golang.org/x/crypto/...
or ./...) or with a single path to a Go binary. In the latter case module and symbol
information will be extracted from the binary to detect vulnerable symbols.
The environment variable GOVULNDB can be set to a comma-separated list of vulnerability
database URLs, with http://, https://, or file:// protocols. Entries from multiple
databases are merged.
I see. It can also output in JSON format. Let's try it right away. First, I'll test it in my local depm development environment.
$ cd ~/path/to/depm
$ govulncheck ./...
govulncheck is an experimental tool. Share feedback at https://go.dev/s/govulncheck-feedback.
Scanning for dependencies with known vulnerabilities...
No vulnerabilities found.
Great. It looks fine. Next, I'll try outputting in JSON format.
$ govulncheck -json ./...
{
"Calls": {
"Functions": {},
"Entries": null
},
"Imports": {
"Packages": {},
"Entries": null
},
"Requires": {
"Modules": {},
"Entries": null
},
"Vulns": null,
"Modules": [
{
"Path": "github.com/BurntSushi/toml",
"Version": "v1.2.0",
"Dir": "",
"Replace": null
},
{
"Path": "github.com/davecgh/go-spew",
"Version": "v1.1.1",
"Dir": "",
"Replace": null
},
{
"Path": "github.com/emicklei/dot",
"Version": "v1.0.0",
"Dir": "",
"Replace": null
},
{
"Path": "github.com/goark/depm",
"Version": "",
"Dir": "",
"Replace": null
},
{
"Path": "github.com/goark/errs",
"Version": "v1.1.0",
"Dir": "",
"Replace": null
},
{
"Path": "github.com/goark/gocli",
"Version": "v0.12.0",
"Dir": "",
"Replace": null
},
{
"Path": "github.com/google/licenseclassifier/v2",
"Version": "v2.0.0-pre6",
"Dir": "",
"Replace": null
},
{
"Path": "github.com/sergi/go-diff",
"Version": "v1.2.0",
"Dir": "",
"Replace": null
},
{
"Path": "github.com/spf13/cobra",
"Version": "v1.5.0",
"Dir": "",
"Replace": null
},
{
"Path": "github.com/spf13/pflag",
"Version": "v1.0.5",
"Dir": "",
"Replace": null
},
{
"Path": "golang.org/x/mod",
"Version": "v0.6.0-dev.0.20220419223038-86c51ed26bb4",
"Dir": "",
"Replace": null
},
{
"Path": "golang.org/x/sys",
"Version": "v0.0.0-20220804214406-8e32c043e418",
"Dir": "",
"Replace": null
},
{
"Path": "golang.org/x/tools",
"Version": "v0.1.12",
"Dir": "",
"Replace": null
},
{
"Path": "stdlib",
"Version": "v1.19.0",
"Dir": "",
"Replace": null
}
]
}
Hmm? The dependencies are empty—is that okay? I had a thought and tried downgrading to Go 1.18 to test it.
$ go version
go version go1.18 linux/amd64
$ govulncheck -json ./...
{
"Calls": {
"Functions": {},
"Entries": null
},
"Imports": {
"Packages": {
"1": {
"ID": 1,
"Name": "syscall",
"Path": "syscall",
"Module": 1,
"ImportedBy": [
2,
3,
4,
5,
7,
12,
13,
35,
69,
74,
81
]
},
...
"9": {
"ID": 9,
"Name": "json",
"Path": "encoding/json",
"Module": 1,
"ImportedBy": [
10,
15,
49,
61,
63,
66,
67
]
}
},
"Entries": [
14,
15,
51,
58,
59,
60,
61,
65,
66,
67,
68,
81,
82
]
},
"Requires": {
"Modules": {
"1": {
"ID": 1,
"Path": "stdlib",
"Version": "v1.18.0",
"Replace": 0,
"RequiredBy": [
4,
5,
7,
8,
9,
11,
13,
14,
2,
3,
6,
10,
12
]
},
...
"9": {
"ID": 9,
"Path": "github.com/google/licenseclassifier/v2",
"Version": "v2.0.0-pre6",
"Replace": 0,
"RequiredBy": [
3
]
}
},
"Entries": [
3
]
},
"Vulns": null,
"Modules": [
...
]
}
(Pardon me, it was too long, so I've truncated the middle part.)
It came out properly! Hmm. I wonder if this behavior is something to be addressed in the future.
Anyway, it seems usable at a minimum, and it probably wouldn't be difficult to integrate into CI. Give it a try.
Integration with gopls
It seems that govulncheck can integrate with gopls, the official Go Language Server.
Thanks for the info! 🙇
For example, if you have the Go extension installed in VS Code and have gopls enabled as the Language Server, adding the following items to your setting.json will allow you to integrate govulncheck.
{
"gopls": {
"ui.codelenses": {
"run_vulncheck_exp": true
}
}
}
I tried adding it to my environment, but since I haven't encountered any situations where a warning would appear yet, I'm not entirely sure if it's working properly (lol).
RESTFul Web API
If you already know the problematic module or the Go vulnerability ID (such as GO-2021-1234), you can retrieve information using a simple Web API without needing any specific tools.
| Path | Description |
|---|---|
https://vuln.go.dev/index.json |
List of module paths in the database mapped to its last modified timestamp (link). |
https://vuln.go.dev/$module.json |
List of vulnerability entries for that module (example). |
https://vuln.go.dev/ID/index.json |
List of all the vulnerability entries in the database. |
https://vuln.go.dev/ID/$vuln.json |
An individual Go vulnerability report. |
Here, $module refers to the module name (such as golang.org/x/crypto [2]) and $vuln refers to the vulnerability ID.
For example, since the ID for the vulnerability fixed in Go 1.18.5 is GO-2022-0537, you can retrieve the information like this:
$ curl -L "https://vuln.go.dev/ID/GO-2022-0537.json" | jq .
{
"id": "GO-2022-0537",
"published": "2022-08-01T22:21:06Z",
"modified": "2022-08-01T22:21:06Z",
"aliases": [
"CVE-2022-32189"
],
"details": "Decoding big.Float and big.Rat types can panic if the encoded message is\ntoo short, potentially allowing a denial of service.\n",
"affected": [
{
"package": {
"name": "math/big",
"ecosystem": "Go"
},
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "0"
},
{
"fixed": "1.17.13"
},
{
"introduced": "1.18.0"
},
{
"fixed": "1.18.5"
}
]
}
],
"database_specific": {
"url": "https://pkg.go.dev/vuln/GO-2022-0537"
},
"ecosystem_specific": {
"symbols": [
"Float.GobDecode",
"Rat.GobDecode"
]
}
}
],
"references": [
{
"type": "FIX",
"url": "https://go.dev/cl/417774"
},
{
"type": "FIX",
"url": "https://go.googlesource.com/go/+/055113ef364337607e3e72ed7d48df67fde6fc66"
},
{
"type": "WEB",
"url": "https://go.dev/issue/53871"
},
{
"type": "WEB",
"url": "https://groups.google.com/g/golang-announce/c/YqYYG87xB10"
}
]
}
To be honest, CVE-based information pages are often slow to update and not very user-friendly. If Go officially manages vulnerability IDs and operates the database, I will rely on that in the future.
References
The following article provides some explanation about the vulnerability management system introduced in this article.
These are the slides from the first session of "Go Conference mini 2022 Autumn IN SENDAI".
-
For Go environment variables, please refer to "Go development environment that (as much as possible) does not depend on GOPATH (Go 1.15 version)". ↩︎
-
It seems the module name for standard packages is specified as
stdlib. ↩︎
Discussion