Skip to content

Commit

Permalink
cmd/vulnreport: resolve package references with "go mod tidy".
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
neild committed Mar 7, 2023
1 parent 56fb761 commit dc03e02
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 5 deletions.
29 changes: 26 additions & 3 deletions cmd/vulnreport/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
package main

import (
"bytes"
"context"
"errors"
"flag"
Expand Down Expand Up @@ -705,15 +706,37 @@ func findExportedSymbols(m *report.Module, p *report.Package, c *reportClient) (
return nil, err
}
defer cleanup()

// This procedure was developed through trial and error finding a way
// to load symbols for GO-2023-1549, which has a dependency tree that
// includes go.mod files that reference v0.0.0 versions which do not exist.
//
// Create an empty go.mod.
if err := run("go", "mod", "init", "go.dev/_"); err != nil {
return nil, err
}
if !m.IsStdLib() {
pkgPathAndVersion := p.Package + "@" + m.VulnerableAt.V()
if err := run("go", "get", pkgPathAndVersion); err != nil {
// Require the module we're interested in at the vulnerable_at version.
if err := run("go", "mod", "edit", "-require", m.Module+"@"+m.VulnerableAt.V()); err != nil {
return nil, err
}
for _, req := range m.VulnerableAtRequires {
if err := run("go", "mod", "edit", "-require", req); err != nil {
return nil, err
}
}
// Create a package that imports the package we're interested in.
var content bytes.Buffer
fmt.Fprintf(&content, "package p\n")
fmt.Fprintf(&content, "import _ %q\n", p.Package)
for _, req := range m.VulnerableAtRequires {
pkg, _, _ := strings.Cut(req, "@")
fmt.Fprintf(&content, "import _ %q", pkg)
}
os.WriteFile("p.go", content.Bytes(), 0666)
// Run go mod tidy.
if err := run("go", "mod", "tidy"); err != nil {
return nil, err
}

pkgs, err := loadPackage(&packages.Config{}, p.Package)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions data/osv/GO-2021-0072.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@
{
"path": "github.com/docker/distribution/registry/handlers",
"symbols": [
"NewApp",
"blobUploadHandler.PatchBlobData",
"blobUploadHandler.PutBlobUploadComplete",
"catalogHandler.GetCatalog",
"copyFullPayload",
"imageManifestHandler.GetImageManifest",
"imageManifestHandler.PutImageManifest"
Expand Down
4 changes: 4 additions & 0 deletions data/reports/GO-2021-0072.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ modules:
versions:
- fixed: 2.7.0-rc.0+incompatible
vulnerable_at: 2.6.2+incompatible
vulnerable_at_requires:
- github.com/Sirupsen/[email protected]
packages:
- package: github.com/docker/distribution/registry/handlers
symbols:
- copyFullPayload
derived_symbols:
- NewApp
- blobUploadHandler.PatchBlobData
- blobUploadHandler.PutBlobUploadComplete
- catalogHandler.GetCatalog
- imageManifestHandler.GetImageManifest
- imageManifestHandler.PutImageManifest
- package: github.com/docker/distribution/registry/storage
Expand Down
7 changes: 5 additions & 2 deletions internal/report/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,11 @@ type Module struct {
// In general, we want to use the most recent vulnerable version of
// the package. Determining this programmatically is difficult, especially
// for packages without tagged versions, so we specify it manually here.
VulnerableAt Version `yaml:"vulnerable_at,omitempty"`
Packages []*Package `yaml:",omitempty"`
VulnerableAt Version `yaml:"vulnerable_at,omitempty"`
// Additional list of module@version to require when performing static analysis.
// It is rare that we need to specify this.
VulnerableAtRequires []string `yaml:"vulnerable_at_requires,omitempty"`
Packages []*Package `yaml:",omitempty"`
}

type Package struct {
Expand Down

0 comments on commit dc03e02

Please sign in to comment.