govulncheckでGoプロジェクトの脆弱性を検出(オプション毎の出力の違い)
この記事は カオナビ Advent Calendar 2024(シーズン1) 9日目です。
govulncheckとは
Goの脆弱性を検出してくれるツールです。
アプリケーションに影響を与える可能性のある脆弱性だけにレポートしてくれて
レポートには脆弱性が修正されているバージョン、脆弱性のあるコードを呼び出しているコード行も表示してくれます。
便利😀
チュートリアルもあります
govulncheckのオプション
オプションを見ると -format, -showなど出力内容を変更できそうなオプションが存在します。
※-json は古いオプションなので-format=jsonを使いましょう
※-show=verboseオプションを指定した場合-format=text以外を指定することはできないようです
$ govulncheck -h
Govulncheck reports known vulnerabilities in dependencies.
Usage:
govulncheck [flags] [patterns]
govulncheck -mode=binary [flags] [binary]
-C dir
change to dir before running govulncheck
-db url
vulnerability database url (default "https://vuln.go.dev")
-format value
specify format output
The supported values are 'text', 'json', 'sarif', and 'openvex' (default 'text')
-json
output JSON (Go compatible legacy flag, see format flag)
-mode value
supports 'source', 'binary', and 'extract' (default 'source')
-scan value
set the scanning level desired, one of 'module', 'package', or 'symbol' (default 'symbol')
-show list
enable display of additional information specified by the comma separated list
The supported values are 'traces','color', 'version', and 'verbose'
-tags list
comma-separated list of build tags
-test
analyze test files (only valid for source mode, default false)
-version
print the version information
For details, see https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck.
Goのプログラムで出力結果を扱いたい
出力結果が長くなるので、結果をGoで扱うコードは以下の記事に書いております😀
※以降はサンプルコード + 各オプションの出力結果になります
検証コード
sample
├── go.work
├── mod1
│ ├── go.mod
│ └── mod1.go
├── mod2
│ ├── go.mod
│ └── mod2.go
└── mod3
├── go.mod
└── mod3.go
脆弱性が検出されるコード
-
golang-jwt/jwtのv4.5.0は脆弱性が検出されておりv4.5.1で修正されています -
mod1.goは脆弱性が検知されるようにParseWithClaimsを呼び出します
module sample/mod1
go 1.23.3
require github.com/golang-jwt/jwt/v4 v4.5.0
package mod1
func Run() {
type claims struct {
jwt.Claims
}
keyFunc := func(token *jwt.Token) (interface{}, error) { return nil, nil }
_, _ = jwt.ParseWithClaims("sample token", &claims{}, keyFunc)
}
func NoVuln() {}
脆弱性が検出される処理を呼び出していない、が依存モジュールに脆弱性があるコード
-
bar.goが呼び出しているsample/fooの関数Foo2()では脆弱性の含まれる処理を呼び出していません - しかし呼び出していない関数
Foo()では脆弱性の含まれる処理を呼び出しています
module sample/mod2
go 1.23.3
package mod2
import (
"sample/mod1"
)
func Run() {
mod1.NoVuln()
}
脆弱性が検出されないコード
- 何も書いていないので何も検知されません
module sample/mod3
go 1.23.3
package mod3
func Run() {}
脆弱性チェックを試す
オプション無し
package mod1
脆弱性の詳細が書かれたURL、脆弱性が見つかったモジュールのバージョン、脆弱性が修正されているバージョンが表示されます
出力も整形されており見やすいです😀
出力を見るポイントとしては
-
More info:-> 脆弱性の詳細が書かれたURL -
Module:-> 脆弱性が存在するモジュール名 -
Found in:-> 脆弱性が検知されたバージョン -
Fixed in:-> 脆弱性が修正されているバージョン -
Example traces found:-> 自身のプロジェクト内での脆弱性があるコードの呼び出し箇所
$ govulncheck ./...
=== Symbol Results ===
Vulnerability #1: GO-2024-3250
Improper error handling in ParseWithClaims and bad documentation may cause
dangerous situations in github.com/golang-jwt/jwt
More info: https://pkg.go.dev/vuln/GO-2024-3250
Module: github.com/golang-jwt/jwt/v4
Found in: github.com/golang-jwt/jwt/v4@v4.5.0
Fixed in: github.com/golang-jwt/jwt/v4@v4.5.1
Example traces found:
#1: mod1.go:12:28: mod1.Run calls jwt.ParseWithClaims
Your code is affected by 1 vulnerability from 1 module.
This scan found no other vulnerabilities in packages you import or modules you
require.
Use '-show verbose' for more details.
package mod2
No vulnerabilities found. と表示されていますが
importしているパッケージに脆弱性があります、のようなメッセージが表示されます
$ govulncheck ./...
=== Symbol Results ===
No vulnerabilities found.
Your code is affected by 0 vulnerabilities.
This scan also found 1 vulnerability in packages you import and 0
vulnerabilities in modules you require, but your code doesn't appear to call
these vulnerabilities.
Use '-show verbose' for more details.
package mod3
$ govulncheck ./...
No vulnerabilities found.
-show=verboseオプションを指定
package mod1
Symbol Results の出力内容は変わりませんが、
Package ResultsとModule Results という項目が増えました
$ govulncheck -show=verbose ./...
Scanning your code and 112 packages across 2 dependent modules for known vulnerabilities...
Fetching vulnerabilities from the database...
Checking the code against the vulnerabilities...
=== Symbol Results ===
Vulnerability #1: GO-2024-3250
Improper error handling in ParseWithClaims and bad documentation may cause
dangerous situations in github.com/golang-jwt/jwt
More info: https://pkg.go.dev/vuln/GO-2024-3250
Module: github.com/golang-jwt/jwt/v4
Found in: github.com/golang-jwt/jwt/v4@v4.5.0
Fixed in: github.com/golang-jwt/jwt/v4@v4.5.1
Example traces found:
#1: mod1.go:12:28: mod1.Run calls jwt.ParseWithClaims
=== Package Results ===
No other vulnerabilities found.
=== Module Results ===
No other vulnerabilities found.
Your code is affected by 1 vulnerability from 1 module.
This scan found no other vulnerabilities in packages you import or modules you
require.
package mod2
Package Results に依存モジュール(sample/mod1)に存在する脆弱性が表示されるようになりました
直接使っているわけではないので影響がある訳ではないですが、依存モジュールの脆弱性も検出してくれます。
$ govulncheck -show=verbose ./...
Scanning your code and 113 packages across 3 dependent modules for known vulnerabilities...
Fetching vulnerabilities from the database...
Checking the code against the vulnerabilities...
=== Symbol Results ===
No vulnerabilities found.
=== Package Results ===
Vulnerability #1: GO-2024-3250
Improper error handling in ParseWithClaims and bad documentation may cause
dangerous situations in github.com/golang-jwt/jwt
More info: https://pkg.go.dev/vuln/GO-2024-3250
Module: github.com/golang-jwt/jwt/v4
Found in: github.com/golang-jwt/jwt/v4@v4.5.0
Fixed in: github.com/golang-jwt/jwt/v4@v4.5.1
=== Module Results ===
No other vulnerabilities found.
Your code is affected by 0 vulnerabilities.
This scan also found 1 vulnerability in packages you import and 0
vulnerabilities in modules you require, but your code doesn't appear to call
these vulnerabilities.
package mod3
$ govulncheck -show=verbose ./...
Scanning your code and 0 packages across 1 dependent module for known vulnerabilities...
Fetching vulnerabilities from the database...
Checking the code against the vulnerabilities...
No vulnerabilities found.
-show=tracesオプションを指定
※mod2, mod3はオプション無しと結果が変わらなかったので割愛
package mod1
$ govulncheck -show=traces ./...
=== Symbol Results ===
Vulnerability #1: GO-2024-3250
Improper error handling in ParseWithClaims and bad documentation may cause
dangerous situations in github.com/golang-jwt/jwt
More info: https://pkg.go.dev/vuln/GO-2024-3250
Module: github.com/golang-jwt/jwt/v4
Found in: github.com/golang-jwt/jwt/v4@v4.5.0
Fixed in: github.com/golang-jwt/jwt/v4@v4.5.1
Example traces found:
#1: for function github.com/golang-jwt/jwt/v4.ParseWithClaims
mod1.go:12:28: sample/mod1.Run
token.go:113:6: github.com/golang-jwt/jwt/v4.ParseWithClaims
Your code is affected by 1 vulnerability from 1 module.
This scan found no other vulnerabilities in packages you import or modules you
require.
Use '-show verbose' for more details.
差分としては以下の内容が増えました
Example traces found:
#1: for function github.com/golang-jwt/jwt/v4.ParseWithClaims
mod1.go:12:28: sample/mod1.Run
+ token.go:113:6: github.com/golang-jwt/jwt/v4.ParseWithClaims
-show=colorオプションを指定
オプション指定無しの実行結果が、ちょっとカラフルになります:rainbow:
-show=versionオプションを指定
実行環境のGoのバージョン、govulncheckのバージョン、脆弱性データベースの情報が表示されるようになりました。
CIでもどのような環境で実行されたか分かるため出力しておくと良さそうに思います。
$ govulncheck -show=version ./...
Go: go1.23.3
Scanner: govulncheck@v1.1.3
DB: https://vuln.go.dev
DB updated: 2024-11-27 19:16:39 +0000 UTC
=== Symbol Results ===
Vulnerability #1: GO-2024-3250
Improper error handling in ParseWithClaims and bad documentation may cause
dangerous situations in github.com/golang-jwt/jwt
More info: https://pkg.go.dev/vuln/GO-2024-3250
Module: github.com/golang-jwt/jwt/v4
Found in: github.com/golang-jwt/jwt/v4@v4.5.0
Fixed in: github.com/golang-jwt/jwt/v4@v4.5.1
Example traces found:
#1: mod1.go:12:28: mod1.Run calls jwt.ParseWithClaims
Your code is affected by 1 vulnerability from 1 module.
This scan found no other vulnerabilities in packages you import or modules you
require.
Use '-show verbose' for more details.
-format=sarifオプションを指定
Static Analysis Results Interchange Format(SARIF)とは静的解析ツールの出力の標準形式です
package mod1
runs.tool.rulesに検出された脆弱性の詳細情報が出力されています。
またresultsに検出された脆弱性と"level": "error", が出力されており、プロジェクトで対応が必要な脆弱性であると判断できます。
codeFlowsでは-show=tracesオプションを指定した場合の出力結果が入っているようです。
$ govulncheck -format=sarif ./...
{
"version": "2.1.0",
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"runs": [
{
"tool": {
"driver": {
"name": "govulncheck",
"semanticVersion": "v1.1.3",
"informationUri": "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck",
"properties": {
"protocol_version": "v1.0.0",
"scanner_name": "govulncheck",
"scanner_version": "v1.1.3",
"db": "https://vuln.go.dev",
"db_last_modified": "2024-11-27T19:16:39Z",
"go_version": "go1.23.3",
"scan_level": "symbol",
"scan_mode": "source"
},
"rules": [
{
"id": "GO-2024-3250",
"shortDescription": {
"text": "[GO-2024-3250] Improper error handling in ParseWithClaims and bad documentation may cause dangerous situations in github.com/golang-jwt/jwt"
},
"fullDescription": {
"text": "Improper error handling in ParseWithClaims and bad documentation may cause dangerous situations in github.com/golang-jwt/jwt"
},
"help": {
"text": "Improper error handling in ParseWithClaims and bad documentation may cause dangerous situations in github.com/golang-jwt/jwt"
},
"helpUri": "https://pkg.go.dev/vuln/GO-2024-3250",
"properties": {
"tags": [
"CVE-2024-51744",
"GHSA-29wx-vh33-7x7r"
]
}
}
]
}
},
"results": [
{
"ruleId": "GO-2024-3250",
"level": "error",
"message": {
"text": "Your code calls vulnerable functions in 1 package (github.com/golang-jwt/jwt/v4)."
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "go.mod",
"uriBaseId": "%SRCROOT%"
},
"region": {
"startLine": 1
}
},
"message": {
"text": "Findings for vulnerability GO-2024-3250"
}
}
],
"codeFlows": [
{
"threadFlows": [
{
"locations": [
{
"module": "sample/mod1@",
"location": {
"physicalLocation": {
"artifactLocation": {
"uri": "mod1.go",
"uriBaseId": "%SRCROOT%"
},
"region": {
"startLine": 12,
"startColumn": 28
}
},
"message": {
"text": "sample/mod1.Run"
}
}
},
{
"module": "github.com/golang-jwt/jwt/v4@v4.5.0",
"location": {
"physicalLocation": {
"artifactLocation": {
"uri": "github.com/golang-jwt/jwt/v4@v4.5.0/token.go",
"uriBaseId": "%GOMODCACHE%"
},
"region": {
"startLine": 113,
"startColumn": 6
}
},
"message": {
"text": "github.com/golang-jwt/jwt/v4.ParseWithClaims"
}
}
}
]
}
],
"message": {
"text": "A summarized code flow for vulnerable function github.com/golang-jwt/jwt/v4.ParseWithClaims"
}
}
],
"stacks": [
{
"message": {
"text": "A call stack for vulnerable function github.com/golang-jwt/jwt/v4.ParseWithClaims"
},
"frames": [
{
"module": "sample/mod1@",
"location": {
"physicalLocation": {
"artifactLocation": {
"uri": "mod1.go",
"uriBaseId": "%SRCROOT%"
},
"region": {
"startLine": 12,
"startColumn": 28
}
},
"message": {
"text": "sample/mod1.Run"
}
}
},
{
"module": "github.com/golang-jwt/jwt/v4@v4.5.0",
"location": {
"physicalLocation": {
"artifactLocation": {
"uri": "github.com/golang-jwt/jwt/v4@v4.5.0/token.go",
"uriBaseId": "%GOMODCACHE%"
},
"region": {
"startLine": 113,
"startColumn": 6
}
},
"message": {
"text": "github.com/golang-jwt/jwt/v4.ParseWithClaims"
}
}
}
]
}
]
}
]
}
]
}
package mod2
resultsは表示されていますが、 "level": "warning", となっています。
ここで自分のプロジェクトに直接影響があるものかどうか判断できそうです。
$ govulncheck -format=sarif ./...
{
"version": "2.1.0",
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"runs": [
{
"tool": {
"driver": {
"name": "govulncheck",
"semanticVersion": "v1.1.3",
"informationUri": "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck",
"properties": {
"protocol_version": "v1.0.0",
"scanner_name": "govulncheck",
"scanner_version": "v1.1.3",
"db": "https://vuln.go.dev",
"db_last_modified": "2024-11-27T19:16:39Z",
"go_version": "go1.23.3",
"scan_level": "symbol",
"scan_mode": "source"
},
"rules": [
{
"id": "GO-2024-3250",
"shortDescription": {
"text": "[GO-2024-3250] Improper error handling in ParseWithClaims and bad documentation may cause dangerous situations in github.com/golang-jwt/jwt"
},
"fullDescription": {
"text": "Improper error handling in ParseWithClaims and bad documentation may cause dangerous situations in github.com/golang-jwt/jwt"
},
"help": {
"text": "Improper error handling in ParseWithClaims and bad documentation may cause dangerous situations in github.com/golang-jwt/jwt"
},
"helpUri": "https://pkg.go.dev/vuln/GO-2024-3250",
"properties": {
"tags": [
"CVE-2024-51744",
"GHSA-29wx-vh33-7x7r"
]
}
}
]
}
},
"results": [
{
"ruleId": "GO-2024-3250",
"level": "warning",
"message": {
"text": "Your code imports 1 vulnerable package (github.com/golang-jwt/jwt/v4), but doesn’t appear to call any of the vulnerable symbols."
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "go.mod",
"uriBaseId": "%SRCROOT%"
},
"region": {
"startLine": 1
}
},
"message": {
"text": "Findings for vulnerability GO-2024-3250"
}
}
]
}
]
}
]
}
package mod3
脆弱性が存在しない場合はruns.tool.rules, resultsが出力されなくなりました
$ govulncheck -format=sarif ./...
{
"version": "2.1.0",
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"runs": [
{
"tool": {
"driver": {
"name": "govulncheck",
"semanticVersion": "v1.1.3",
"informationUri": "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck",
"properties": {
"protocol_version": "v1.0.0",
"scanner_name": "govulncheck",
"scanner_version": "v1.1.3",
"db": "https://vuln.go.dev",
"db_last_modified": "2024-11-27T19:16:39Z",
"go_version": "go1.23.3",
"scan_level": "symbol",
"scan_mode": "source"
}
}
}
}
]
}
-format=openvexオプションを指定
OpenVEX is an implementation of the Vulnerability Exploitability Exchange (VEX for short) that is designed to be minimal, compliant, interoperable, and embeddable. The specification is available in the OPENVEX-SPEC.md file of this repository.
Google訳
OpenVEX は、最小限、準拠、相互運用性、埋め込み性を実現するように設計された、Vulnerability Exploitability Exchange (VEX)の実装です。
package mod1
検出された脆弱性の情報は出力されますが、プロジェクトでの検出箇所に関する情報はなくなりました。
内容としてはかなりシンプルになりました。
"status": "affected" でこのプロジェクトに影響のある脆弱性であることがわかります。
$ govulncheck -format=openvex ./...
{
"@context": "https://openvex.dev/ns/v0.2.0",
"@id": "govulncheck/vex:4c2d5514af28c4a0af7e6e0e41e7e9edf08bb78109760380ac776176eca4d73b",
"author": "Unknown Author",
"timestamp": "2024-11-28T15:29:02.404127Z",
"version": 1,
"tooling": "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck",
"statements": [
{
"vulnerability": {
"@id": "https://pkg.go.dev/vuln/GO-2024-3250",
"name": "GO-2024-3250",
"description": "Improper error handling in ParseWithClaims and bad documentation may cause dangerous situations in github.com/golang-jwt/jwt",
"aliases": [
"CVE-2024-51744",
"GHSA-29wx-vh33-7x7r"
]
},
"products": [
{
"@id": "Unknown Product"
}
],
"status": "affected"
}
]
}
package mod2
こちらも同様にシンプルですが若干情報が増えているようです
"status": "not_affected", で直接影響のある脆弱性でないことは分かります。
justificationとimpact_statementにはなぜ影響がないか、という理由が出力されています。
$ govulncheck -format=openvex ./...
{
"@context": "https://openvex.dev/ns/v0.2.0",
"@id": "govulncheck/vex:c6c21792e5ef0187e993b6866abc8b9358d6de429c931c92aa95071e198f2b59",
"author": "Unknown Author",
"timestamp": "2024-11-28T15:29:02.533188Z",
"version": 1,
"tooling": "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck",
"statements": [
{
"vulnerability": {
"@id": "https://pkg.go.dev/vuln/GO-2024-3250",
"name": "GO-2024-3250",
"description": "Improper error handling in ParseWithClaims and bad documentation may cause dangerous situations in github.com/golang-jwt/jwt",
"aliases": [
"CVE-2024-51744",
"GHSA-29wx-vh33-7x7r"
]
},
"products": [
{
"@id": "Unknown Product"
}
],
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path",
"impact_statement": "Govulncheck determined that the vulnerable code isn't called"
}
]
}
package mod3
statements 自体が出力されません。
$ govulncheck -format=openvex ./...
{
"@context": "https://openvex.dev/ns/v0.2.0",
"@id": "govulncheck/vex:dbe7160a7e784903e7018529dca9791796885b4a0bad84a321cecbf1dc0473a5",
"author": "Unknown Author",
"timestamp": "2024-11-28T15:29:02.183641Z",
"version": 1,
"tooling": "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck"
}
-format=jsonオプションを指定
※出力が非常に長いので内容はガッツリ割愛します
大きく分けると config, progress osv, finding のパターンでJSONが出力されます。
目で見るにはかなりきつい量が出力されました。
config: -show=versionオプションで出力されていた内容と同じ
progress: INFOメッセージみたいなもの
osv: 脆弱性の詳細情報(修正バージョンなどもここに含まれる)
finding 検出された脆弱性の情報(依存モジュールのみで検出されている脆弱性の場合はtraceは出力されないです)
$ govulncheck -format=json ./...
{
"config": {
"protocol_version": "v1.0.0",
"scanner_name": "govulncheck",
"scanner_version": "v1.1.3",
"db": "https://vuln.go.dev",
"db_last_modified": "2024-11-27T19:16:39Z",
"go_version": "go1.23.3",
"scan_level": "symbol",
"scan_mode": "source"
}
}
{
"progress": {
"message": "Scanning your code and 112 packages across 2 dependent modules for known vulnerabilities..."
}
}
{
"progress": {
"message": "Fetching vulnerabilities from the database..."
}
}
{
"osv": {
"schema_version": "1.3.1",
"id": "GO-2024-3250",
"modified": "2024-11-12T14:50:10Z",
"published": "2024-11-12T13:55:08Z",
"aliases": [
"CVE-2024-51744",
"GHSA-29wx-vh33-7x7r"
],
"summary": "Improper error handling in ParseWithClaims and bad documentation may cause dangerous situations in github.com/golang-jwt/jwt",
"details": "Improper error handling in ParseWithClaims and bad documentation may cause dangerous situations in github.com/golang-jwt/jwt",
"affected": [
{
"package": {
"name": "github.com/golang-jwt/jwt/v4",
"ecosystem": "Go"
},
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "0"
},
{
"fixed": "4.5.1"
}
]
}
],
"ecosystem_specific": {
"imports": [
{
"path": "github.com/golang-jwt/jwt/v4",
"symbols": [
"Parse",
"ParseWithClaims",
"Parser.Parse",
"Parser.ParseWithClaims"
]
}
]
}
}
],
"references": [
{
"type": "ADVISORY",
"url": "https://github.com/golang-jwt/jwt/security/advisories/GHSA-29wx-vh33-7x7r"
},
{
"type": "FIX",
"url": "https://github.com/golang-jwt/jwt/commit/7b1c1c00a171c6c79bbdb40e4ce7d197060c1c2c"
}
],
"database_specific": {
"url": "https://pkg.go.dev/vuln/GO-2024-3250",
"review_status": "REVIEWED"
}
}
}
〜〜〜 osvのJSONがドバーッと出力される 〜〜〜
{
"progress": {
"message": "Checking the code against the vulnerabilities..."
}
}
〜〜〜 findingのJSONがドバーッと出力される 〜〜〜
{
"finding": {
"osv": "GO-2024-3250",
"fixed_version": "v4.5.1",
"trace": [
{
"module": "github.com/golang-jwt/jwt/v4",
"version": "v4.5.0",
"package": "github.com/golang-jwt/jwt/v4",
"function": "ParseWithClaims",
"position": {
"filename": "token.go",
"offset": 4856,
"line": 113,
"column": 6
}
},
{
"module": "sample/mod1",
"package": "sample/mod1",
"function": "Run",
"position": {
"filename": "mod1.go",
"offset": 212,
"line": 12,
"column": 28
}
}
]
}
}
Discussion