From f4d7af419827ec2c13503468fd688fd278ef677f Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Mon, 15 Jul 2024 10:29:05 +0600 Subject: [PATCH 01/14] feat(gomod): parse `toolchain` to get stdlib version --- pkg/dependency/parser/golang/mod/parse.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pkg/dependency/parser/golang/mod/parse.go b/pkg/dependency/parser/golang/mod/parse.go index 508da6911521..936e003146cd 100644 --- a/pkg/dependency/parser/golang/mod/parse.go +++ b/pkg/dependency/parser/golang/mod/parse.go @@ -83,6 +83,19 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc skipIndirect = lessThan117(modFileParsed.Go.Version) } + // Stdlib + if toolchain := modFileParsed.Toolchain; toolchain != nil { + // `go1.22.5` => `1.22.5` + ver := strings.TrimPrefix(toolchain.Name, "go") + pkgs["stdlib"] = ftypes.Package{ + // Add the toolchain version as stdlib version + ID: packageID("stdlib", ver), + Name: "stdlib", + Version: ver, + Relationship: ftypes.RelationshipDirect, // Considered a direct dependency as the main module depends on the standard packages. + } + } + // Main module if m := modFileParsed.Module; m != nil { ver := strings.TrimPrefix(m.Mod.Version, "v") From a3d25f5eaccd10ac795b1da391a8831d3bf69816 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Mon, 15 Jul 2024 10:30:24 +0600 Subject: [PATCH 02/14] test(gomod): update unit test --- .../parser/golang/mod/parse_testcase.go | 52 ++++++++++--- .../parser/golang/mod/testdata/normal/go.mod | 12 ++- .../parser/golang/mod/testdata/normal/go.sum | 74 +++---------------- .../parser/golang/mod/testdata/normal/main.go | 4 +- 4 files changed, 63 insertions(+), 79 deletions(-) diff --git a/pkg/dependency/parser/golang/mod/parse_testcase.go b/pkg/dependency/parser/golang/mod/parse_testcase.go index 5a07b939c549..334b18703c60 100644 --- a/pkg/dependency/parser/golang/mod/parse_testcase.go +++ b/pkg/dependency/parser/golang/mod/parse_testcase.go @@ -17,35 +17,65 @@ var ( }, }, { - ID: "github.com/aquasecurity/go-dep-parser@v0.0.0-20211224170007-df43bca6b6ff", - Name: "github.com/aquasecurity/go-dep-parser", - Version: "0.0.0-20211224170007-df43bca6b6ff", + ID: "stdlib@v1.22.5", + Name: "stdlib", + Version: "1.22.5", + Relationship: ftypes.RelationshipDirect, + }, + { + ID: "github.com/aquasecurity/go-version@v0.0.0-20240603093900-cf8a8d29271d", + Name: "github.com/aquasecurity/go-version", + Version: "0.0.0-20240603093900-cf8a8d29271d", Relationship: ftypes.RelationshipDirect, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefVCS, - URL: "https://github.com/aquasecurity/go-dep-parser", + URL: "https://github.com/aquasecurity/go-version", }, }, }, { - ID: "golang.org/x/xerrors@v0.0.0-20200804184101-5ec99f83aff1", - Name: "golang.org/x/xerrors", - Version: "0.0.0-20200804184101-5ec99f83aff1", + ID: "github.com/davecgh/go-spew@v1.1.2-0.20180830191138-d8f796af33cc", + Name: "github.com/davecgh/go-spew", + Version: "1.1.2-0.20180830191138-d8f796af33cc", Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefVCS, + URL: "https://github.com/davecgh/go-spew", + }, + }, }, { - ID: "gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b", - Name: "gopkg.in/yaml.v3", - Version: "3.0.0-20210107192922-496545a6307b", + ID: "github.com/pmezard/go-difflib@v1.0.1-0.20181226105442-5d4384ee4fb2", + Name: "github.com/pmezard/go-difflib", + Version: "1.0.1-0.20181226105442-5d4384ee4fb2", Relationship: ftypes.RelationshipIndirect, ExternalReferences: []ftypes.ExternalRef{ { Type: ftypes.RefVCS, - URL: "https://github.com/go-yaml/yaml", + URL: "https://github.com/pmezard/go-difflib", }, }, }, + { + ID: "github.com/stretchr/testify@v1.9.0", + Name: "github.com/stretchr/testify", + Version: "1.9.0", + Relationship: ftypes.RelationshipIndirect, + ExternalReferences: []ftypes.ExternalRef{ + { + Type: ftypes.RefVCS, + URL: "https://github.com/stretchr/testify", + }, + }, + }, + { + ID: "golang.org/x/xerrors@v0.0.0-20231012003039-104605ab7028", + Name: "golang.org/x/xerrors", + Version: "0.0.0-20231012003039-104605ab7028", + Relationship: ftypes.RelationshipIndirect, + }, } // execute go mod tidy in replaced folder diff --git a/pkg/dependency/parser/golang/mod/testdata/normal/go.mod b/pkg/dependency/parser/golang/mod/testdata/normal/go.mod index 9d48b25e0079..564414c10583 100644 --- a/pkg/dependency/parser/golang/mod/testdata/normal/go.mod +++ b/pkg/dependency/parser/golang/mod/testdata/normal/go.mod @@ -1,10 +1,14 @@ module github.com/org/repo -go 1.17 +go 1.22.0 -require github.com/aquasecurity/go-dep-parser v0.0.0-20211224170007-df43bca6b6ff +toolchain go1.22.5 + +require github.com/aquasecurity/go-version v0.0.0-20240603093900-cf8a8d29271d require ( - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/stretchr/testify v1.9.0 // indirect + golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect ) diff --git a/pkg/dependency/parser/golang/mod/testdata/normal/go.sum b/pkg/dependency/parser/golang/mod/testdata/normal/go.sum index 032bb4727cfe..eefc0690f47d 100644 --- a/pkg/dependency/parser/golang/mod/testdata/normal/go.sum +++ b/pkg/dependency/parser/golang/mod/testdata/normal/go.sum @@ -1,62 +1,12 @@ -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/aquasecurity/go-dep-parser v0.0.0-20211224170007-df43bca6b6ff h1:JCKEV3TgUNh9fn+8hXyIdsF9yErA0rUbCkgt2flRKt4= -github.com/aquasecurity/go-dep-parser v0.0.0-20211224170007-df43bca6b6ff/go.mod h1:8fJ//Ob6/03lxbn4xa1F+G/giVtiVLxnZNpBp5xOxNk= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= -github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-retryablehttp v0.7.0/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +github.com/aquasecurity/go-version v0.0.0-20240603093900-cf8a8d29271d h1:4zour5Sh9chOg+IqIinIcJ3qtr3cIf8FdFY6aArlXBw= +github.com/aquasecurity/go-version v0.0.0-20240603093900-cf8a8d29271d/go.mod h1:1cPOp4BaQZ1G2F5fnw4dFz6pkOyXJI9KTuak8ghIl3U= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/dependency/parser/golang/mod/testdata/normal/main.go b/pkg/dependency/parser/golang/mod/testdata/normal/main.go index 0b51fb861f32..fe31e68d5da8 100644 --- a/pkg/dependency/parser/golang/mod/testdata/normal/main.go +++ b/pkg/dependency/parser/golang/mod/testdata/normal/main.go @@ -3,11 +3,11 @@ package main import ( "log" - "github.com/aquasecurity/trivy/pkg/dependency/parser/golang/mod" + "github.com/aquasecurity/go-version/pkg/version" ) func main() { - if _, err := mod.Parse(nil); err != nil { + if _, err := version.Parse("v0.1.2"); err != nil { log.Fatal(err) } } From 132fa50b4f2976e49faaa143c0770f803a9e6ba7 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Mon, 15 Jul 2024 11:07:24 +0600 Subject: [PATCH 03/14] docs(go): update coverage page --- docs/docs/coverage/language/golang.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/docs/coverage/language/golang.md b/docs/docs/coverage/language/golang.md index 6b3646329318..5644325dcc14 100644 --- a/docs/docs/coverage/language/golang.md +++ b/docs/docs/coverage/language/golang.md @@ -18,7 +18,7 @@ The table below provides an outline of the features Trivy offers. | Artifact | Offline[^1] | Dev dependencies | [Dependency graph][dependency-graph] | Stdlib | |----------|:-----------:|:-----------------|:------------------------------------:|:------:| -| Modules | ✅ | Include | ✅[^2] | - | +| Modules | ✅ | Include | ✅[^2] | ✅[^6] | | Binaries | ✅ | Exclude | - | ✅[^4] | !!! note @@ -93,5 +93,6 @@ empty if it cannot do so[^5]. For the second case, the version of such packages [^3]: See https://github.com/aquasecurity/trivy/issues/1837#issuecomment-1832523477 [^4]: Identify the Go version used to compile the binary and detect its vulnerabilities [^5]: See https://github.com/golang/go/issues/63432#issuecomment-1751610604 +[^6]: Only available if `toolchain` directive exists [dependency-graph]: ../../configuration/reporting.md#show-origins-of-vulnerable-dependencies From f0fe5c5ea1988d6bddb2b318e0fb9594c602f23f Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Mon, 15 Jul 2024 14:18:13 +0600 Subject: [PATCH 04/14] docs(go): add info about toolchain and local go version --- docs/docs/coverage/language/golang.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/docs/coverage/language/golang.md b/docs/docs/coverage/language/golang.md index 5644325dcc14..fbff40e9efef 100644 --- a/docs/docs/coverage/language/golang.md +++ b/docs/docs/coverage/language/golang.md @@ -65,6 +65,13 @@ To identify licenses and dependency relationships, you need to download modules such as `go mod download`, `go mod tidy`, etc. Trivy traverses `$GOPATH/pkg/mod` and collects those extra information. +#### stdlib +By default, `Go` selects the higher version from of `toolchan` or local version of `Go`. +See [toolchain] for more details. +But Trivy doesn't use third-party application or utilities, so Trivy can't detect the local version of `Go`. + +This is why Trivy uses the `toolchain` version for `stdlib` - as the minimum required version for the `go.mod` file. + ### Go binaries Trivy scans binaries built by Go, which include [module information](https://tip.golang.org/doc/go1.18#go-version). If there is a Go binary in your container image, Trivy automatically finds and scans it. @@ -96,3 +103,4 @@ empty if it cannot do so[^5]. For the second case, the version of such packages [^6]: Only available if `toolchain` directive exists [dependency-graph]: ../../configuration/reporting.md#show-origins-of-vulnerable-dependencies +[toolchain]: https://go.dev/doc/toolchain From 5c136e9bd8e4805831149a0fc72631fdcb492f53 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Thu, 18 Jul 2024 13:53:54 +0600 Subject: [PATCH 05/14] feat: parse `go` line when toolchain omitted --- pkg/dependency/parser/golang/mod/parse.go | 65 ++++++++++++--- .../parser/golang/mod/parse_test.go | 79 +++++++++++++++++++ 2 files changed, 133 insertions(+), 11 deletions(-) diff --git a/pkg/dependency/parser/golang/mod/parse.go b/pkg/dependency/parser/golang/mod/parse.go index 936e003146cd..ecf0ac1dabba 100644 --- a/pkg/dependency/parser/golang/mod/parse.go +++ b/pkg/dependency/parser/golang/mod/parse.go @@ -80,21 +80,21 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc skipIndirect := true if modFileParsed.Go != nil { // Old go.mod file may not include the go version. Go version for these files is less than 1.17 - skipIndirect = lessThan117(modFileParsed.Go.Version) + skipIndirect = lessThan(modFileParsed.Go.Version, 1, 17) } - // Stdlib - if toolchain := modFileParsed.Toolchain; toolchain != nil { - // `go1.22.5` => `1.22.5` - ver := strings.TrimPrefix(toolchain.Name, "go") + // Use minimal required go version from `toolchain` line (or from `go` line if `toolchain` is omitted) as `stdlib` + if toolchainVer := toolchainVersion(modFileParsed.Toolchain, modFileParsed.Go); toolchainVer != "" { pkgs["stdlib"] = ftypes.Package{ - // Add the toolchain version as stdlib version - ID: packageID("stdlib", ver), + ID: packageID("stdlib", toolchainVer), Name: "stdlib", - Version: ver, + Version: toolchainVer, Relationship: ftypes.RelationshipDirect, // Considered a direct dependency as the main module depends on the standard packages. } } + if toolchain := modFileParsed.Toolchain; toolchain != nil { + + } // Main module if m := modFileParsed.Module; m != nil { @@ -163,8 +163,8 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc return lo.Values(pkgs), nil, nil } -// Check if the Go version is less than 1.17 -func lessThan117(ver string) bool { +// lessThan checks if the Go version is less than `.` +func lessThan(ver string, majorVer, minorVer int) bool { ss := strings.Split(ver, ".") if len(ss) != 2 { return false @@ -178,7 +178,50 @@ func lessThan117(ver string) bool { return false } - return major <= 1 && minor < 17 + return major <= majorVer && minor < minorVer +} + +// toolchainVersion returns version from `toolchain`. +// If `toolchain` is omitted - return version from `go` line (if it is version in toolchain format) +// cf. https://go.dev/doc/toolchain +func toolchainVersion(toolchain *modfile.Toolchain, goVer *modfile.Go) string { + if toolchain != nil && toolchain.Name != "" { + // `go1.22.5` => `1.22.5` + return strings.TrimPrefix(toolchain.Name, "go") + } + + if goVer != nil && isToolchainVer(goVer.Version) { + return goVer.Version + } + return "" +} + +// isToolchainVer returns true if `ver` is the toolchain format version +// e.g. `1.22.0` or `1.21rc1` +// cf. https://go.dev/doc/toolchain +func isToolchainVer(ver string) bool { + ss := strings.Split(ver, ".") + // e.g. `1.22.0` or `1.22.0-suffix.with.dot`. + // go toolchain discards off any suffix beginning with `-` when compares versions + // `toolchain` has been added in go 1.21 + // So we need to check that minor version <= 21 + if len(ss) > 2 && !lessThan(strings.Join(ss[:2], "."), 1, 21) { + return true + } + + // Go `1.N` release candidates, which are issued before `1.N.0`, use the version syntax `1.NrcR` format. + majorMinorVer, _, rcFound := strings.Cut(ver, "rc") + // This is `1.N` version (e.g. `1.21`) + // We can't be sure this is toolchain version: + // cf. https://github.com/aquasecurity/trivy/pull/7163#discussion_r1680436648 + // Or this can be old beta format (e.g. `1.18beta2`) + if !rcFound { + return false + } + + // `toolchain` has been added in go 1.21 + // So we need to check that minor version <= 21 + return !lessThan(majorMinorVer, 1, 21) } func packageID(name, version string) string { diff --git a/pkg/dependency/parser/golang/mod/parse_test.go b/pkg/dependency/parser/golang/mod/parse_test.go index 598cb3fe70f3..b5dfc5c609a7 100644 --- a/pkg/dependency/parser/golang/mod/parse_test.go +++ b/pkg/dependency/parser/golang/mod/parse_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/mod/modfile" ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" ) @@ -95,3 +96,81 @@ func TestParse(t *testing.T) { }) } } + +func TestToolchainVersion(t *testing.T) { + tests := []struct { + name string + modFile modfile.File + want string + }{ + { + name: "version from toolchain line", + modFile: modfile.File{ + Toolchain: &modfile.Toolchain{ + Name: "1.21.1", + }, + }, + want: "1.21.1", + }, + { + name: "'1.18rc1' from go line", + modFile: modfile.File{ + Go: &modfile.Go{ + Version: "1.18rc1", + }, + }, + want: "", + }, + { + name: "'1.18.1' from go line", + modFile: modfile.File{ + Go: &modfile.Go{ + Version: "1.18.1", + }, + }, + want: "", + }, + { + name: "'1.22' from go line", + modFile: modfile.File{ + Go: &modfile.Go{ + Version: "1.22", + }, + }, + want: "", + }, + { + name: "'1.21rc1' from go line", + modFile: modfile.File{ + Go: &modfile.Go{ + Version: "1.21rc1", + }, + }, + want: "1.21rc1", + }, + { + name: "'1.21.2' from go line", + modFile: modfile.File{ + Go: &modfile.Go{ + Version: "1.21.2", + }, + }, + want: "1.21.2", + }, + { + name: "'1.21.3-with.dot.in.suffix' from go line", + modFile: modfile.File{ + Go: &modfile.Go{ + Version: "1.21.3-with.dot.in.suffix", + }, + }, + want: "1.21.3-with.dot.in.suffix", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + require.Equal(t, tt.want, toolchainVersion(tt.modFile.Toolchain, tt.modFile.Go)) + }) + } +} From 797a1b921228541b276a7074370f463397ec10ce Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Thu, 18 Jul 2024 13:58:06 +0600 Subject: [PATCH 06/14] docs: add info about Go version restrictions --- docs/docs/coverage/language/golang.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/docs/coverage/language/golang.md b/docs/docs/coverage/language/golang.md index fbff40e9efef..09c48aa700d4 100644 --- a/docs/docs/coverage/language/golang.md +++ b/docs/docs/coverage/language/golang.md @@ -70,7 +70,10 @@ By default, `Go` selects the higher version from of `toolchan` or local version See [toolchain] for more details. But Trivy doesn't use third-party application or utilities, so Trivy can't detect the local version of `Go`. -This is why Trivy uses the `toolchain` version for `stdlib` - as the minimum required version for the `go.mod` file. +This is why Trivy uses the `toolchain` version (or version from `go` line, if `toolchain` line is omitted) for `stdlib` - as the minimum required version for the `go.mod` file. + +!!! note + `toolchain` was added in Go `1.21`, so Trivy detects `stdlib` only for `Go` 1.21 or higher. ### Go binaries Trivy scans binaries built by Go, which include [module information](https://tip.golang.org/doc/go1.18#go-version). From fe248fc548db1792001e31be34f93ef64655df37 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Thu, 18 Jul 2024 16:11:50 +0600 Subject: [PATCH 07/14] refactor: update logic to detect Go version for `go` line --- pkg/dependency/parser/golang/mod/parse.go | 55 ++++++++++--------- .../parser/golang/mod/parse_test.go | 13 ++++- 2 files changed, 39 insertions(+), 29 deletions(-) diff --git a/pkg/dependency/parser/golang/mod/parse.go b/pkg/dependency/parser/golang/mod/parse.go index ecf0ac1dabba..5d16714a5f34 100644 --- a/pkg/dependency/parser/golang/mod/parse.go +++ b/pkg/dependency/parser/golang/mod/parse.go @@ -165,6 +165,10 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc // lessThan checks if the Go version is less than `.` func lessThan(ver string, majorVer, minorVer int) bool { + if ver == "" { + return false + } + ss := strings.Split(ver, ".") if len(ss) != 2 { return false @@ -190,38 +194,35 @@ func toolchainVersion(toolchain *modfile.Toolchain, goVer *modfile.Go) string { return strings.TrimPrefix(toolchain.Name, "go") } - if goVer != nil && isToolchainVer(goVer.Version) { - return goVer.Version + if goVer != nil { + return toolchainVersionFromGoLine(goVer.Version) } return "" } -// isToolchainVer returns true if `ver` is the toolchain format version -// e.g. `1.22.0` or `1.21rc1` -// cf. https://go.dev/doc/toolchain -func isToolchainVer(ver string) bool { - ss := strings.Split(ver, ".") - // e.g. `1.22.0` or `1.22.0-suffix.with.dot`. - // go toolchain discards off any suffix beginning with `-` when compares versions - // `toolchain` has been added in go 1.21 - // So we need to check that minor version <= 21 - if len(ss) > 2 && !lessThan(strings.Join(ss[:2], "."), 1, 21) { - return true - } - - // Go `1.N` release candidates, which are issued before `1.N.0`, use the version syntax `1.NrcR` format. - majorMinorVer, _, rcFound := strings.Cut(ver, "rc") - // This is `1.N` version (e.g. `1.21`) - // We can't be sure this is toolchain version: - // cf. https://github.com/aquasecurity/trivy/pull/7163#discussion_r1680436648 - // Or this can be old beta format (e.g. `1.18beta2`) - if !rcFound { - return false - } +// toolchainVersionFromGoLine detects Go version from `go` line if `toolchain` line is omitted +func toolchainVersionFromGoLine(ver string) string { + var majorMinorVer string - // `toolchain` has been added in go 1.21 - // So we need to check that minor version <= 21 - return !lessThan(majorMinorVer, 1, 21) + // `1.N.P` or `1.N.P-suffix` version + // e.g. `1.22.0` or `1.22.0-suffix.with.dot`. + if ss := strings.Split(ver, "."); len(ss) > 2 { + majorMinorVer = strings.Join(ss[:2], ".") + } else if v, _, rcFound := strings.Cut(ver, "rc"); rcFound { // `1.NrcR` version. e.g. `1.22rc1` + majorMinorVer = v + } else { // `1.N` version. e.g. `1.22` + majorMinorVer = ver + // Add patch `0` to get version format + ver = v + ".0" + } + + // `toolchain` has been added in go 1.21. + // So we need to check that Go version is 1.21 or higher. + // cf. https://github.com/aquasecurity/trivy/pull/7163#discussion_r1682424315 + if lessThan(majorMinorVer, 1, 21) { + return "" + } + return ver } func packageID(name, version string) string { diff --git a/pkg/dependency/parser/golang/mod/parse_test.go b/pkg/dependency/parser/golang/mod/parse_test.go index b5dfc5c609a7..db634abf280d 100644 --- a/pkg/dependency/parser/golang/mod/parse_test.go +++ b/pkg/dependency/parser/golang/mod/parse_test.go @@ -131,14 +131,23 @@ func TestToolchainVersion(t *testing.T) { want: "", }, { - name: "'1.22' from go line", + name: "'1.20' from go line", modFile: modfile.File{ Go: &modfile.Go{ - Version: "1.22", + Version: "1.20", }, }, want: "", }, + { + name: "'1.21' from go line", + modFile: modfile.File{ + Go: &modfile.Go{ + Version: "1.21", + }, + }, + want: "1.21.0", + }, { name: "'1.21rc1' from go line", modFile: modfile.File{ From 4c0d49c27695de8d3832ca63f83f3d81315fc6b2 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Thu, 18 Jul 2024 16:11:55 +0600 Subject: [PATCH 08/14] update docs --- docs/docs/coverage/language/golang.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/docs/coverage/language/golang.md b/docs/docs/coverage/language/golang.md index 09c48aa700d4..a4f9128154fe 100644 --- a/docs/docs/coverage/language/golang.md +++ b/docs/docs/coverage/language/golang.md @@ -68,12 +68,17 @@ Trivy traverses `$GOPATH/pkg/mod` and collects those extra information. #### stdlib By default, `Go` selects the higher version from of `toolchan` or local version of `Go`. See [toolchain] for more details. -But Trivy doesn't use third-party application or utilities, so Trivy can't detect the local version of `Go`. -This is why Trivy uses the `toolchain` version (or version from `go` line, if `toolchain` line is omitted) for `stdlib` - as the minimum required version for the `go.mod` file. +To obtain reproducible scan results Trivy doesn't check the local version of `Go`. +Trivy shows the minimum required version for the `go.mod` file, obtained from `toolchain` line (or from the `go` line, if `toolchain` line is omitted). !!! note - `toolchain` was added in Go `1.21`, so Trivy detects `stdlib` only for `Go` 1.21 or higher. + Trivy detects `stdlib` only for `Go` 1.21 or higher. + + The version from the `go` line (for `Go` 1.20 or early) is not a minimum required version. + For details, see [this](https://go.googlesource.com/proposal/+/master/design/57001-gotoolchain.md). + + ### Go binaries Trivy scans binaries built by Go, which include [module information](https://tip.golang.org/doc/go1.18#go-version). From 4d0814c55f7f145e145ee9ec840ff14d53de285a Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 30 Aug 2024 12:28:19 +0600 Subject: [PATCH 09/14] feat: add useMinVersion + update comments --- pkg/dependency/parser/golang/mod/parse.go | 36 +++++++++++++++-------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/pkg/dependency/parser/golang/mod/parse.go b/pkg/dependency/parser/golang/mod/parse.go index 5d16714a5f34..519a4bb6c3e2 100644 --- a/pkg/dependency/parser/golang/mod/parse.go +++ b/pkg/dependency/parser/golang/mod/parse.go @@ -29,12 +29,14 @@ var ( ) type Parser struct { - replace bool // 'replace' represents if the 'replace' directive should be taken into account. + replace bool // 'replace' represents if the 'replace' directive should be taken into account. + useMinVersion bool } -func NewParser(replace bool) *Parser { +func NewParser(replace, useMinVersion bool) *Parser { return &Parser{ - replace: replace, + replace: replace, + useMinVersion: useMinVersion, } } @@ -83,8 +85,9 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc skipIndirect = lessThan(modFileParsed.Go.Version, 1, 17) } - // Use minimal required go version from `toolchain` line (or from `go` line if `toolchain` is omitted) as `stdlib` - if toolchainVer := toolchainVersion(modFileParsed.Toolchain, modFileParsed.Go); toolchainVer != "" { + // Use minimal required go version from `toolchain` line (or from `go` line if `toolchain` is omitted) as `stdlib`. + // Show `stdlib` only with `useMinVersion` flag. + if toolchainVer := toolchainVersion(modFileParsed.Toolchain, modFileParsed.Go); p.useMinVersion && toolchainVer != "" { pkgs["stdlib"] = ftypes.Package{ ID: packageID("stdlib", toolchainVer), Name: "stdlib", @@ -190,8 +193,11 @@ func lessThan(ver string, majorVer, minorVer int) bool { // cf. https://go.dev/doc/toolchain func toolchainVersion(toolchain *modfile.Toolchain, goVer *modfile.Go) string { if toolchain != nil && toolchain.Name != "" { - // `go1.22.5` => `1.22.5` - return strings.TrimPrefix(toolchain.Name, "go") + // cf. https://go.dev/doc/toolchain#name + // `dropping the initial go and discarding off any suffix beginning with -` + // e.g. `go1.22.5-custom` => `1.22.5` + name, _, _ := strings.Cut(toolchain.Name, "-") + return strings.TrimPrefix(name, "go") } if goVer != nil { @@ -201,18 +207,22 @@ func toolchainVersion(toolchain *modfile.Toolchain, goVer *modfile.Go) string { } // toolchainVersionFromGoLine detects Go version from `go` line if `toolchain` line is omitted +// `go` line supports the following formats: +// cf. https://go.dev/doc/toolchain#version +// - `1.N.P`. e.g. `1.22.0` +// - `1.N`. e.g. `1.22` +// - `1.NrcR`. e.g. `1.22rc1` +// - `1.NbetaR`. e.g. `1.18beta1` - only for 1.20 or early func toolchainVersionFromGoLine(ver string) string { var majorMinorVer string - // `1.N.P` or `1.N.P-suffix` version - // e.g. `1.22.0` or `1.22.0-suffix.with.dot`. - if ss := strings.Split(ver, "."); len(ss) > 2 { + if ss := strings.Split(ver, "."); len(ss) > 2 { // `1.N.P` majorMinorVer = strings.Join(ss[:2], ".") - } else if v, _, rcFound := strings.Cut(ver, "rc"); rcFound { // `1.NrcR` version. e.g. `1.22rc1` + } else if v, _, rcFound := strings.Cut(ver, "rc"); rcFound { // `1.NrcR` majorMinorVer = v - } else { // `1.N` version. e.g. `1.22` + } else { // `1.N` majorMinorVer = ver - // Add patch `0` to get version format + // Add `.0` suffix to avoid user confusing ver = v + ".0" } From 294bd1e07ba787e5528662a3daa6d9d9743264ed Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 30 Aug 2024 12:28:29 +0600 Subject: [PATCH 10/14] test: update testcases --- .../parser/golang/mod/parse_test.go | 38 +++++++++++-------- .../parser/golang/mod/parse_testcase.go | 10 ++++- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/pkg/dependency/parser/golang/mod/parse_test.go b/pkg/dependency/parser/golang/mod/parse_test.go index db634abf280d..10bda7f01144 100644 --- a/pkg/dependency/parser/golang/mod/parse_test.go +++ b/pkg/dependency/parser/golang/mod/parse_test.go @@ -14,16 +14,24 @@ import ( func TestParse(t *testing.T) { tests := []struct { - name string - file string - replace bool - want []ftypes.Package + name string + file string + replace bool + useMinVersion bool + want []ftypes.Package }{ + { + name: "normal with stdlib", + file: "testdata/normal/go.mod", + replace: true, + useMinVersion: true, + want: GoModNormal, + }, { name: "normal", file: "testdata/normal/go.mod", replace: true, - want: GoModNormal, + want: GoModNormalWithoutStdlib, }, { name: "without go version", @@ -86,7 +94,7 @@ func TestParse(t *testing.T) { f, err := os.Open(tt.file) require.NoError(t, err) - got, _, err := NewParser(tt.replace).Parse(f) + got, _, err := NewParser(tt.replace, tt.useMinVersion).Parse(f) require.NoError(t, err) sort.Sort(ftypes.Packages(got)) @@ -112,6 +120,15 @@ func TestToolchainVersion(t *testing.T) { }, want: "1.21.1", }, + { + name: "version from toolchain line with suffix", + modFile: modfile.File{ + Toolchain: &modfile.Toolchain{ + Name: "1.21.1-custom", + }, + }, + want: "1.21.1", + }, { name: "'1.18rc1' from go line", modFile: modfile.File{ @@ -166,15 +183,6 @@ func TestToolchainVersion(t *testing.T) { }, want: "1.21.2", }, - { - name: "'1.21.3-with.dot.in.suffix' from go line", - modFile: modfile.File{ - Go: &modfile.Go{ - Version: "1.21.3-with.dot.in.suffix", - }, - }, - want: "1.21.3-with.dot.in.suffix", - }, } for _, tt := range tests { diff --git a/pkg/dependency/parser/golang/mod/parse_testcase.go b/pkg/dependency/parser/golang/mod/parse_testcase.go index 334b18703c60..4671ef3e6854 100644 --- a/pkg/dependency/parser/golang/mod/parse_testcase.go +++ b/pkg/dependency/parser/golang/mod/parse_testcase.go @@ -1,6 +1,10 @@ package mod -import ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" +import ( + "slices" + + ftypes "github.com/aquasecurity/trivy/pkg/fanal/types" +) var ( // execute go mod tidy in normal folder @@ -78,6 +82,10 @@ var ( }, } + GoModNormalWithoutStdlib = slices.DeleteFunc(slices.Clone(GoModNormal), func(f ftypes.Package) bool { + return f.Name == "stdlib" + }) + // execute go mod tidy in replaced folder GoModReplaced = []ftypes.Package{ { From 70ca3cde4a4827a2547e2f6b2a5324bdd2b6e17e Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 30 Aug 2024 13:26:42 +0600 Subject: [PATCH 11/14] fix: update newGoModAnalyzer --- pkg/fanal/analyzer/language/golang/mod/mod.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/fanal/analyzer/language/golang/mod/mod.go b/pkg/fanal/analyzer/language/golang/mod/mod.go index 96d40ba1c954..398511fdc63c 100644 --- a/pkg/fanal/analyzer/language/golang/mod/mod.go +++ b/pkg/fanal/analyzer/language/golang/mod/mod.go @@ -56,9 +56,9 @@ type gomodAnalyzer struct { func newGoModAnalyzer(opt analyzer.AnalyzerOptions) (analyzer.PostAnalyzer, error) { return &gomodAnalyzer{ - modParser: mod.NewParser(true), // Only the root module should replace + modParser: mod.NewParser(true, opt.DetectionPriority == types.PriorityComprehensive), // Only the root module should replace sumParser: sum.NewParser(), - leafModParser: mod.NewParser(false), + leafModParser: mod.NewParser(false, false), // Don't detect stdlib for non-root go.mod files licenseClassifierConfidenceLevel: opt.LicenseScannerOption.ClassifierConfidenceLevel, logger: log.WithPrefix("golang"), }, nil From e8aaef4b7b0b1304785e4c845787b56a0c60e519 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 30 Aug 2024 13:27:08 +0600 Subject: [PATCH 12/14] docs: update --- docs/docs/coverage/language/golang.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/docs/coverage/language/golang.md b/docs/docs/coverage/language/golang.md index ed3943e416a2..f2cbff03255a 100644 --- a/docs/docs/coverage/language/golang.md +++ b/docs/docs/coverage/language/golang.md @@ -18,7 +18,7 @@ The table below provides an outline of the features Trivy offers. | Artifact | Offline[^1] | Dev dependencies | [Dependency graph][dependency-graph] | Stdlib | [Detection Priority][detection-priority] | |----------|:-----------:|:-----------------|:------------------------------------:|:------:|:----------------------------------------:| -| Modules | ✅ | Include | ✅[^2] | ✅[^6] | - | +| Modules | ✅ | Include | ✅[^2] | ✅[^6] | [✅](#stdlib) | | Binaries | ✅ | Exclude | - | ✅[^4] | Not needed | !!! note @@ -66,6 +66,8 @@ such as `go mod download`, `go mod tidy`, etc. Trivy traverses `$GOPATH/pkg/mod` and collects those extra information. #### stdlib +If [--detection-priority comprehensive][detection-priority] is passed, Trivy determines the minimum version of `Go` and saves it as a `stdlib` dependency. + By default, `Go` selects the higher version from of `toolchan` or local version of `Go`. See [toolchain] for more details. From 175b5421320e1b3f8584634a5271d814f0c0ef67 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Fri, 30 Aug 2024 13:29:56 +0600 Subject: [PATCH 13/14] refactor: update comments --- pkg/dependency/parser/golang/mod/parse.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/dependency/parser/golang/mod/parse.go b/pkg/dependency/parser/golang/mod/parse.go index 519a4bb6c3e2..98baf1102acd 100644 --- a/pkg/dependency/parser/golang/mod/parse.go +++ b/pkg/dependency/parser/golang/mod/parse.go @@ -206,13 +206,13 @@ func toolchainVersion(toolchain *modfile.Toolchain, goVer *modfile.Go) string { return "" } -// toolchainVersionFromGoLine detects Go version from `go` line if `toolchain` line is omitted +// toolchainVersionFromGoLine detects Go version from `go` line if `toolchain` line is omitted. // `go` line supports the following formats: // cf. https://go.dev/doc/toolchain#version // - `1.N.P`. e.g. `1.22.0` // - `1.N`. e.g. `1.22` // - `1.NrcR`. e.g. `1.22rc1` -// - `1.NbetaR`. e.g. `1.18beta1` - only for 1.20 or early +// - `1.NbetaR`. e.g. `1.18beta1` - only for Go 1.20 or earlier func toolchainVersionFromGoLine(ver string) string { var majorMinorVer string @@ -222,7 +222,8 @@ func toolchainVersionFromGoLine(ver string) string { majorMinorVer = v } else { // `1.N` majorMinorVer = ver - // Add `.0` suffix to avoid user confusing + // Add `.0` suffix to avoid user confusing. + // See https://github.com/aquasecurity/trivy/pull/7163#discussion_r1682424315 ver = v + ".0" } From e6411c054e1c8bcf2fdf4175c0a7b522698d3f91 Mon Sep 17 00:00:00 2001 From: DmitriyLewen Date: Mon, 2 Sep 2024 16:17:49 +0600 Subject: [PATCH 14/14] refactor --- pkg/dependency/parser/golang/mod/parse.go | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/pkg/dependency/parser/golang/mod/parse.go b/pkg/dependency/parser/golang/mod/parse.go index 98baf1102acd..bbf42926a766 100644 --- a/pkg/dependency/parser/golang/mod/parse.go +++ b/pkg/dependency/parser/golang/mod/parse.go @@ -87,17 +87,16 @@ func (p *Parser) Parse(r xio.ReadSeekerAt) ([]ftypes.Package, []ftypes.Dependenc // Use minimal required go version from `toolchain` line (or from `go` line if `toolchain` is omitted) as `stdlib`. // Show `stdlib` only with `useMinVersion` flag. - if toolchainVer := toolchainVersion(modFileParsed.Toolchain, modFileParsed.Go); p.useMinVersion && toolchainVer != "" { - pkgs["stdlib"] = ftypes.Package{ - ID: packageID("stdlib", toolchainVer), - Name: "stdlib", - Version: toolchainVer, - Relationship: ftypes.RelationshipDirect, // Considered a direct dependency as the main module depends on the standard packages. + if p.useMinVersion { + if toolchainVer := toolchainVersion(modFileParsed.Toolchain, modFileParsed.Go); toolchainVer != "" { + pkgs["stdlib"] = ftypes.Package{ + ID: packageID("stdlib", toolchainVer), + Name: "stdlib", + Version: toolchainVer, + Relationship: ftypes.RelationshipDirect, // Considered a direct dependency as the main module depends on the standard packages. + } } } - if toolchain := modFileParsed.Toolchain; toolchain != nil { - - } // Main module if m := modFileParsed.Module; m != nil {