vuln/vulncheck: include stdlib in module list
Include the standard library as one of the modules of the binary or
source, so govulncheck can display the version where a vuln was found.
Updates #53948.
Change-Id: Ib0ab43517fc00f6edaa75675089a031bb37b9351
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/418794
Run-TryBot: Jonathan Amsterdam <jba@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Julie Qiu <julieqiu@google.com>
diff --git a/cmd/govulncheck/main_command_118_test.go b/cmd/govulncheck/main_command_118_test.go
index 2e31a82..e45c797 100644
--- a/cmd/govulncheck/main_command_118_test.go
+++ b/cmd/govulncheck/main_command_118_test.go
@@ -59,6 +59,7 @@
cmd.Env = append(os.Environ(), "GOVULNDB=file://"+testDir+"/testdata/vulndb", "GOVERSION=go1.18")
out, err := cmd.CombinedOutput()
out = filterGoFilePaths(out)
+ out = filterStdlibVersions(out)
return out, err
}
@@ -78,9 +79,12 @@
ts.Run(t, *update)
}
-var goFileRegexp = regexp.MustCompile(`[^\s"]*\.go[\s":]`)
+var (
+ goFileRegexp = regexp.MustCompile(`[^\s"]*\.go[\s":]`)
+ stdlibVersionRegexp = regexp.MustCompile(`("Path": "stdlib",\s*"Version": ")v[^\s]+"`)
+)
-// filterGoFilePaths modifies paths to Go files by replacing their directory with "...".
+// filterGoFilePaths modifies paths to Go files by replacing their directory with "...".
// For example,/a/b/c.go becomes .../c.go .
// This makes it possible to compare govulncheck output across systems, because
// Go filenames include setup-specific paths.
@@ -90,3 +94,11 @@
return []byte(fmt.Sprintf(`.../%s%c`, filepath.Base(s[1:len(s)-1]), s[len(s)-1]))
})
}
+
+// filterStdlibVersions removes Go standard library versions from JSON output,
+// since they depend on the system running the test. Some have different
+// versions than others, and on some we are unable to extract a version from
+// the binary so the version is empty.
+func filterStdlibVersions(data []byte) []byte {
+ return stdlibVersionRegexp.ReplaceAll(data, []byte(`${1}"`))
+}
diff --git a/cmd/govulncheck/testdata/json-binary.ct b/cmd/govulncheck/testdata/json-binary.ct
index 30e6e4b..27ea33b 100644
--- a/cmd/govulncheck/testdata/json-binary.ct
+++ b/cmd/govulncheck/testdata/json-binary.ct
@@ -10,6 +10,12 @@
"Version": "v0.3.7",
"Dir": "",
"Replace": null
+ },
+ {
+ "Path": "stdlib",
+ "Version": "",
+ "Dir": "",
+ "Replace": null
}
]
}
@@ -86,6 +92,12 @@
"Version": "v0.3.0",
"Dir": "",
"Replace": null
+ },
+ {
+ "Path": "stdlib",
+ "Version": "",
+ "Dir": "",
+ "Replace": null
}
]
}
diff --git a/cmd/govulncheck/testdata/json.ct b/cmd/govulncheck/testdata/json.ct
index f93fd2c..57defcf 100644
--- a/cmd/govulncheck/testdata/json.ct
+++ b/cmd/govulncheck/testdata/json.ct
@@ -30,6 +30,12 @@
"Version": "v0.3.7",
"Dir": "",
"Replace": null
+ },
+ {
+ "Path": "stdlib",
+ "Version": "",
+ "Dir": "",
+ "Replace": null
}
]
}
@@ -202,6 +208,12 @@
"Version": "v0.3.0",
"Dir": "",
"Replace": null
+ },
+ {
+ "Path": "stdlib",
+ "Version": "",
+ "Dir": "",
+ "Replace": null
}
]
}
diff --git a/cmd/govulncheck/testdata/stdlib.ct b/cmd/govulncheck/testdata/stdlib.ct
index 913e73f..743a4c6 100644
--- a/cmd/govulncheck/testdata/stdlib.ct
+++ b/cmd/govulncheck/testdata/stdlib.ct
@@ -13,5 +13,5 @@
Call stacks in your code:
golang.org/stdvuln.main calls archive/zip.OpenReader
-Found in: archive/zip
+Found in: archive/zip@v1.18.0
More info: https://pkg.go.dev/vuln/STD
diff --git a/vulncheck/binary.go b/vulncheck/binary.go
index f0eac7f..034ba4e 100644
--- a/vulncheck/binary.go
+++ b/vulncheck/binary.go
@@ -32,8 +32,7 @@
// set the stdlib version for detection of vulns in the standard library
// TODO(#53740): what if Go version is not in semver format?
stdlibModule.Version = goTagToSemver(goVersion)
- // Add "stdlib" module. Even if stdlib is not used, which is unlikely, it
- // won't appear in vulncheck.Modules nor other results.
+ // Add "stdlib" module.
cmods = append(cmods, stdlibModule)
modVulns, err := fetchVulnerabilities(ctx, cfg.Client, cmods)
diff --git a/vulncheck/binary_test.go b/vulncheck/binary_test.go
index c0316df..0d91820 100644
--- a/vulncheck/binary_test.go
+++ b/vulncheck/binary_test.go
@@ -172,6 +172,7 @@
{Path: "golang.org/amod", Version: "v1.1.3"},
{Path: "golang.org/bmod", Version: "v0.5.0"},
{Path: "golang.org/cmod", Version: "v1.1.3"},
+ stdlibModule,
}
gotMods := res.Modules
sort.Slice(gotMods, func(i, j int) bool { return gotMods[i].Path < gotMods[j].Path })
diff --git a/vulncheck/source.go b/vulncheck/source.go
index 9015c9e..c5d9198 100644
--- a/vulncheck/source.go
+++ b/vulncheck/source.go
@@ -93,13 +93,7 @@
}
// Sort for determinism.
sort.Slice(mods, func(i, j int) bool { return mods[i].Path < mods[j].Path })
- for _, m := range mods {
- // stdlib is not a module per se, so we don't
- // save it as module comprising user code.
- if m != stdlibModule {
- r.Modules = append(r.Modules, m)
- }
- }
+ r.Modules = append(r.Modules, mods...)
}
// pkgID is an id counter for nodes of Imports graph.
diff --git a/vulncheck/source_test.go b/vulncheck/source_test.go
index 9229ff7..10f6f73 100644
--- a/vulncheck/source_test.go
+++ b/vulncheck/source_test.go
@@ -175,6 +175,7 @@
{Path: "golang.org/entry"},
{Path: "golang.org/wmod", Version: "v0.0.0"},
{Path: "golang.org/zmod", Version: "v0.0.0"},
+ {Path: "stdlib", Version: "v1.18.0"},
}
gotMods := result.Modules
sort.Slice(gotMods, func(i, j int) bool { return gotMods[i].Path < gotMods[j].Path })
@@ -307,6 +308,7 @@
{Path: "golang.org/entry"},
{Path: "golang.org/imod1", Version: "v0.0.0"},
{Path: "golang.org/imod2", Version: "v0.0.0"},
+ stdlibModule,
}
gotMods := result.Modules
sort.Slice(gotMods, func(i, j int) bool { return gotMods[i].Path < gotMods[j].Path })