hero_picture
Cover Image for Go言語の脆弱性チェックツール(govulncheck)でチェック対象のGoバージョンを変更する

Go言語の脆弱性チェックツール(govulncheck)でチェック対象のGoバージョンを変更する

2023/08/29

初めまして。クラウドソリューション事業部の新永です。

Go 言語を使用したプロジェクト内の脆弱な依存関係を修正するためのツールに govulncheck があります。govulncheck は脆弱な依存関係と、その依存関係の修正されたバージョンの情報を提供してくれます。

本記事では govulncheck でチェック対象の Go バージョンを指定する方法をご紹介します。

執筆時の govulncheck -version の情報は以下です。

1Go: go1.21.0
2Scanner: govulncheck@v1.0.1
3DB: https://vuln.go.dev
4DB updated: 2023-08-23 14:38:50 +0000 UTC

結論

GOVERSION という環境変数を設定して govulncheck を実行することで、チェック対象の Go バージョンの変更ができます。 go という接頭辞を付け忘れないように気をつけましょう。

1GOVERSION=go1.20.5 govulncheck -version ./...

govulncheck の導入

以下のコマンドで導入しています。2023/08/29 現在では govulncheck@v1.0.1 がインストールされます。

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

検証に使用したコード

GO-2023-1878 を参考に、govulncheck で検出されるコードを用意しました。

go.mod:

1module govulncheck_test
2
3go 1.21

main.go:

1package main
2
3import (
4	"net/http"
5)
6
7func main() {
8	// https://pkg.go.dev/vuln/GO-2023-1878
9	// go1.20.6 で修正
10	if _, err := http.Get("http://127.0.0.1:12345"); err != nil {
11		panic(err)
12	}
13}

チェック対象の Go バージョンを指定しない場合

チェック対象の Go バージョンを指定しない場合、ホストにインストールされている Go のバージョンを元にチェックが行われます。govulncheck では v1.0.1 から -version オプションを指定しないと、チェック時の出力に実行対象のバージョンと Go 脆弱性データベースの最終更新日が含まれなくなりました。

1govulncheck -version ./...

以下のような出力が行われます。検証当時は go1.21.0 をホストにインストールしていたので、go1.20.6 で修正された内容は出力されていません。

1Go: go1.21.0
2Scanner: govulncheck@v1.0.1
3DB: https://vuln.go.dev
4DB updated: 2023-08-23 14:38:50 +0000 UTC
5
6Scanning your code and 128 packages across 0 dependent modules for known vulnerabilities...
7
8No vulnerabilities found.
9
10Share feedback at https://go.dev/s/govulncheck-feedback.

チェック対象の Go バージョンを指定するには

チェック対象の Go バージョンを指定するには GOVERSION という環境変数を設定します。
今回は
GO-2023-1878 に向けた修正が行われる前の go1.20.5 を指定してみます。go という接頭辞を付け忘れないように気をつけましょう。

1GOVERSION=go1.20.5 govulncheck -version ./...

以下のような出力が行われます。 -version オプションで出力させている Go バージョンが変わっていることと、GO-2023-1878 が検出されていることを確認できました。

1Go: go1.20.5
2Scanner: govulncheck@v1.0.1
3DB: https://vuln.go.dev
4DB updated: 2023-08-23 14:38:50 +0000 UTC
5
6Scanning your code and 128 packages across 0 dependent modules for known vulnerabilities...
7
8Vulnerability #1: GO-2023-1987
9    Large RSA keys can cause high CPU usage in crypto/tls
10  More info: https://pkg.go.dev/vuln/GO-2023-1987
11  Standard library
12    Found in: crypto/tls@go1.20.5
13    Fixed in: crypto/tls@go1.21rc4
14    Example traces found:
15      #1: main.go:10:23: govulncheck_test.main calls http.Get, which eventually calls tls.Conn.HandshakeContext
16      #2: main.go:10:23: govulncheck_test.main calls http.Get, which eventually calls tls.Conn.Read
17      #3: main.go:10:23: govulncheck_test.main calls http.Get, which eventually calls tls.Conn.Write
18      #4: main.go:10:23: govulncheck_test.main calls http.Get, which eventually calls tls.Dialer.DialContext
19
20Vulnerability #2: GO-2023-1878
21    Insufficient sanitization of Host header in net/http
22  More info: https://pkg.go.dev/vuln/GO-2023-1878
23  Standard library
24    Found in: net/http@go1.20.5
25    Fixed in: net/http@go1.20.6
26    Example traces found:
27      #1: main.go:10:23: govulncheck_test.main calls http.Get
28
29Your code is affected by 2 vulnerabilities from the Go standard library.
30
31Share feedback at https://go.dev/s/govulncheck-feedback.

GOVERSION の優先順位

govulncheck@v1.0.1 のソースコードを覗いてみると、 GOVERSION は環境変数に登録されている値が優先され、環境変数に登録されていない場合は go env GOVERSION から取得されたバージョンが使用されるようになっていました。

govulncheck でチェック対象の Go バージョンを取得している処理は以下の部分です。
https://github.com/golang/vuln/blob/v1.0.1/internal/scan/run.go#L72-L94

cfg.env には os.Environ() の結果が代入されています。
https://github.com/golang/vuln/blob/v1.0.1/scan/scan.go#L78-L80

この挙動を見つけた経緯

この挙動を見つけた経緯は、govulncheck の結果を処理する GitHub Actions のワークフローを作成する中、以下の条件が重なることで想定したチェック結果が得られないというハマりどころからでした。

  1. actions/setup-go@v3 で用意する Go のバージョン値を GOVERSION という環境変数名でワークフローに定義していた
  2. govulncheck は環境変数 GOVERSION を優先して実行すること
    • 環境変数 GOVERSION は本来、 go env GOVERSION の実行結果のように go という接頭辞が必要
    • 接頭辞がついていないことにより、Go 脆弱性データベースへの検索で引っ掛からなかった

接頭辞 go を付けないバージョン指定を環境変数で行う場合は、 GOVERSION とは異なる環境変数名にセットする必要がありました。

最後に

本記事では govulncheck でチェック対象の Go バージョンを指定する方法を紹介しました。

本記事で紹介した手法を用いることで、ホストと運用環境で Go バージョンが異なっていても、運用環境と同じバージョンの Go を用意せずに govulncheck によるチェックができるようになります。

本記事が誰かのお役に立てれば幸いです。