add matcher tests + dpkg constraint adapter (add <)

This commit is contained in:
Alex Goodman 2020-06-03 11:53:43 -04:00
parent d9c922218c
commit 622f09feff
No known key found for this signature in database
GPG key ID: 86E2870463D5E890
18 changed files with 378 additions and 96 deletions

View file

@ -91,7 +91,7 @@ func runDefaultCmd(_ *cobra.Command, args []string) int {
// })
// store := db.NewMockDb()
store := db.GetStoreFromSqlite()
store := db.GetStore()
provider := vulnerability.NewProviderFromStore(store)
results := vulnscan.FindAllVulnerabilities(provider, osObj, catalog)

View file

@ -2,6 +2,7 @@ package db
import "github.com/anchore/vulnscan-db/pkg/db"
func GetStoreFromSqlite() *db.SqliteStore {
func GetStore() db.VulnStore {
// TODO: add connection options and info
return db.NewSqliteStore(nil)
}

20
internal/stringset.go Normal file
View file

@ -0,0 +1,20 @@
package internal
type Set map[string]struct{}
func NewStringSet() Set {
return make(Set)
}
func (s Set) Add(i string) {
s[i] = struct{}{}
}
func (s Set) Remove(i string) {
delete(s, i)
}
func (s Set) Contains(i string) bool {
_, ok := s[i]
return ok
}

View file

@ -25,13 +25,13 @@ func ExactPackageNameMatch(store vulnerability.Provider, o distro.Distro, p *pkg
for _, vuln := range allPkgVulns {
// if the constraint it met, then the given package has the vulnerability
satisfied, err := vuln.Constraint.Satisfied(verObj)
isPackageVulnerable, err := vuln.Constraint.Satisfied(verObj)
if err != nil {
// TODO: not enough information (cannot back track constraint object)
return nil, fmt.Errorf("matcher failed to check constraint='%s' version='%s': %w", vuln.Constraint, verObj, err)
}
if satisfied {
if isPackageVulnerable {
matches = append(matches, match.Match{
Type: match.ExactDirectMatch,
Confidence: 1.0, // TODO: this is hard coded for now

View file

@ -0,0 +1,55 @@
package distro
import (
"strings"
"github.com/anchore/imgbom/imgbom/distro"
"github.com/anchore/imgbom/imgbom/pkg"
"github.com/anchore/vulnscan/vulnscan/version"
"github.com/anchore/vulnscan/vulnscan/vulnerability"
)
type mockProvider struct {
data map[string]map[string][]*vulnerability.Vulnerability
}
func newMockProvider() *mockProvider {
pr := mockProvider{
data: make(map[string]map[string][]*vulnerability.Vulnerability),
}
pr.stub()
return &pr
}
func (pr *mockProvider) stub() {
pr.data["debian:8"] = map[string][]*vulnerability.Vulnerability{
// direct...
"neutron": {
{
Constraint: version.MustGetConstraint("< 2014.1.5-6", version.DpkgFormat),
ID: "CVE-2014-fake-1",
},
},
// indirect...
"neutron-devel": {
// expected...
{
Constraint: version.MustGetConstraint("< 2014.1.4-5", version.DpkgFormat),
ID: "CVE-2014-fake-2",
},
{
Constraint: version.MustGetConstraint("< 2015.0.0-1", version.DpkgFormat),
ID: "CVE-2013-fake-3",
},
// unexpected...
{
Constraint: version.MustGetConstraint("< 2014.0.4-1", version.DpkgFormat),
ID: "CVE-2013-fake-BAD",
},
},
}
}
func (pr *mockProvider) GetByDistro(d distro.Distro, p *pkg.Package) ([]*vulnerability.Vulnerability, error) {
return pr.data[strings.ToLower(d.Type.String())+":"+d.FullVersion()][p.Name], nil
}

View file

@ -0,0 +1,63 @@
package distro
import (
"testing"
"github.com/anchore/imgbom/imgbom/distro"
"github.com/anchore/imgbom/imgbom/pkg"
"github.com/anchore/vulnscan/internal"
"github.com/anchore/vulnscan/vulnscan/match"
)
func TestMatcher_ExactPackageNameMatch(t *testing.T) {
p := pkg.Package{
Name: "neutron",
Version: "2014.1.3-6",
Type: pkg.DebPkg,
Metadata: pkg.DpkgMetadata{
Source: "neutron-devel",
},
}
d, err := distro.NewDistro(distro.Debian, "8")
if err != nil {
t.Fatal("could not create distro: ", err)
}
store := newMockProvider()
actual, err := ExactPackageNameMatch(store, d, &p, "SOME_OTHER_MATCHER")
if len(actual) != 1 {
t.Fatalf("unexpected direct matches count: %d", len(actual))
}
foundCVEs := internal.NewStringSet()
for _, a := range actual {
foundCVEs.Add(a.Vulnerability.ID)
if a.Type != match.ExactDirectMatch {
t.Error("direct match not indicated")
}
if a.Package.Name != p.Name {
t.Errorf("failed to capture correct original package: %s", a.Package.Name)
}
if a.Matcher != "SOME_OTHER_MATCHER" {
t.Errorf("failed to capture matcher name: %s", a.Matcher)
}
if a.IndirectPackage != nil {
t.Fatalf("should not have captured indirect package")
}
}
for _, id := range []string{"CVE-2014-fake-1"} {
if !foundCVEs.Contains(id) {
t.Errorf("missing discovered CVE: %s", id)
}
}
}

View file

@ -40,7 +40,7 @@ func (m *Matcher) Match(store vulnerability.Provider, d _distro.Distro, p *pkg.P
return matches, nil
}
func (m *Matcher) matchBySourceIndirection(store vulnerability.Provider, d _distro.Distro, p *pkg.Package) ([]match.Match, error) {
func (m *Matcher) matchBySourceIndirection(store vulnerability.ProviderByDistro, d _distro.Distro, p *pkg.Package) ([]match.Match, error) {
value, ok := p.Metadata.(pkg.DpkgMetadata)
if !ok {
return nil, fmt.Errorf("bad dpkg metadata type='%T'", value)

View file

@ -0,0 +1,55 @@
package dpkg
import (
"strings"
"github.com/anchore/imgbom/imgbom/distro"
"github.com/anchore/imgbom/imgbom/pkg"
"github.com/anchore/vulnscan/vulnscan/version"
"github.com/anchore/vulnscan/vulnscan/vulnerability"
)
type mockProvider struct {
data map[string]map[string][]*vulnerability.Vulnerability
}
func newMockProvider() *mockProvider {
pr := mockProvider{
data: make(map[string]map[string][]*vulnerability.Vulnerability),
}
pr.stub()
return &pr
}
func (pr *mockProvider) stub() {
pr.data["debian:8"] = map[string][]*vulnerability.Vulnerability{
// direct...
"neutron": {
{
Constraint: version.MustGetConstraint("< 2014.1.3-6", version.DpkgFormat),
ID: "CVE-2014-fake-1",
},
},
// indirect...
"neutron-devel": {
// expected...
{
Constraint: version.MustGetConstraint("< 2014.1.4-5", version.DpkgFormat),
ID: "CVE-2014-fake-2",
},
{
Constraint: version.MustGetConstraint("< 2015.0.0-1", version.DpkgFormat),
ID: "CVE-2013-fake-3",
},
// unexpected...
{
Constraint: version.MustGetConstraint("< 2014.0.4-1", version.DpkgFormat),
ID: "CVE-2013-fake-BAD",
},
},
}
}
func (pr *mockProvider) GetByDistro(d distro.Distro, p *pkg.Package) ([]*vulnerability.Vulnerability, error) {
return pr.data[strings.ToLower(d.Type.String())+":"+d.FullVersion()][p.Name], nil
}

View file

@ -0,0 +1,70 @@
package dpkg
import (
"testing"
"github.com/anchore/imgbom/imgbom/distro"
"github.com/anchore/imgbom/imgbom/pkg"
"github.com/anchore/vulnscan/internal"
"github.com/anchore/vulnscan/vulnscan/match"
)
func TestMatcherDpkg_matchBySourceIndirection(t *testing.T) {
matcher := Matcher{}
p := pkg.Package{
Name: "neutron",
Version: "2014.1.3-6",
Type: pkg.DebPkg,
Metadata: pkg.DpkgMetadata{
Source: "neutron-devel",
},
}
d, err := distro.NewDistro(distro.Debian, "8")
if err != nil {
t.Fatal("could not create distro: ", err)
}
store := newMockProvider()
actual, err := matcher.matchBySourceIndirection(store, d, &p)
if len(actual) != 2 {
t.Fatalf("unexpected indirect matches count: %d", len(actual))
}
foundCVEs := internal.NewStringSet()
for _, a := range actual {
foundCVEs.Add(a.Vulnerability.ID)
if a.Type != match.ExactIndirectMatch {
t.Error("indirect match not indicated")
}
if a.Package.Name != p.Name {
t.Errorf("failed to capture correct original package: %s", a.Package.Name)
}
if a.Matcher != matcher.Name() {
t.Errorf("failed to capture matcher name: %s", a.Matcher)
}
if a.IndirectPackage == nil {
t.Fatalf("failed to capture correct indirect package")
}
if a.IndirectPackage.Name != p.Name+"-devel" {
t.Errorf("failed to capture correct indirect package name: %s", a.IndirectPackage.Name)
}
}
for _, id := range []string{"CVE-2014-fake-2", "CVE-2013-fake-3"} {
if !foundCVEs.Contains(id) {
t.Errorf("missing discovered CVE: %s", id)
}
}
if t.Failed() {
t.Logf("discovered CVES: %+v", foundCVEs)
}
}

View file

@ -2,6 +2,7 @@ package version
import (
"fmt"
"strings"
deb "github.com/knqyf263/go-deb-version"
)
@ -21,12 +22,20 @@ type dpkgConstraint struct {
}
func newDpkgConstraint(raw string) (dpkgConstraint, error) {
// TODO: allow for "<" parsing
if raw == "" {
// an empty constraint is always satisfied
return dpkgConstraint{}, nil
}
fixedIn, err := newDpkgVersion(raw)
fixedVersion := strings.TrimPrefix(strings.TrimSpace(raw), "<")
if strings.ContainsAny(fixedVersion, "><=") {
return dpkgConstraint{}, fmt.Errorf("invalid constraint given (%s), only '< fixedversion' allowed for DPKG version constraints", fixedVersion)
}
if fixedVersion == raw {
return dpkgConstraint{}, fmt.Errorf("no constraints found (< operator)")
}
fixedIn, err := newDpkgVersion(fixedVersion)
if err != nil {
return dpkgConstraint{}, fmt.Errorf("failed to create Dpkg constraint: %w", err)
}
@ -57,9 +66,8 @@ func (c dpkgConstraint) Satisfied(version *Version) (bool, error) {
}
func (c dpkgConstraint) String() string {
// TODO: don't put the "<" here, allow the vulnscan-db to insert this for us
if c.raw == "" {
return "None (dpkg)"
return "[no constraint] (dpkg)"
}
return fmt.Sprintf("< %s (dpkg)", c.raw)
return fmt.Sprintf("%s (dpkg)", c.raw)
}

View file

@ -7,43 +7,43 @@ import (
func TestVersionDpkg(t *testing.T) {
tests := []testCase{
{version: "2.3.1", constraint: "2.0.0", expected: false},
{version: "2.3.1", constraint: "2.0", expected: false},
{version: "2.3.1", constraint: "2", expected: false},
{version: "2.3.1", constraint: "2.3", expected: false},
{version: "2.3.1", constraint: "2.3.1", expected: false},
{version: "2.3.1", constraint: "2.3.2", expected: true},
{version: "2.3.1", constraint: "2.4", expected: true},
{version: "2.3.1", constraint: "3", expected: true},
{version: "2.3.1", constraint: "3.0", expected: true},
{version: "2.3.1", constraint: "3.0.0", expected: true},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "2.0.0", expected: false},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "2.0", expected: false},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "2", expected: false},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "2.3", expected: false},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "2.3.1", expected: false},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "2.3.2", expected: true},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "2.4", expected: true},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "3", expected: true},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "3.0", expected: true},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "3.0.0", expected: true},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: "7u151-2.6.11-2ubuntu0.14.04.1", expected: false},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: "7u151-2.6.11", expected: false},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: "7u151-2.7", expected: false},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: "7u151", expected: false},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: "7u150", expected: false},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: "7u152", expected: true},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: "7u152-2.6.11-2ubuntu0.14.04.1", expected: true},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: "8u1-2.6.11-2ubuntu0.14.04.1", expected: true},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "43", expected: false},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "43.0", expected: false},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "43.0.2357", expected: false},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "43.0.2357.81", expected: false},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "43.0.2357.81-0ubuntu0.14.04.1.1089", expected: false},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "43.0.2357.82-0ubuntu0.14.04.1.1089", expected: true},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "43.0.2358-0ubuntu0.14.04.1.1089", expected: true},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "43.1-0ubuntu0.14.04.1.1089", expected: true},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "44-0ubuntu0.14.04.1.1089", expected: true},
{version: "2.3.1", constraint: "< 2.0.0", isVulnerable: false},
{version: "2.3.1", constraint: "< 2.0", isVulnerable: false},
{version: "2.3.1", constraint: "< 2", isVulnerable: false},
{version: "2.3.1", constraint: "< 2.3", isVulnerable: false},
{version: "2.3.1", constraint: "< 2.3.1", isVulnerable: false},
{version: "2.3.1", constraint: "< 2.3.2", isVulnerable: true},
{version: "2.3.1", constraint: "< 2.4", isVulnerable: true},
{version: "2.3.1", constraint: "< 3", isVulnerable: true},
{version: "2.3.1", constraint: "< 3.0", isVulnerable: true},
{version: "2.3.1", constraint: "< 3.0.0", isVulnerable: true},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <2.0.0", isVulnerable: false},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <2.0", isVulnerable: false},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <2", isVulnerable: false},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <2.3", isVulnerable: false},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <2.3.1", isVulnerable: false},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <2.3.2", isVulnerable: true},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <2.4", isVulnerable: true},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <3", isVulnerable: true},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <3.0", isVulnerable: true},
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <3.0.0", isVulnerable: true},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: " < 7u151-2.6.11-2ubuntu0.14.04.1", isVulnerable: false},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: " < 7u151-2.6.11", isVulnerable: false},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: " < 7u151-2.7", isVulnerable: false},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: " < 7u151", isVulnerable: false},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: " < 7u150", isVulnerable: false},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: " < 7u152", isVulnerable: true},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: " < 7u152-2.6.11-2ubuntu0.14.04.1", isVulnerable: true},
{version: "7u151-2.6.11-2ubuntu0.14.04.1", constraint: " < 8u1-2.6.11-2ubuntu0.14.04.1", isVulnerable: true},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "<43", isVulnerable: false},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "<43.0", isVulnerable: false},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "<43.0.2357", isVulnerable: false},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "<43.0.2357.81", isVulnerable: false},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "<43.0.2357.81-0ubuntu0.14.04.1.1089", isVulnerable: false},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "<43.0.2357.82-0ubuntu0.14.04.1.1089", isVulnerable: true},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "<43.0.2358-0ubuntu0.14.04.1.1089", isVulnerable: true},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "<43.1-0ubuntu0.14.04.1.1089", isVulnerable: true},
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "<44-0ubuntu0.14.04.1.1089", isVulnerable: true},
}
for _, test := range tests {

View file

@ -8,12 +8,12 @@ import (
)
type testCase struct {
version string
constraint string
expected bool
createErr error
constErr error
checkErr error
version string
constraint string
isVulnerable bool
createErr error
constErr error
checkErr error
}
func (c *testCase) name() string {
@ -26,13 +26,13 @@ func (c *testCase) assert(t *testing.T, format Format, constraint Constraint) {
t.Fatalf("unexpected create error: '%+v'!='%+v'", err, c.createErr)
}
actual, err := constraint.Satisfied(verObj)
isVulnerable, err := constraint.Satisfied(verObj)
if !errors.Is(err, c.checkErr) {
t.Fatalf("unexpected check error: '%+v'!='%+v'", err, c.checkErr)
}
if actual != c.expected {
t.Errorf("unexpected constraint check result: expected %+v, got %+v", c.expected, actual)
if isVulnerable != c.isVulnerable {
t.Errorf("unexpected constraint check result: expected %+v, got %+v", c.isVulnerable, isVulnerable)
}
}

View file

@ -7,42 +7,42 @@ import (
func TestVersionSemantic(t *testing.T) {
tests := []testCase{
{version: "2.3.1", constraint: "2.3.1", expected: true},
{version: "2.3.1", constraint: "= 2.3.1", expected: true},
{version: "2.3.1", constraint: " = 2.3.1", expected: true},
{version: "2.3.1", constraint: ">= 2.3.1", expected: true},
{version: "2.3.1", constraint: "> 2.0.0", expected: true},
{version: "2.3.1", constraint: "> 2.0", expected: true},
{version: "2.3.1", constraint: "> 2", expected: true},
{version: "2.3.1", constraint: "> 2, < 3", expected: true},
{version: "2.3.1", constraint: "> 2.3, < 3.1", expected: true},
{version: "2.3.1", constraint: "> 2.3.0, < 3.1", expected: true},
{version: "2.3.1", constraint: ">= 2.3.1, < 3.1", expected: true},
{version: "2.3.1", constraint: " = 2.3.2", expected: false},
{version: "2.3.1", constraint: ">= 2.3.2", expected: false},
{version: "2.3.1", constraint: "> 2.3.1", expected: false},
{version: "2.3.1", constraint: "< 2.0.0", expected: false},
{version: "2.3.1", constraint: "< 2.0", expected: false},
{version: "2.3.1", constraint: "< 2", expected: false},
{version: "2.3.1", constraint: "< 2, > 3", expected: false},
{version: "2.3.1+meta", constraint: "2.3.1", expected: true},
{version: "2.3.1+meta", constraint: "= 2.3.1", expected: true},
{version: "2.3.1+meta", constraint: " = 2.3.1", expected: true},
{version: "2.3.1+meta", constraint: ">= 2.3.1", expected: true},
{version: "2.3.1+meta", constraint: "> 2.0.0", expected: true},
{version: "2.3.1+meta", constraint: "> 2.0", expected: true},
{version: "2.3.1+meta", constraint: "> 2", expected: true},
{version: "2.3.1+meta", constraint: "> 2, < 3", expected: true},
{version: "2.3.1+meta", constraint: "> 2.3, < 3.1", expected: true},
{version: "2.3.1+meta", constraint: "> 2.3.0, < 3.1", expected: true},
{version: "2.3.1+meta", constraint: ">= 2.3.1, < 3.1", expected: true},
{version: "2.3.1+meta", constraint: " = 2.3.2", expected: false},
{version: "2.3.1+meta", constraint: ">= 2.3.2", expected: false},
{version: "2.3.1+meta", constraint: "> 2.3.1", expected: false},
{version: "2.3.1+meta", constraint: "< 2.0.0", expected: false},
{version: "2.3.1+meta", constraint: "< 2.0", expected: false},
{version: "2.3.1+meta", constraint: "< 2", expected: false},
{version: "2.3.1+meta", constraint: "< 2, > 3", expected: false},
{version: "2.3.1", constraint: "2.3.1", isVulnerable: true},
{version: "2.3.1", constraint: "= 2.3.1", isVulnerable: true},
{version: "2.3.1", constraint: " = 2.3.1", isVulnerable: true},
{version: "2.3.1", constraint: ">= 2.3.1", isVulnerable: true},
{version: "2.3.1", constraint: "> 2.0.0", isVulnerable: true},
{version: "2.3.1", constraint: "> 2.0", isVulnerable: true},
{version: "2.3.1", constraint: "> 2", isVulnerable: true},
{version: "2.3.1", constraint: "> 2, < 3", isVulnerable: true},
{version: "2.3.1", constraint: "> 2.3, < 3.1", isVulnerable: true},
{version: "2.3.1", constraint: "> 2.3.0, < 3.1", isVulnerable: true},
{version: "2.3.1", constraint: ">= 2.3.1, < 3.1", isVulnerable: true},
{version: "2.3.1", constraint: " = 2.3.2", isVulnerable: false},
{version: "2.3.1", constraint: ">= 2.3.2", isVulnerable: false},
{version: "2.3.1", constraint: "> 2.3.1", isVulnerable: false},
{version: "2.3.1", constraint: "< 2.0.0", isVulnerable: false},
{version: "2.3.1", constraint: "< 2.0", isVulnerable: false},
{version: "2.3.1", constraint: "< 2", isVulnerable: false},
{version: "2.3.1", constraint: "< 2, > 3", isVulnerable: false},
{version: "2.3.1+meta", constraint: "2.3.1", isVulnerable: true},
{version: "2.3.1+meta", constraint: "= 2.3.1", isVulnerable: true},
{version: "2.3.1+meta", constraint: " = 2.3.1", isVulnerable: true},
{version: "2.3.1+meta", constraint: ">= 2.3.1", isVulnerable: true},
{version: "2.3.1+meta", constraint: "> 2.0.0", isVulnerable: true},
{version: "2.3.1+meta", constraint: "> 2.0", isVulnerable: true},
{version: "2.3.1+meta", constraint: "> 2", isVulnerable: true},
{version: "2.3.1+meta", constraint: "> 2, < 3", isVulnerable: true},
{version: "2.3.1+meta", constraint: "> 2.3, < 3.1", isVulnerable: true},
{version: "2.3.1+meta", constraint: "> 2.3.0, < 3.1", isVulnerable: true},
{version: "2.3.1+meta", constraint: ">= 2.3.1, < 3.1", isVulnerable: true},
{version: "2.3.1+meta", constraint: " = 2.3.2", isVulnerable: false},
{version: "2.3.1+meta", constraint: ">= 2.3.2", isVulnerable: false},
{version: "2.3.1+meta", constraint: "> 2.3.1", isVulnerable: false},
{version: "2.3.1+meta", constraint: "< 2.0.0", isVulnerable: false},
{version: "2.3.1+meta", constraint: "< 2.0", isVulnerable: false},
{version: "2.3.1+meta", constraint: "< 2", isVulnerable: false},
{version: "2.3.1+meta", constraint: "< 2, > 3", isVulnerable: false},
}
for _, test := range tests {

View file

@ -38,7 +38,6 @@ func NewVersionFromPkg(p *pkg.Package) (*Version, error) {
switch p.Type {
case pkg.DebPkg:
format = DpkgFormat
// ...
default:
format = UnknownFormat
}

View file

@ -6,5 +6,9 @@ import (
)
type Provider interface {
ProviderByDistro
}
type ProviderByDistro interface {
GetByDistro(distro.Distro, *pkg.Package) ([]*Vulnerability, error)
}

View file

@ -34,7 +34,14 @@ func (pr *StoreProvider) GetByDistro(d distro.Distro, p *pkg.Package) ([]*Vulner
for _, vuln := range allPkgVulns {
format := version.ParseFormat(vuln.VersionFormat)
constraint, err := version.GetConstraint(vuln.Version, format)
// TODO: delete me, this should be implemented in the vulnscan-db repo
var prefix string
if format == version.DpkgFormat && vuln.Version != "" {
prefix = "< "
}
// </TODO>
constraint, err := version.GetConstraint(prefix+vuln.Version, format)
if err != nil {
return nil, fmt.Errorf("provider failed to parse constraint='%s' format='%s': %w", vuln.Version, format, err)
}

View file

@ -32,11 +32,11 @@ func TestGetByDistro(t *testing.T) {
expected := []Vulnerability{
{
Constraint: version.MustGetConstraint("2014.1.3-6", version.DpkgFormat),
Constraint: version.MustGetConstraint("< 2014.1.3-6", version.DpkgFormat),
ID: "CVE-2014-fake-1",
},
{
Constraint: version.MustGetConstraint("2013.0.2-1", version.DpkgFormat),
Constraint: version.MustGetConstraint("< 2013.0.2-1", version.DpkgFormat),
ID: "CVE-2013-fake-2",
},
}