mirror of https://github.com/golang/go.git
gopls/internal/govulncheck: sync x/vuln@62b0186
VulnDB OSV schema was changed recently https://go-review.googlesource.com/c/vulndb/+/424895 to fix the misinterpretation of 'affected.package.name', and the database entries were repopulated with the new schema. We need to update the client library to pick up the change. We also need to update the fake vulndb entries used in tests. gopls/regtest/misc/testdata/vulndb was copied from golang.org/x/vuln/cmd/govulncheck/testdata/vulndb @ 62b0186 (the version updated in cl/424895) Also reverse golang.org/cl/425183 which includes the position information in the SummarizeCallStack result. Like in govulncheck -v, the position info is already available in the callstack, thus this is unnecessary for us. Since x/vuln is currently frozen until the preview release, revert it from gopls/internal/vulncheck. Ran go mod tidy -compat=1.16; otherwise, the transitive dependency on github.com/client9/misspell from golang.org/x/vuln breaks go1.16 build. Updated copy.sh script to copy x/vuln/internal/semver package (golang/go#54401) and add the build tags back to all go files. Gopls's builder builds&tests packages with old go versions, so we still need go1.18 build tag. Fixes golang/go#54818 Change-Id: I37770d698082378656a7988d3412a4ca2196ca7b Reviewed-on: https://go-review.googlesource.com/c/tools/+/427542 gopls-CI: kokoro <noreply+kokoro@google.com> Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Jonathan Amsterdam <jba@google.com>
This commit is contained in:
parent
655abda1c0
commit
eb8352e307
|
|
@ -10,12 +10,14 @@ require (
|
|||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
|
||||
golang.org/x/sys v0.0.0-20220808155132-1c4a2a72c664
|
||||
golang.org/x/tools v0.1.13-0.20220810174125-0ad49fdeb955
|
||||
golang.org/x/vuln v0.0.0-20220809164104-12ff722659c1
|
||||
golang.org/x/vuln v0.0.0-20220901221904-62b0186a1058
|
||||
honnef.co/go/tools v0.3.3
|
||||
mvdan.cc/gofumpt v0.3.1
|
||||
mvdan.cc/xurls/v2 v2.4.0
|
||||
)
|
||||
|
||||
require golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.2.0 // indirect
|
||||
github.com/google/safehtml v0.0.2 // indirect
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnX
|
|||
github.com/frankban/quicktest v1.14.2/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||
github.com/google/go-cmdtest v0.4.0/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
|
|
@ -43,6 +42,8 @@ github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJy
|
|||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
|
||||
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
|
||||
golang.org/x/exp/typeparams v0.0.0-20220218215828-6cf2b201936e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
||||
golang.org/x/exp/typeparams v0.0.0-20220722155223-a9213eeb770e h1:7Xs2YCOpMlNqSQSmrrnhlzBXIE/bpMecZplbLePTJvE=
|
||||
golang.org/x/exp/typeparams v0.0.0-20220722155223-a9213eeb770e/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
|
||||
|
|
@ -68,8 +69,8 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
|
|||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/vuln v0.0.0-20220809164104-12ff722659c1 h1:wxIK8Hnmd3ervTxk4aON+gAbfWbb2hToeKSTQd0eXgo=
|
||||
golang.org/x/vuln v0.0.0-20220809164104-12ff722659c1/go.mod h1:t0tyWMAuNGUOL2N4il/aj/M5LLt4ktPpOGuTBNUqmiM=
|
||||
golang.org/x/vuln v0.0.0-20220901221904-62b0186a1058 h1:YnB27EXBD8XxB0JcaOeluuvhF2kS4DrH0k+lpopG2xc=
|
||||
golang.org/x/vuln v0.0.0-20220901221904-62b0186a1058/go.mod h1:7tDfEDtOLlzHQRi4Yzfg5seVBSvouUIjyPzBx4q5CxQ=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ package govulncheck
|
|||
import (
|
||||
"encoding/json"
|
||||
"go/build"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
|
@ -66,7 +65,7 @@ func (c *FSCache) ReadIndex(dbName string) (client.DBIndex, time.Time, error) {
|
|||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
b, err := ioutil.ReadFile(filepath.Join(c.rootDir, dbName, "index.json"))
|
||||
b, err := os.ReadFile(filepath.Join(c.rootDir, dbName, "index.json"))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, time.Time{}, nil
|
||||
|
|
@ -95,7 +94,7 @@ func (c *FSCache) WriteIndex(dbName string, index client.DBIndex, retrieved time
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile(filepath.Join(path, "index.json"), j, 0666); err != nil {
|
||||
if err := os.WriteFile(filepath.Join(path, "index.json"), j, 0666); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
@ -105,7 +104,11 @@ func (c *FSCache) ReadEntries(dbName string, p string) ([]*osv.Entry, error) {
|
|||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
b, err := ioutil.ReadFile(filepath.Join(c.rootDir, dbName, p, "vulns.json"))
|
||||
ep, err := client.EscapeModulePath(p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, err := os.ReadFile(filepath.Join(c.rootDir, dbName, ep, "vulns.json"))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
|
|
@ -123,7 +126,11 @@ func (c *FSCache) WriteEntries(dbName string, p string, entries []*osv.Entry) er
|
|||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
path := filepath.Join(c.rootDir, dbName, p)
|
||||
ep, err := client.EscapeModulePath(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
path := filepath.Join(c.rootDir, dbName, ep)
|
||||
if err := os.MkdirAll(path, 0777); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -131,7 +138,7 @@ func (c *FSCache) WriteEntries(dbName string, p string, entries []*osv.Entry) er
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile(filepath.Join(path, "vulns.json"), j, 0666); err != nil {
|
||||
if err := os.WriteFile(filepath.Join(path, "vulns.json"), j, 0666); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ func TestConcurrency(t *testing.T) {
|
|||
i := i
|
||||
g.Go(func() error {
|
||||
id := i % 5
|
||||
p := fmt.Sprintf("package%d", id)
|
||||
p := fmt.Sprintf("example.com/package%d", id)
|
||||
|
||||
entries, err := cache.ReadEntries(dbName, p)
|
||||
if err != nil {
|
||||
|
|
@ -115,7 +115,7 @@ func TestConcurrency(t *testing.T) {
|
|||
// sanity checking
|
||||
for i := 0; i < 5; i++ {
|
||||
id := fmt.Sprint(i)
|
||||
p := fmt.Sprintf("package%s", id)
|
||||
p := fmt.Sprintf("example.com/package%s", id)
|
||||
|
||||
es, err := cache.ReadEntries(dbName, p)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -11,3 +11,22 @@ set -o pipefail
|
|||
|
||||
rm -f *.go
|
||||
cp ../../../../vuln/cmd/govulncheck/internal/govulncheck/*.go .
|
||||
|
||||
sed -i '' 's/\"golang.org\/x\/vuln\/internal\/semver\"/\"golang.org\/x\/tools\/gopls\/internal\/govulncheck\/semver\"/g' *.go
|
||||
sed -i '' -e '4 i\
|
||||
' -e '4 i\
|
||||
//go:build go1.18' -e '4 i\
|
||||
// +build go1.18' *.go
|
||||
|
||||
# Copy golang.org/x/vuln/internal/semver that
|
||||
# golang.org/x/vuln/cmd/govulncheck/internal/govulncheck
|
||||
# depends on.
|
||||
|
||||
mkdir -p semver
|
||||
cd semver
|
||||
rm -f *.go
|
||||
cp ../../../../../vuln/internal/semver/*.go .
|
||||
sed -i '' -e '4 i\
|
||||
' -e '4 i\
|
||||
//go:build go1.18' -e '4 i\
|
||||
// +build go1.18' *.go
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package govulncheck
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// AbsRelShorter takes path and returns its path relative
|
||||
// to the current directory, if shorter. Returns path
|
||||
// when path is an empty string or upon any error.
|
||||
func AbsRelShorter(path string) string {
|
||||
if path == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
c, err := filepath.Abs(".")
|
||||
if err != nil {
|
||||
return path
|
||||
}
|
||||
r, err := filepath.Rel(c, path)
|
||||
if err != nil {
|
||||
return path
|
||||
}
|
||||
|
||||
rSegments := strings.Split(r, string(filepath.Separator))
|
||||
pathSegments := strings.Split(path, string(filepath.Separator))
|
||||
if len(rSegments) < len(pathSegments) {
|
||||
return r
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package govulncheck
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAbsRelShorter(t *testing.T) {
|
||||
thisFile := "filepath_test.go"
|
||||
thisFileAbs, _ := filepath.Abs(thisFile)
|
||||
|
||||
tf, err := os.CreateTemp("", "filepath_test.gp")
|
||||
if err != nil {
|
||||
t.Errorf("could not create temporary filepath_test.go file: %v", err)
|
||||
}
|
||||
tempFile := tf.Name()
|
||||
tempFileAbs, _ := filepath.Abs(tempFile)
|
||||
|
||||
for _, test := range []struct {
|
||||
l string
|
||||
want string
|
||||
}{
|
||||
{thisFile, "filepath_test.go"},
|
||||
{thisFileAbs, "filepath_test.go"},
|
||||
// Relative path to temp file from "." is longer as
|
||||
// it needs to go back the length of the absolute
|
||||
// path and then in addition go to os.TempDir.
|
||||
{tempFile, tempFileAbs},
|
||||
} {
|
||||
if got := AbsRelShorter(test.l); got != test.want {
|
||||
t.Errorf("want %s; got %s", test.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
// Package semver provides shared utilities for manipulating
|
||||
// Go semantic versions.
|
||||
package semver
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// addSemverPrefix adds a 'v' prefix to s if it isn't already prefixed
|
||||
// with 'v' or 'go'. This allows us to easily test go-style SEMVER
|
||||
// strings against normal SEMVER strings.
|
||||
func addSemverPrefix(s string) string {
|
||||
if !strings.HasPrefix(s, "v") && !strings.HasPrefix(s, "go") {
|
||||
return "v" + s
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// removeSemverPrefix removes the 'v' or 'go' prefixes from go-style
|
||||
// SEMVER strings, for usage in the public vulnerability format.
|
||||
func removeSemverPrefix(s string) string {
|
||||
s = strings.TrimPrefix(s, "v")
|
||||
s = strings.TrimPrefix(s, "go")
|
||||
return s
|
||||
}
|
||||
|
||||
// CanonicalizeSemverPrefix turns a SEMVER string into the canonical
|
||||
// representation using the 'v' prefix, as used by the OSV format.
|
||||
// Input may be a bare SEMVER ("1.2.3"), Go prefixed SEMVER ("go1.2.3"),
|
||||
// or already canonical SEMVER ("v1.2.3").
|
||||
func CanonicalizeSemverPrefix(s string) string {
|
||||
return addSemverPrefix(removeSemverPrefix(s))
|
||||
}
|
||||
|
||||
var (
|
||||
// Regexp for matching go tags. The groups are:
|
||||
// 1 the major.minor version
|
||||
// 2 the patch version, or empty if none
|
||||
// 3 the entire prerelease, if present
|
||||
// 4 the prerelease type ("beta" or "rc")
|
||||
// 5 the prerelease number
|
||||
tagRegexp = regexp.MustCompile(`^go(\d+\.\d+)(\.\d+|)((beta|rc|-pre)(\d+))?$`)
|
||||
)
|
||||
|
||||
// This is a modified copy of pkgsite/internal/stdlib:VersionForTag.
|
||||
func GoTagToSemver(tag string) string {
|
||||
if tag == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
tag = strings.Fields(tag)[0]
|
||||
// Special cases for go1.
|
||||
if tag == "go1" {
|
||||
return "v1.0.0"
|
||||
}
|
||||
if tag == "go1.0" {
|
||||
return ""
|
||||
}
|
||||
m := tagRegexp.FindStringSubmatch(tag)
|
||||
if m == nil {
|
||||
return ""
|
||||
}
|
||||
version := "v" + m[1]
|
||||
if m[2] != "" {
|
||||
version += m[2]
|
||||
} else {
|
||||
version += ".0"
|
||||
}
|
||||
if m[3] != "" {
|
||||
if !strings.HasPrefix(m[4], "-") {
|
||||
version += "-"
|
||||
}
|
||||
version += m[4] + "." + m[5]
|
||||
}
|
||||
return version
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2022 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package semver
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCanonicalize(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
v string
|
||||
want string
|
||||
}{
|
||||
{"v1.2.3", "v1.2.3"},
|
||||
{"1.2.3", "v1.2.3"},
|
||||
{"go1.2.3", "v1.2.3"},
|
||||
} {
|
||||
got := CanonicalizeSemverPrefix(test.v)
|
||||
if got != test.want {
|
||||
t.Errorf("want %s; got %s", test.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoTagToSemver(t *testing.T) {
|
||||
for _, test := range []struct {
|
||||
v string
|
||||
want string
|
||||
}{
|
||||
{"go1.19", "v1.19.0"},
|
||||
{"go1.20-pre4", "v1.20.0-pre.4"},
|
||||
} {
|
||||
got := GoTagToSemver(test.v)
|
||||
if got != test.want {
|
||||
t.Errorf("want %s; got %s", test.want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@ func (e *PackageError) Error() string {
|
|||
var b strings.Builder
|
||||
fmt.Fprintln(&b, "Packages contain errors:")
|
||||
for _, e := range e.Errors {
|
||||
fmt.Println(&b, e)
|
||||
fmt.Fprintln(&b, e)
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"golang.org/x/mod/semver"
|
||||
isem "golang.org/x/tools/gopls/internal/govulncheck/semver"
|
||||
"golang.org/x/vuln/osv"
|
||||
"golang.org/x/vuln/vulncheck"
|
||||
)
|
||||
|
|
@ -24,7 +25,8 @@ func LatestFixed(as []osv.Affected) string {
|
|||
for _, r := range a.Ranges {
|
||||
if r.Type == osv.TypeSemver {
|
||||
for _, e := range r.Events {
|
||||
if e.Fixed != "" && (v == "" || semver.Compare(e.Fixed, v) > 0) {
|
||||
if e.Fixed != "" && (v == "" ||
|
||||
semver.Compare(isem.CanonicalizeSemverPrefix(e.Fixed), isem.CanonicalizeSemverPrefix(v)) > 0) {
|
||||
v = e.Fixed
|
||||
}
|
||||
}
|
||||
|
|
@ -60,12 +62,16 @@ func SummarizeCallStack(cs vulncheck.CallStack, topPkgs map[string]bool, vulnPkg
|
|||
}
|
||||
iVuln += iTop + 1 // adjust for slice in call to highest.
|
||||
topName := FuncName(cs[iTop].Function)
|
||||
topPos := AbsRelShorter(FuncPos(cs[iTop].Call))
|
||||
if topPos != "" {
|
||||
topPos += ": "
|
||||
}
|
||||
vulnName := FuncName(cs[iVuln].Function)
|
||||
if iVuln == iTop+1 {
|
||||
return fmt.Sprintf("%s calls %s", topName, vulnName)
|
||||
return fmt.Sprintf("%s%s calls %s", topPos, topName, vulnName)
|
||||
}
|
||||
return fmt.Sprintf("%s calls %s, which eventually calls %s",
|
||||
topName, FuncName(cs[iTop+1].Function), vulnName)
|
||||
return fmt.Sprintf("%s%s calls %s, which eventually calls %s",
|
||||
topPos, topName, FuncName(cs[iTop+1].Function), vulnName)
|
||||
}
|
||||
|
||||
// highest returns the highest (one with the smallest index) entry in the call
|
||||
|
|
@ -107,3 +113,11 @@ func PkgPath(fn *vulncheck.FuncNode) string {
|
|||
func FuncName(fn *vulncheck.FuncNode) string {
|
||||
return strings.TrimPrefix(fn.String(), "*")
|
||||
}
|
||||
|
||||
// FuncPos returns the function position from call.
|
||||
func FuncPos(call *vulncheck.CallSite) string {
|
||||
if call != nil && call.Pos != nil {
|
||||
return call.Pos.String()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1 +1 @@
|
|||
[{"id":"GO-2020-0015","published":"2021-04-14T20:04:52Z","modified":"2021-06-07T12:00:00Z","aliases":["CVE-2020-14040"],"details":"An attacker could provide a single byte to a UTF16 decoder instantiated with\nUseBOM or ExpectBOM to trigger an infinite loop if the String function on\nthe Decoder is called, or the Decoder is passed to transform.String.\nIf used to parse user supplied input, this may be used as a denial of service\nvector.\n","affected":[{"package":{"name":"golang.org/x/text/encoding/unicode","ecosystem":"Go"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.3.3"}]}],"database_specific":{"url":"https://pkg.go.dev/vuln/GO-2020-0015"},"ecosystem_specific":{"symbols":["utf16Decoder.Transform","bomOverride.Transform"]}},{"package":{"name":"golang.org/x/text/transform","ecosystem":"Go"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.3.3"}]}],"database_specific":{"url":"https://pkg.go.dev/vuln/GO-2020-0015"},"ecosystem_specific":{"symbols":["Transform"]}}],"references":[{"type":"FIX","url":"https://go-review.googlesource.com/c/text/+/238238"},{"type":"FIX","url":"https://go.googlesource.com/text/+/23ae387dee1f90d29a23c0e87ee0b46038fbed0e"},{"type":"WEB","url":"https://go.dev/issue/39491"},{"type":"WEB","url":"https://groups.google.com/g/golang-announce/c/bXVeAmGOqz0"}]},{"id":"GO-2021-0113","published":"2021-10-06T17:51:21Z","modified":"2021-10-06T17:51:21Z","aliases":["CVE-2021-38561"],"details":"Due to improper index calculation, an incorrectly formatted language tag can cause Parse\nto panic via an out of bounds read. If Parse is used to process untrusted user inputs,\nthis may be used as a vector for a denial of service attack.\n","affected":[{"package":{"name":"golang.org/x/text/language","ecosystem":"Go"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.3.7"}]}],"database_specific":{"url":"https://pkg.go.dev/vuln/GO-2021-0113"},"ecosystem_specific":{"symbols":["Parse","MatchStrings","MustParse","ParseAcceptLanguage"]}}],"references":[{"type":"FIX","url":"https://go-review.googlesource.com/c/text/+/340830"},{"type":"FIX","url":"https://go.googlesource.com/text/+/383b2e75a7a4198c42f8f87833eefb772868a56f"}]}]
|
||||
[{"id":"GO-2020-0015","published":"2021-04-14T20:04:52Z","modified":"2021-06-07T12:00:00Z","aliases":["CVE-2020-14040","GHSA-5rcv-m4m3-hfh7"],"details":"An attacker could provide a single byte to a UTF16 decoder instantiated with\nUseBOM or ExpectBOM to trigger an infinite loop if the String function on\nthe Decoder is called, or the Decoder is passed to transform.String.\nIf used to parse user supplied input, this may be used as a denial of service\nvector.\n","affected":[{"package":{"name":"golang.org/x/text","ecosystem":"Go"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.3.3"}]}],"database_specific":{"url":"https://pkg.go.dev/vuln/GO-2020-0015"},"ecosystem_specific":{"imports":[{"path":"golang.org/x/text/encoding/unicode","symbols":["bomOverride.Transform","utf16Decoder.Transform"]},{"path":"golang.org/x/text/transform","symbols":["Transform"]}]}}],"references":[{"type":"FIX","url":"https://go.dev/cl/238238"},{"type":"FIX","url":"https://go.googlesource.com/text/+/23ae387dee1f90d29a23c0e87ee0b46038fbed0e"},{"type":"WEB","url":"https://go.dev/issue/39491"},{"type":"WEB","url":"https://groups.google.com/g/golang-announce/c/bXVeAmGOqz0"},{"type":"WEB","url":"https://nvd.nist.gov/vuln/detail/CVE-2020-14040"},{"type":"WEB","url":"https://github.com/advisories/GHSA-5rcv-m4m3-hfh7"}]},{"id":"GO-2021-0113","published":"2021-10-06T17:51:21Z","modified":"2021-10-06T17:51:21Z","aliases":["CVE-2021-38561"],"details":"Due to improper index calculation, an incorrectly formatted language tag can cause Parse\nto panic via an out of bounds read. If Parse is used to process untrusted user inputs,\nthis may be used as a vector for a denial of service attack.\n","affected":[{"package":{"name":"golang.org/x/text","ecosystem":"Go"},"ranges":[{"type":"SEMVER","events":[{"introduced":"0"},{"fixed":"0.3.7"}]}],"database_specific":{"url":"https://pkg.go.dev/vuln/GO-2021-0113"},"ecosystem_specific":{"imports":[{"path":"golang.org/x/text/language","symbols":["MatchStrings","MustParse","Parse","ParseAcceptLanguage"]}]}}],"references":[{"type":"FIX","url":"https://go.dev/cl/340830"},{"type":"FIX","url":"https://go.googlesource.com/text/+/383b2e75a7a4198c42f8f87833eefb772868a56f"},{"type":"WEB","url":"https://nvd.nist.gov/vuln/detail/CVE-2021-38561"}]}]
|
||||
|
|
@ -1 +1 @@
|
|||
[{"id":"GO-0000-001","affected":[{"package":{"name":"archive/zip"},"ranges":[{"type":"SEMVER","events":[{"introduced":"1.18.0"}]}],"ecosystem_specific":{"symbols":["OpenReader"]}}]}]
|
||||
[{"id":"STD","affected":[{"package":{"name":"stdlib"},"ranges":[{"type":"SEMVER","events":[{"introduced":"1.18.0"}]}],"ecosystem_specific":{"imports":[{"path":"archive/zip","symbols":["OpenReader"]}]}}]}]
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ import (
|
|||
)
|
||||
|
||||
func main() {
|
||||
_, err := zip.OpenReader("file.zip") // vulnerability GO-0000-001
|
||||
_, err := zip.OpenReader("file.zip") // vulnerability id: STD
|
||||
fmt.Println(err)
|
||||
}
|
||||
`
|
||||
|
|
@ -111,7 +111,7 @@ func main() {
|
|||
env.Await(
|
||||
CompletedWork("govulncheck", 1, true),
|
||||
// TODO(hyangah): once the diagnostics are published, wait for diagnostics.
|
||||
ShownMessage("Found GO-0000-001"),
|
||||
ShownMessage("Found STD"),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,7 +175,10 @@ func toVulns(ci *gvc.CallInfo, unaffectedMods map[string][]*osv.Entry) ([]Vuln,
|
|||
for _, v := range vg {
|
||||
if css := ci.CallStacks[v]; len(css) > 0 {
|
||||
vuln.CallStacks = append(vuln.CallStacks, toCallStack(css[0]))
|
||||
vuln.CallStackSummaries = append(vuln.CallStackSummaries, gvc.SummarizeCallStack(css[0], ci.TopPackages, v.PkgPath))
|
||||
// TODO(hyangah): https://go-review.googlesource.com/c/vuln/+/425183 added position info
|
||||
// in the summary but we don't need the info. Allow SummarizeCallStack to skip it optionally.
|
||||
sum := trimPosPrefix(gvc.SummarizeCallStack(css[0], ci.TopPackages, v.PkgPath))
|
||||
vuln.CallStackSummaries = append(vuln.CallStackSummaries, sum)
|
||||
}
|
||||
}
|
||||
vulns = append(vulns, vuln)
|
||||
|
|
@ -196,3 +199,11 @@ func toVulns(ci *gvc.CallInfo, unaffectedMods map[string][]*osv.Entry) ([]Vuln,
|
|||
}
|
||||
return vulns, nil
|
||||
}
|
||||
|
||||
func trimPosPrefix(summary string) string {
|
||||
_, after, found := strings.Cut(summary, ": ")
|
||||
if !found {
|
||||
return summary
|
||||
}
|
||||
return after
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
|
@ -42,6 +43,13 @@ func TestCmd_Run(t *testing.T) {
|
|||
for _, v := range result {
|
||||
got = append(got, toReport(v))
|
||||
}
|
||||
// drop the workspace root directory path included in the summary.
|
||||
cwd := cfg.Dir
|
||||
for _, g := range got {
|
||||
for i, summary := range g.CallStackSummaries {
|
||||
g.CallStackSummaries[i] = strings.ReplaceAll(summary, cwd, ".")
|
||||
}
|
||||
}
|
||||
|
||||
var want = []report{
|
||||
{
|
||||
|
|
@ -232,9 +240,13 @@ var testClient1 = &mockClient{
|
|||
},
|
||||
},
|
||||
Affected: []osv.Affected{{
|
||||
Package: osv.Package{Name: "golang.org/amod/avuln"},
|
||||
Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.0"}, {Fixed: "1.0.4"}, {Introduced: "1.1.2"}}}},
|
||||
EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"VulnData.Vuln1", "VulnData.Vuln2"}},
|
||||
Package: osv.Package{Name: "golang.org/amod"},
|
||||
Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.0"}, {Fixed: "1.0.4"}, {Introduced: "1.1.2"}}}},
|
||||
EcosystemSpecific: osv.EcosystemSpecific{
|
||||
Imports: []osv.EcosystemSpecificImport{{
|
||||
Path: "golang.org/amod/avuln",
|
||||
Symbols: []string{"VulnData.Vuln1", "VulnData.Vuln2"}}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
|
|
@ -247,9 +259,13 @@ var testClient1 = &mockClient{
|
|||
},
|
||||
},
|
||||
Affected: []osv.Affected{{
|
||||
Package: osv.Package{Name: "golang.org/amod/avuln"},
|
||||
Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.0"}, {Fixed: "1.0.4"}, {Introduced: "1.1.2"}}}},
|
||||
EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"nonExisting"}},
|
||||
Package: osv.Package{Name: "golang.org/amod"},
|
||||
Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.0"}, {Fixed: "1.0.4"}, {Introduced: "1.1.2"}}}},
|
||||
EcosystemSpecific: osv.EcosystemSpecific{
|
||||
Imports: []osv.EcosystemSpecificImport{{
|
||||
Path: "golang.org/amod/avuln",
|
||||
Symbols: []string{"nonExisting"}}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
|
|
@ -257,9 +273,13 @@ var testClient1 = &mockClient{
|
|||
{
|
||||
ID: "GO-2022-02",
|
||||
Affected: []osv.Affected{{
|
||||
Package: osv.Package{Name: "golang.org/bmod/bvuln"},
|
||||
Ranges: osv.Affects{{Type: osv.TypeSemver}},
|
||||
EcosystemSpecific: osv.EcosystemSpecific{Symbols: []string{"Vuln"}},
|
||||
Package: osv.Package{Name: "golang.org/bmod"},
|
||||
Ranges: osv.Affects{{Type: osv.TypeSemver}},
|
||||
EcosystemSpecific: osv.EcosystemSpecific{
|
||||
Imports: []osv.EcosystemSpecificImport{{
|
||||
Path: "golang.org/bmod/bvuln",
|
||||
Symbols: []string{"Vuln"}}},
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue