Skip to content

Commit dc03e02

Browse files
committed
cmd/vulnreport: resolve package references with "go mod tidy".
When resolving vulnerable symbols, we create a temporary module which depends on the vulnerable package. Construct this temporary module's go.mod file with "go mod tidy" rather than "go get -u", which seems to do a better of job of resolving the dependencies for packages in the Kubernetes ecosystem. Allows vulnreport fix to work on GO-2023-1549. Change-Id: I50a71807411a3bab896b5982186d3e57fa1d941b Reviewed-on: https://go-review.googlesource.com/c/vulndb/+/470376 TryBot-Result: Gopher Robot <[email protected]> Run-TryBot: Damien Neil <[email protected]> Reviewed-by: Tatiana Bradley <[email protected]>
1 parent 56fb761 commit dc03e02

File tree

4 files changed

+37
-5
lines changed

4 files changed

+37
-5
lines changed

cmd/vulnreport/main.go

+26-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package main
88

99
import (
10+
"bytes"
1011
"context"
1112
"errors"
1213
"flag"
@@ -705,15 +706,37 @@ func findExportedSymbols(m *report.Module, p *report.Package, c *reportClient) (
705706
return nil, err
706707
}
707708
defer cleanup()
709+
710+
// This procedure was developed through trial and error finding a way
711+
// to load symbols for GO-2023-1549, which has a dependency tree that
712+
// includes go.mod files that reference v0.0.0 versions which do not exist.
713+
//
714+
// Create an empty go.mod.
708715
if err := run("go", "mod", "init", "go.dev/_"); err != nil {
709716
return nil, err
710717
}
711-
if !m.IsStdLib() {
712-
pkgPathAndVersion := p.Package + "@" + m.VulnerableAt.V()
713-
if err := run("go", "get", pkgPathAndVersion); err != nil {
718+
// Require the module we're interested in at the vulnerable_at version.
719+
if err := run("go", "mod", "edit", "-require", m.Module+"@"+m.VulnerableAt.V()); err != nil {
720+
return nil, err
721+
}
722+
for _, req := range m.VulnerableAtRequires {
723+
if err := run("go", "mod", "edit", "-require", req); err != nil {
714724
return nil, err
715725
}
716726
}
727+
// Create a package that imports the package we're interested in.
728+
var content bytes.Buffer
729+
fmt.Fprintf(&content, "package p\n")
730+
fmt.Fprintf(&content, "import _ %q\n", p.Package)
731+
for _, req := range m.VulnerableAtRequires {
732+
pkg, _, _ := strings.Cut(req, "@")
733+
fmt.Fprintf(&content, "import _ %q", pkg)
734+
}
735+
os.WriteFile("p.go", content.Bytes(), 0666)
736+
// Run go mod tidy.
737+
if err := run("go", "mod", "tidy"); err != nil {
738+
return nil, err
739+
}
717740

718741
pkgs, err := loadPackage(&packages.Config{}, p.Package)
719742
if err != nil {

data/osv/GO-2021-0072.json

+2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@
3434
{
3535
"path": "github.com/docker/distribution/registry/handlers",
3636
"symbols": [
37+
"NewApp",
3738
"blobUploadHandler.PatchBlobData",
3839
"blobUploadHandler.PutBlobUploadComplete",
40+
"catalogHandler.GetCatalog",
3941
"copyFullPayload",
4042
"imageManifestHandler.GetImageManifest",
4143
"imageManifestHandler.PutImageManifest"

data/reports/GO-2021-0072.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@ modules:
33
versions:
44
- fixed: 2.7.0-rc.0+incompatible
55
vulnerable_at: 2.6.2+incompatible
6+
vulnerable_at_requires:
7+
- github.com/Sirupsen/[email protected]
68
packages:
79
- package: github.com/docker/distribution/registry/handlers
810
symbols:
911
- copyFullPayload
1012
derived_symbols:
13+
- NewApp
1114
- blobUploadHandler.PatchBlobData
1215
- blobUploadHandler.PutBlobUploadComplete
16+
- catalogHandler.GetCatalog
1317
- imageManifestHandler.GetImageManifest
1418
- imageManifestHandler.PutImageManifest
1519
- package: github.com/docker/distribution/registry/storage

internal/report/report.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,11 @@ type Module struct {
5959
// In general, we want to use the most recent vulnerable version of
6060
// the package. Determining this programmatically is difficult, especially
6161
// for packages without tagged versions, so we specify it manually here.
62-
VulnerableAt Version `yaml:"vulnerable_at,omitempty"`
63-
Packages []*Package `yaml:",omitempty"`
62+
VulnerableAt Version `yaml:"vulnerable_at,omitempty"`
63+
// Additional list of module@version to require when performing static analysis.
64+
// It is rare that we need to specify this.
65+
VulnerableAtRequires []string `yaml:"vulnerable_at_requires,omitempty"`
66+
Packages []*Package `yaml:",omitempty"`
6467
}
6568

6669
type Package struct {

0 commit comments

Comments
 (0)