Skip to content

Commit

Permalink
internal/vuln,static/frontend: display custom versions on vuln pages
Browse files Browse the repository at this point in the history
On vulnerability entry pages, display "custom versions" (and a note
explainining them) if there are any "custom_ranges" published in the OSV.

(Once this is live, we will remove the disclaimer from the OSV details
since this will be redundant.)

Change-Id: I20c3b08ecb3f36ce0334553eef0dacd0fe57480b
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/597616
kokoro-CI: kokoro <[email protected]>
Reviewed-by: Damien Neil <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
  • Loading branch information
tatianab committed Jul 15, 2024
1 parent bdc5daf commit 763ccd4
Show file tree
Hide file tree
Showing 20 changed files with 205 additions and 76 deletions.
9 changes: 9 additions & 0 deletions internal/osv/affected.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,12 @@ func (e *Entry) AffectsStandardLibrary() bool {
func (e *Entry) IsUnreviewed() bool {
return e.DatabaseSpecific.ReviewStatus == ReviewStatusUnreviewed
}

func (e *Entry) HasCustomVersions() bool {
for _, a := range e.Affected {
if len(a.EcosystemSpecific.CustomRanges) != 0 {
return true
}
}
return false
}
6 changes: 6 additions & 0 deletions internal/osv/osv.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ type Package struct {
type EcosystemSpecific struct {
// Packages is the list of affected packages within the module.
Packages []Package `json:"imports,omitempty"`
// CustomRanges are the version ranges affected by the vulnerability
// which are not compatible with Go module version numbering
// (https://go.dev/doc/modules/version-numbers).
// These ranges may be displayed but are generally not consumable
// by tools like govulncheck which expect standard Go module versions.
CustomRanges []Range `json:"custom_ranges,omitempty"`
}

// Entry represents a vulnerability in the Go OSV format, documented
Expand Down
59 changes: 34 additions & 25 deletions internal/vuln/vulns.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,9 @@ func toVulns(entries []*osv.Entry) []Vuln {

// AffectedComponent holds information about a module/package affected by a certain vulnerability.
type AffectedComponent struct {
Path string
Versions string
Path string
Versions string
CustomVersions string
// Lists of affected symbols (for packages).
// If both of these lists are empty, all symbols in the package are affected.
ExportedSymbols []string
Expand All @@ -92,18 +93,18 @@ type pair struct {

// collectRangePairs turns a slice of osv Ranges into a more manageable slice of
// formatted version pairs.
func collectRangePairs(a osv.Affected) []pair {
func collectRangePairs(modulePath string, rs []osv.Range) []pair {
var (
ps []pair
p pair
prefix string
)
if stdlib.Contains(a.Module.Path) {
if stdlib.Contains(modulePath) {
prefix = "go"
} else {
prefix = "v"
}
for _, r := range a.Ranges {
for _, r := range rs {
isSemver := r.Type == osv.RangeTypeSemver
for _, v := range r.Events {
if v.Introduced != "" {
Expand Down Expand Up @@ -131,37 +132,45 @@ func collectRangePairs(a osv.Affected) []pair {
return ps
}

func versionString(modulePath string, rs []osv.Range) string {
pairs := collectRangePairs(modulePath, rs)
var vs []string
for _, p := range pairs {
var s string
if p.intro == "" && p.fixed == "" {
// If neither field is set, the vuln applies to all versions.
// Leave it blank, the template will render it properly.
s = ""
} else if p.intro == "" {
s = "before " + p.fixed
} else if p.fixed == "" {
s = p.intro + " and later"
} else {
s = "from " + p.intro + " before " + p.fixed
}
vs = append(vs, s)
}
return strings.Join(vs, ", ")
}

// AffectedComponents extracts information about affected packages (and // modules, if there are any with no package information) from the given osv.Entry.
func AffectedComponents(e *osv.Entry) (pkgs, modsNoPkgs []*AffectedComponent) {
for _, a := range e.Affected {
pairs := collectRangePairs(a)
var vs []string
for _, p := range pairs {
var s string
if p.intro == "" && p.fixed == "" {
// If neither field is set, the vuln applies to all versions.
// Leave it blank, the template will render it properly.
s = ""
} else if p.intro == "" {
s = "before " + p.fixed
} else if p.fixed == "" {
s = p.intro + " and later"
} else {
s = "from " + p.intro + " before " + p.fixed
}
vs = append(vs, s)
}
vs := versionString(a.Module.Path, a.Ranges)
cvs := versionString(a.Module.Path, a.EcosystemSpecific.CustomRanges)
if len(a.EcosystemSpecific.Packages) == 0 {
modsNoPkgs = append(modsNoPkgs, &AffectedComponent{
Path: a.Module.Path,
Versions: strings.Join(vs, ", "),
Path: a.Module.Path,
Versions: vs,
CustomVersions: cvs,
})
}
for _, p := range a.EcosystemSpecific.Packages {
exported, unexported := affectedSymbols(p.Symbols)
pkgs = append(pkgs, &AffectedComponent{
Path: p.Path,
Versions: strings.Join(vs, ", "),
Versions: vs,
CustomVersions: cvs,
ExportedSymbols: exported,
UnexportedSymbols: unexported,
// TODO(hyangah): where to place GOOS/GOARCH info
Expand Down
29 changes: 28 additions & 1 deletion internal/vuln/vulns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ func TestCollectRangePairs(t *testing.T) {
{Type: "unspecified", Events: []osv.RangeEvent{{Introduced: "a", Fixed: "b"}}},
},
}
got := collectRangePairs(in)
got := collectRangePairs(in.Module.Path, in.Ranges)
want := []pair{
{"", "v0.5"},
{"v1.2", "v1.5"},
Expand Down Expand Up @@ -306,6 +306,33 @@ func TestAffectedComponents(t *testing.T) {
}},
wantMods: nil,
},
{
name: "custom ranges",
in: &osv.Entry{
ID: "GO-2022-0003",
Affected: []osv.Affected{{
Module: osv.Module{Path: "example.com/mod"},
EcosystemSpecific: osv.EcosystemSpecific{
Packages: []osv.Package{{
Path: "example.com/mod/pkg",
}},
CustomRanges: []osv.Range{
{
Type: osv.RangeType("ECOSYSTEM"),
Events: []osv.RangeEvent{
{Introduced: "0"}, {Fixed: "2.0.2"},
},
},
},
},
}},
},
wantPkgs: []*AffectedComponent{{
Path: "example.com/mod/pkg",
CustomVersions: "before 2.0.2",
}},
wantMods: nil,
},
{
name: "multiple pkgs and modules",
in: &osv.Entry{
Expand Down
6 changes: 5 additions & 1 deletion static/frontend/vuln/entry/entry.css
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,14 @@
padding: 0.5rem;
}

.VulnEntryModules {
.VulnTable-item-2col {
grid-template-columns: minmax(10em, 50%) 1fr;
}

.VulnTable-item-4col {
grid-template-columns: minmax(10em, 50%) minmax(5em, 20%) minmax(5em, 20%) 1fr;
}

/* Header */
.VulnEntryPackages-item-container:first-child {
background-color: var(--color-background-accented);
Expand Down
2 changes: 1 addition & 1 deletion static/frontend/vuln/entry/entry.min.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions static/frontend/vuln/entry/entry.min.css.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 763ccd4

Please sign in to comment.