Skip to content

Commit

Permalink
internal/openvex: add handler
Browse files Browse the repository at this point in the history
updates golang/go#62486

Change-Id: Ib1cd9281cf33fb84a8a3c0f3e7523cfb8d93e677
Reviewed-on: https://go-review.googlesource.com/c/vuln/+/575858
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
  • Loading branch information
Maceo Thompson committed Jun 3, 2024
1 parent b6af818 commit ad5a6f8
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 7 deletions.
4 changes: 4 additions & 0 deletions cmd/govulncheck/testdata/common/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
{
"pattern": "\"go_version\": \"go[^\\s\"]*\"",
"replace": "\"go_version\": \"go1.18\""
},
{
"pattern": "\"timestamp\": (.*),",
"replace": "\"timestamp\": \"2024-01-01T00:00:00\","
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#####
# Test basic binary scanning with vex output
$ govulncheck -format openvex -mode binary ${common_vuln_binary}
{
"@context": "https://openvex.dev/ns/v0.2.0",
"@id": "govulncheckVEX",
"author": "Unknown Author",
"timestamp": "2024-01-01T00:00:00",
"version": 1,
"tooling": "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#####
# Test vex json output
$ govulncheck -C ${moddir}/vuln -format openvex ./...
{
"@context": "https://openvex.dev/ns/v0.2.0",
"@id": "govulncheckVEX",
"author": "Unknown Author",
"timestamp": "2024-01-01T00:00:00",
"version": 1,
"tooling": "https://pkg.go.dev/golang.org/x/vuln/cmd/govulncheck"
}
98 changes: 98 additions & 0 deletions internal/openvex/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package openvex

import (
"encoding/json"
"io"
"time"

"golang.org/x/vuln/internal/govulncheck"
"golang.org/x/vuln/internal/osv"
)

type findingLevel int

const (
invalid findingLevel = iota
required
imported
called
)

type handler struct {
w io.Writer
cfg *govulncheck.Config
osvs map[string]*osv.Entry
levels map[string]findingLevel
}

func NewHandler(w io.Writer) *handler {
return &handler{
w: w,
osvs: make(map[string]*osv.Entry),
levels: make(map[string]findingLevel),
}
}

func (h *handler) Config(cfg *govulncheck.Config) error {
h.cfg = cfg
return nil
}

func (h *handler) Progress(progress *govulncheck.Progress) error {
return nil
}

func (h *handler) OSV(e *osv.Entry) error {
h.osvs[e.ID] = e
return nil
}

// foundAtLevel returns the level at which a specific finding is present in the
// scanned product.
func foundAtLevel(f *govulncheck.Finding) findingLevel {
frame := f.Trace[0]
if frame.Function != "" {
return called
}
if frame.Package != "" {
return imported
}
return required
}

func (h *handler) Finding(f *govulncheck.Finding) error {
fLevel := foundAtLevel(f)
if fLevel > h.levels[f.OSV] {
h.levels[f.OSV] = fLevel
}
return nil
}

// Flush is used to print the vex json to w.
// This is needed as vex is not streamed.
func (h *handler) Flush() error {
doc := toVex()
out, err := json.MarshalIndent(doc, "", " ")
if err != nil {
return err
}
_, err = h.w.Write(out)
return err
}

func toVex() Document {
doc := Document{
ID: "govulncheckVEX", // TODO: create hash from document for ID
Context: ContextURI,
Author: DefaultAuthor,
Timestamp: time.Now().UTC(),
Version: 1,
Tooling: Tooling,
//TODO: Add statements
}
return doc
}
70 changes: 70 additions & 0 deletions internal/openvex/handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package openvex

import (
"testing"

"golang.org/x/vuln/internal/govulncheck"
)

func TestFinding(t *testing.T) {
const id1 = "ID1"
tests := []struct {
name string
id string
findings []*govulncheck.Finding
want findingLevel
}{
{
name: "multiple",
id: id1,
findings: []*govulncheck.Finding{
{
OSV: id1,
Trace: []*govulncheck.Frame{
{
Module: "mod",
Package: "pkg",
},
},
},
{
OSV: id1,
Trace: []*govulncheck.Frame{
{
Module: "mod",
Package: "pkg",
Function: "func",
},
},
},
{
OSV: id1,
Trace: []*govulncheck.Frame{
{
Module: "mod",
},
},
},
},
want: called,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := NewHandler(nil)
for _, f := range tt.findings {
if err := h.Finding(f); err != nil {
t.Errorf("handler.Finding() error = %v", err)
}
}
got := h.levels[tt.id]
if got != tt.want {
t.Errorf("want %v; got %v", tt.want, got)
}
})
}
}
16 changes: 9 additions & 7 deletions internal/scan/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,16 +236,18 @@ func (v ShowFlag) Update(h *TextHandler) {
type FormatFlag string

const (
formatUnset = ""
formatJSON = "json"
formatText = "text"
formatSarif = "sarif"
formatUnset = ""
formatJSON = "json"
formatText = "text"
formatSarif = "sarif"
formatOpenVEX = "openvex"
)

var supportedFormats = map[string]bool{
formatJSON: true,
formatText: true,
formatSarif: true,
formatJSON: true,
formatText: true,
formatSarif: true,
formatOpenVEX: true,
}

func (f *FormatFlag) Get() interface{} { return *f }
Expand Down
3 changes: 3 additions & 0 deletions internal/scan/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"golang.org/x/telemetry/counter"
"golang.org/x/vuln/internal/client"
"golang.org/x/vuln/internal/govulncheck"
"golang.org/x/vuln/internal/openvex"
"golang.org/x/vuln/internal/sarif"
)

Expand All @@ -42,6 +43,8 @@ func RunGovulncheck(ctx context.Context, env []string, r io.Reader, stdout io.Wr
handler = govulncheck.NewJSONHandler(stdout)
case formatSarif:
handler = sarif.NewHandler(stdout)
case formatOpenVEX:
handler = openvex.NewHandler(stdout)
default:
th := NewTextHandler(stdout)
cfg.show.Update(th)
Expand Down

0 comments on commit ad5a6f8

Please sign in to comment.