Skip to content

Commit

Permalink
Merge pull request google#70 from zpavlinovic:govulncheck
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 640545958
  • Loading branch information
copybara-github committed Jun 5, 2024
2 parents f5cca0e + ac470f4 commit 58c1eff
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 12 deletions.
29 changes: 22 additions & 7 deletions detector/govulncheck/binary/detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ import (
"path"
"strings"

"golang.org/x/vuln/scan"
"github.com/google/osv-scalibr/detector"
"github.com/google/osv-scalibr/extractor/filesystem/language/golang/gobinary"
"github.com/google/osv-scalibr/inventoryindex"
"github.com/google/osv-scalibr/log"
"github.com/google/osv-scalibr/purl"

"golang.org/x/vuln/scan"
)

const (
Expand Down Expand Up @@ -110,29 +111,43 @@ func (d Detector) runGovulncheck(ctx context.Context, binaryPath, scanRoot strin

func parseVulnsFromOutput(out *bytes.Buffer, binaryPath string) ([]*detector.Finding, error) {
result := []*detector.Finding{}
allOSVs := make(map[string]*osvEntry)
detectedOSVs := make(map[string]struct{}) // osvs detected at the symbol level
dec := json.NewDecoder(bytes.NewReader(out.Bytes()))
for dec.More() {
msg := govulncheckMessage{}
if err := dec.Decode(&msg); err != nil {
return nil, err
}
if msg.OSV == nil {
continue
if msg.OSV != nil {
allOSVs[msg.OSV.ID] = msg.OSV
}
if msg.Finding != nil {
trace := msg.Finding.Trace
if len(trace) != 0 && trace[0].Function != "" {
// symbol findings
detectedOSVs[msg.Finding.OSV] = struct{}{}
}
}
}

// create scalibr findings for detected govulncheck findings
for osvID := range detectedOSVs {
osv := allOSVs[osvID]
recommendation := "Remove the binary or upgrade its affected dependencies to non-vulnerable versions"
extra := ""
affected, err := json.Marshal(msg.OSV.Affected)
affected, err := json.Marshal(osv.Affected)
if err == nil {
extra = fmt.Sprintf("Vulnerable dependencies for binary %s: %s", binaryPath, string(affected[:]))
} else {
log.Warnf("error serializing affected software: %w", err)
}
result = append(result, &detector.Finding{
Adv: &detector.Advisory{
ID: getAdvisoryID(msg.OSV),
ID: getAdvisoryID(osv),
Type: detector.TypeVulnerability,
Title: msg.OSV.Summary,
Description: msg.OSV.Details,
Title: osv.Summary,
Description: osv.Details,
Recommendation: recommendation,
Sev: &detector.Severity{Severity: detector.SeverityMedium},
},
Expand Down
8 changes: 6 additions & 2 deletions detector/govulncheck/binary/detector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,12 @@ func TestScan(t *testing.T) {
if err != nil {
t.Fatalf("detector.Scan(%v): %v", ix, err)
}
if len(findings) == 0 {
t.Fatalf("detector.Scan(%v): expected findings, got none: %v", ix, findings)
// There are two vulns in the test vulndb defined for two
// module dependencies of the test binary. Both dependencies
// are used at a vulnerable version. However, for only one
// there is a vulnerable symbol present in the binary.
if len(findings) != 1 {
t.Fatalf("detector.Scan(%v): expected 1 finding, got: %v", ix, findings)
}
got := findings[0]
wantTitle := "Excessive memory growth in net/http and golang.org/x/net/http2"
Expand Down
16 changes: 15 additions & 1 deletion detector/govulncheck/binary/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,19 @@ package binary

// govulncheckMessage contains the relevant parts of the json output of govulncheck.
type govulncheckMessage struct {
OSV *osvEntry `json:"osv,omitempty"`
OSV *osvEntry `json:"osv,omitempty"`
Finding *govulncheckFinding `json:"finding,omitempty"`
}

// govulncheckFinding is a trimmed down version of govulncheck finding.
type govulncheckFinding struct {
OSV string `json:"osv,omitempty"`
Trace []*govulncheckFrame `json:"trace,omitempty"`
}

type govulncheckFrame struct {
// Function is the detected symbol.
Function string `json:"function,omitempty"`
}

// osvEntry represents a vulnerability in the Go OSV format, documented
Expand All @@ -37,6 +49,7 @@ type osvEntry struct {
// affected by the vulnerability.
Affected []affected
}

type affected struct {
// The affected Go module. Required.
// Note that this field is called "package" in the OSV specification.
Expand All @@ -46,6 +59,7 @@ type affected struct {
// Details on the affected packages and symbols within the module.
EcosystemSpecific ecosystemSpecific `json:"ecosystem_specific"`
}

type module struct {
// The Go module path.
Path string `json:"name"`
Expand Down
80 changes: 80 additions & 0 deletions detector/govulncheck/binary/testdata/vulndb/ID/GO-2024-2887.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
{
"schema_version": "1.3.1",
"id": "GO-2024-2887",
"modified": "0001-01-01T00:00:00Z",
"published": "0001-01-01T00:00:00Z",
"aliases": [
"CVE-2024-24790"
],
"summary": "Unexpected behavior from Is methods for IPv4-mapped IPv6 addresses in net/netip",
"details": "The various Is methods (IsPrivate, IsLoopback, etc) did not work as expected for IPv4-mapped IPv6 addresses, returning false for addresses which would return true in their traditional IPv4 forms.",
"affected": [
{
"package": {
"name": "stdlib",
"ecosystem": "Go"
},
"ranges": [
{
"type": "SEMVER",
"events": [
{
"introduced": "0"
},
{
"fixed": "1.21.11"
},
{
"introduced": "1.22.0-0"
},
{
"fixed": "1.22.4"
}
]
}
],
"ecosystem_specific": {
"imports": [
{
"path": "net/netip",
"symbols": [
"Addr.IsGlobalUnicast",
"Addr.IsInterfaceLocalMulticast",
"Addr.IsLinkLocalMulticast",
"Addr.IsLoopback",
"Addr.IsMulticast",
"Addr.IsPrivate"
]
}
]
}
}
],
"references": [
{
"type": "FIX",
"url": "https://go.dev/cl/590316"
},
{
"type": "REPORT",
"url": "https://go.dev/issue/67680"
},
{
"type": "WEB",
"url": "https://groups.google.com/g/golang-announce/c/XbxouI9gY7k/m/TuoGEhxIEwAJ"
}
],
"credits": [
{
"name": "Enze Wang of Alioth (@zer0yu)"
},
{
"name": "Jianjun Chen of Zhongguancun Lab (@chenjj)"
}
],
"database_specific": {
"url": "https://pkg.go.dev/vuln/GO-2024-2887",
"review_status": "REVIEWED"
}
}

Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"path":"golang.org/x/net","vulns":[{"id":"GO-2022-1144","modified":"2023-06-12T18:45:41Z","fixed":"0.4.0"}]},{"path":"stdlib","vulns":[{"id":"GO-2022-1144","modified":"2023-06-12T18:45:41Z","fixed":"1.19.4"}]}]
[{"path":"golang.org/x/net","vulns":[{"id":"GO-2022-1144","modified":"2023-06-12T18:45:41Z","fixed":"0.4.0"}]},{"path":"stdlib","vulns":[{"id":"GO-2022-1144","modified":"2023-06-12T18:45:41Z","fixed":"1.19.4"},{"id":"GO-2024-2887","modified":"2024-06-04T17:58:12Z","fixed":"1.22.4"}]}]
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"id":"GO-2022-1144","modified":"2023-06-12T18:45:41Z","aliases":["CVE-2022-41717","GHSA-xrjj-mj9h-534m"]}]
[{"id":"GO-2022-1144","modified":"2023-06-12T18:45:41Z","aliases":["CVE-2022-41717","GHSA-xrjj-mj9h-534m"]},{"id":"GO-2024-2887","modified":"2024-06-04T17:58:12Z","aliases":["CVE-2024-24790"]}]

0 comments on commit 58c1eff

Please sign in to comment.