Goの脆弱性を確認するにはgovulncheckを使おう

Go言語

安全にシステムを稼働していくために、開発しているシステムの脆弱性(セキュリティ上の弱点)を診断する必要があります。
今回Go公式の脆弱性チェッカーであるgovulncheckを使用すれば、コマンド一発でコードの脆弱性を発見することができるということなので実際に動かしてみました。

govulncheckとは

govulncheckは、プロジェクトの依存関係から既知の脆弱性を見つけるコマンドラインツールです。このツールはコードとバイナリの両方を分析が可能で、コードが実際に呼び出している関数の脆弱性に優先順位をつけて表示させています。

Govulncheck v1.0.0 is released! - The Go Programming Language
Version v1.0.0 of golang.org/x/vuln has been released, introducing a new API and other improvements.

試したこと

以下、自分のリポジトリに対して、govulncheckを実行してみて、発見された脆弱性について対応してみました。

GitHub - SND1231/go-column at road-map
Go コラムのサンプルコードをこちらに残す. Contribute to SND1231/go-column development by creating an account on GitHub.

インストール

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

脆弱性の確認

確認の手順は以下

  1. リポジトリのルートディレクトリで「make containers-up」を実行
  2. コンテナに接続する。
  3. コンテナ上で、「govulncheck ./…」を実行する。

root@265382251bc7:/work# govulncheck ./...
Using go1.19.9 and govulncheck@v1.0.0 with vulnerability data from https://vuln.go.dev (last modified 2023-07-13 22:19:53 +0000 UTC).

Scanning your code and 192 packages across 23 dependent modules for known vulnerabilities...

Vulnerability #1: GO-2023-1840
    Unsafe behavior in setuid/setgid binaries in runtime
  More info: https://pkg.go.dev/vuln/GO-2023-1840
  Standard library
    Found in: runtime@go1.19.9
    Fixed in: runtime@go1.20.5
    Example traces found:
      #1: handler/user.go:110:14: handler.UserHandler.Get calls log.Println, which eventually calls runtime.Caller
      #2: models/user.go:999:28: models.UserExists calls errors.Wrap, which eventually calls runtime.Callers
      #3: handler/user.go:31:15: handler.setErrorResponse calls http.response.WriteHeader, which eventually calls runtime.CallersFrames
      #4: handler/user.go:31:15: handler.setErrorResponse calls http.response.WriteHeader, which eventually calls runtime.Frames.Next
      #5: models/user.go:992:15: models.UserExists calls fmt.Fprintln, which eventually calls runtime.Func.FileLine
      #6: models/user.go:992:15: models.UserExists calls fmt.Fprintln, which eventually calls runtime.Func.Name
      #7: models/user.go:992:15: models.UserExists calls fmt.Fprintln, which eventually calls runtime.FuncForPC
      #8: models/user.go:975:15: models.UserSlice.ReloadAll calls queries.Query.Bind, which eventually calls runtime.GC
      #9: models/user.go:712:28: models.User.Upsert calls strmangle.GetBuffer, which eventually calls runtime.GOMAXPROCS
      #10: usecase/user.go:6:2: usecase.init calls http.init, which eventually calls runtime.GOROOT
      #11: models/user.go:992:15: models.UserExists calls fmt.Fprintln, which eventually calls runtime.KeepAlive
      #12: cmd/root.go:9:2: cmd.init calls os.init, which eventually calls runtime.SetFinalizer
      #13: handler/user.go:129:25: handler.UserHandler.Get calls sql.DB.BeginTx, which eventually calls runtime.Stack
      #14: models/user.go:992:15: models.UserExists calls fmt.Fprintln, which eventually calls runtime.TypeAssertionError.Error
      #15: models/user.go:14:2: models.init calls time.init, which eventually calls runtime.defaultMemProfileRate
      #16: models/user.go:14:2: models.init calls time.init, which eventually calls runtime.efaceOf
      #17: models/user.go:14:2: models.init calls time.init, which eventually calls runtime.findfunc
      #18: models/user.go:14:2: models.init calls time.init, which eventually calls runtime.float64frombits
      #19: models/user.go:14:2: models.init calls time.init, which eventually calls runtime.forcegchelper
      #20: models/user.go:14:2: models.init calls time.init, which eventually calls runtime.funcMaxSPDelta
      #21: models/user.go:992:15: models.UserExists calls fmt.Fprintln, which eventually calls runtime.plainError.Error
      #22: models/user.go:14:2: models.init calls time.init, which eventually calls runtime.throw

=== Informational ===

Found 1 vulnerability in packages that you import, but there are no call
stacks leading to the use of this vulnerability. You may not need to
take any action. See https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck
for details.

Vulnerability #1: GO-2023-1878
    Insufficient sanitization of Host header in net/http
  More info: https://pkg.go.dev/vuln/GO-2023-1878
  Standard library
    Found in: net/http@go1.19.9
    Fixed in: net/http@go1.20.6

Your code is affected by 1 vulnerability from the Go standard library.

Share feedback at https://go.dev/s/govulncheck-feedback.

実行した結果、2つの脆弱性が見つかりました(1つは対応する必要はないですが)。
それぞれの脆弱性の詳細については「More info」に書かれているURLのサイトに書かれています。

脆弱性を解消


Goのバージョンを1.20.6にあげれば脆弱性の問題は解決できるので、バージョンを上げて脆弱性のチェックを再実行してみます。

Goのバージョンを上げたり、govulncheckをインストールするためにDockerfileの変更をしています。変更後のリポジトリは以下になります。

GitHub - SND1231/go-column at govulncheck
Go コラムのサンプルコードをこちらに残す. Contribute to SND1231/go-column development by creating an account on GitHub.

再確認する方法(1~3はリポジトリのルートディレクトリで実施)

  1. 「make container-down」を実行して、コンテナ落とす
  2. 「make container-build」を実行して、コンテナをビルドし直す。
  3. 「make containers-up」を実行して、コンテナを起動する。
  4. コンテナに接続
  5. 再度「govulncheck ./…」を実行します。

root@5c3b1242591c:/work# go version
go version go1.20.6 linux/amd64
root@5c3b1242591c:/work# govulncheck ./...
Using go1.20.6 and govulncheck@v1.0.0 with vulnerability data from https://vuln.go.dev (last modified 2023-07-13 22:19:53 +0000 UTC).

Scanning your code and 193 packages across 23 dependent modules for known vulnerabilities...

No vulnerabilities found.

Share feedback at https://go.dev/s/govulncheck-feedback.

脆弱性がないことを確認できました!!
今回は簡単にバージョン上げてしまったのですが、実際の開発現場ではバージョンが上がって影響がないかをテストするので、テストコードで動作に問題ないかをすぐに確認できるようにする必要があります。

まとめ

Goの脆弱性を発見するコマンドラインツールであるgovulncheckについて紹介しました。
開発しているシステムに脆弱性がないかを確認するのは大切なことなので、govulncheckを現場でも使っていく必要があるので積極的に使っていきましょう。
Go言語について他にも記事を書いておりまして、興味がありましたら、そちらも読んでいただけたらと思います。

【おすすめ記事のリンク】

コメント

タイトルとURLをコピーしました