vulncheck: include proper filtering of vulnerabilities
Cherry-picked: https://go-review.googlesource.com/c/exp/+/370457
Change-Id: Icb61985cb7c22cf6d2b99a5eea05cb8ba31b8f45
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/395048
Trust: Julie Qiu <julie@golang.org>
Run-TryBot: Julie Qiu <julie@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/vulncheck/binary.go b/vulncheck/binary.go
index bd2f7d7..17b5d16 100644
--- a/vulncheck/binary.go
+++ b/vulncheck/binary.go
@@ -7,6 +7,7 @@
import (
"context"
"io"
+ "runtime"
"golang.org/x/tools/go/packages"
"golang.org/x/vuln/vulncheck/internal/binscan"
@@ -23,6 +24,7 @@
if err != nil {
return nil, err
}
+ modVulns = modVulns.Filter(lookupEnv("GOOS", runtime.GOOS), lookupEnv("GOARCH", runtime.GOARCH))
result := &Result{}
for pkg, symbols := range packageSymbols {
diff --git a/vulncheck/source.go b/vulncheck/source.go
index fa12790..cd20d50 100644
--- a/vulncheck/source.go
+++ b/vulncheck/source.go
@@ -6,6 +6,7 @@
import (
"context"
+ "runtime"
"golang.org/x/tools/go/callgraph"
"golang.org/x/tools/go/ssa"
@@ -24,6 +25,7 @@
if err != nil {
return nil, err
}
+ modVulns = modVulns.Filter(lookupEnv("GOOS", runtime.GOOS), lookupEnv("GOARCH", runtime.GOARCH))
result := &Result{
Imports: &ImportGraph{Packages: make(map[int]*PkgNode)},
diff --git a/vulncheck/source_test.go b/vulncheck/source_test.go
index 7398392..c97adf0 100644
--- a/vulncheck/source_test.go
+++ b/vulncheck/source_test.go
@@ -6,11 +6,13 @@
import (
"context"
+ "os"
"path"
"reflect"
"testing"
"golang.org/x/tools/go/packages/packagestest"
+ "golang.org/x/vuln/osv"
)
// TestImportsOnly checks for module and imports graph correctness
@@ -379,3 +381,89 @@
t.Errorf("want %v call graph; got %v", wantCalls, callStrMap)
}
}
+
+func TestFiltering(t *testing.T) {
+ e := packagestest.Export(t, packagestest.Modules, []packagestest.Module{
+ {
+ Name: "golang.org/entry",
+ Files: map[string]interface{}{
+ "x/x.go": `
+ package x
+
+ import "golang.org/vmod/vuln"
+
+ func X() {
+ vuln.V()
+ }`,
+ },
+ },
+ {
+ Name: "golang.org/vmod@v1.2.3",
+ Files: map[string]interface{}{"vuln/vuln.go": `
+ package vuln
+
+ func V() {}
+ `},
+ },
+ })
+ defer e.Cleanup()
+
+ client := &mockClient{
+ ret: map[string][]*osv.Entry{
+ "golang.org/vmod": []*osv.Entry{
+ {
+ ID: "V",
+ Affected: []osv.Affected{{
+ Package: osv.Package{Name: "golang.org/vmod/vuln"},
+ Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.2.0"}}}},
+ EcosystemSpecific: osv.EcosystemSpecific{
+ Symbols: []string{"V"},
+ GOOS: []string{"linux"},
+ GOARCH: []string{"amd64"},
+ },
+ }},
+ },
+ },
+ },
+ }
+
+ // Make sure local vulns can be loaded.
+ fetchingInTesting = true
+ // Load x as entry package.
+ pkgs, err := loadPackages(e, path.Join(e.Temp(), "entry/x"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(pkgs) != 1 {
+ t.Fatal("failed to load x test package")
+ }
+
+ cfg := &Config{
+ Client: client,
+ ImportsOnly: true,
+ }
+
+ os.Setenv("GOOS", "linux")
+ os.Setenv("GOARCH", "amd64")
+
+ result, err := Source(context.Background(), Convert(pkgs), cfg)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if len(result.Vulns) != 1 {
+ t.Errorf("want 1 Vuln, got %d", len(result.Vulns))
+ }
+
+ os.Setenv("GOOS", "freebsd")
+ os.Setenv("GOARCH", "arm64")
+
+ result, err = Source(context.Background(), Convert(pkgs), cfg)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if len(result.Vulns) != 0 {
+ t.Errorf("want 0 Vulns, got %d", len(result.Vulns))
+ }
+}
diff --git a/vulncheck/utils.go b/vulncheck/utils.go
index d120f56..70d37f5 100644
--- a/vulncheck/utils.go
+++ b/vulncheck/utils.go
@@ -8,6 +8,7 @@
"bytes"
"go/token"
"go/types"
+ "os"
"strings"
"golang.org/x/tools/go/callgraph"
@@ -214,3 +215,10 @@
types.WriteType(buf, v.Type(), nil)
return buf.String()
}
+
+func lookupEnv(key, defaultValue string) string {
+ if v, ok := os.LookupEnv(key); ok {
+ return v
+ }
+ return defaultValue
+}