mirror of
https://github.com/anchore/grype
synced 2024-11-12 23:37:06 +00:00
add matcher tests + dpkg constraint adapter (add <)
This commit is contained in:
parent
d9c922218c
commit
622f09feff
18 changed files with 378 additions and 96 deletions
|
@ -91,7 +91,7 @@ func runDefaultCmd(_ *cobra.Command, args []string) int {
|
||||||
// })
|
// })
|
||||||
|
|
||||||
// store := db.NewMockDb()
|
// store := db.NewMockDb()
|
||||||
store := db.GetStoreFromSqlite()
|
store := db.GetStore()
|
||||||
provider := vulnerability.NewProviderFromStore(store)
|
provider := vulnerability.NewProviderFromStore(store)
|
||||||
|
|
||||||
results := vulnscan.FindAllVulnerabilities(provider, osObj, catalog)
|
results := vulnscan.FindAllVulnerabilities(provider, osObj, catalog)
|
||||||
|
|
|
@ -2,6 +2,7 @@ package db
|
||||||
|
|
||||||
import "github.com/anchore/vulnscan-db/pkg/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)
|
return db.NewSqliteStore(nil)
|
||||||
}
|
}
|
||||||
|
|
20
internal/stringset.go
Normal file
20
internal/stringset.go
Normal 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
|
||||||
|
}
|
|
@ -25,13 +25,13 @@ func ExactPackageNameMatch(store vulnerability.Provider, o distro.Distro, p *pkg
|
||||||
|
|
||||||
for _, vuln := range allPkgVulns {
|
for _, vuln := range allPkgVulns {
|
||||||
// if the constraint it met, then the given package has the vulnerability
|
// 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 {
|
if err != nil {
|
||||||
// TODO: not enough information (cannot back track constraint object)
|
// 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)
|
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{
|
matches = append(matches, match.Match{
|
||||||
Type: match.ExactDirectMatch,
|
Type: match.ExactDirectMatch,
|
||||||
Confidence: 1.0, // TODO: this is hard coded for now
|
Confidence: 1.0, // TODO: this is hard coded for now
|
||||||
|
|
55
vulnscan/matcher/distro/matcher_mocks_test.go
Normal file
55
vulnscan/matcher/distro/matcher_mocks_test.go
Normal 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
|
||||||
|
}
|
63
vulnscan/matcher/distro/matcher_test.go
Normal file
63
vulnscan/matcher/distro/matcher_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -40,7 +40,7 @@ func (m *Matcher) Match(store vulnerability.Provider, d _distro.Distro, p *pkg.P
|
||||||
return matches, nil
|
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)
|
value, ok := p.Metadata.(pkg.DpkgMetadata)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("bad dpkg metadata type='%T'", value)
|
return nil, fmt.Errorf("bad dpkg metadata type='%T'", value)
|
||||||
|
|
55
vulnscan/matcher/dpkg/matcher_mocks_test.go
Normal file
55
vulnscan/matcher/dpkg/matcher_mocks_test.go
Normal 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
|
||||||
|
}
|
70
vulnscan/matcher/dpkg/matcher_test.go
Normal file
70
vulnscan/matcher/dpkg/matcher_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ package version
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
deb "github.com/knqyf263/go-deb-version"
|
deb "github.com/knqyf263/go-deb-version"
|
||||||
)
|
)
|
||||||
|
@ -21,12 +22,20 @@ type dpkgConstraint struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDpkgConstraint(raw string) (dpkgConstraint, error) {
|
func newDpkgConstraint(raw string) (dpkgConstraint, error) {
|
||||||
// TODO: allow for "<" parsing
|
|
||||||
if raw == "" {
|
if raw == "" {
|
||||||
// an empty constraint is always satisfied
|
// an empty constraint is always satisfied
|
||||||
return dpkgConstraint{}, nil
|
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 {
|
if err != nil {
|
||||||
return dpkgConstraint{}, fmt.Errorf("failed to create Dpkg constraint: %w", err)
|
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 {
|
func (c dpkgConstraint) String() string {
|
||||||
// TODO: don't put the "<" here, allow the vulnscan-db to insert this for us
|
|
||||||
if c.raw == "" {
|
if c.raw == "" {
|
||||||
return "None (dpkg)"
|
return "[no constraint] (dpkg)"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("< %s (dpkg)", c.raw)
|
return fmt.Sprintf("%s (dpkg)", c.raw)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,43 +7,43 @@ import (
|
||||||
|
|
||||||
func TestVersionDpkg(t *testing.T) {
|
func TestVersionDpkg(t *testing.T) {
|
||||||
tests := []testCase{
|
tests := []testCase{
|
||||||
{version: "2.3.1", constraint: "2.0.0", expected: false},
|
{version: "2.3.1", constraint: "< 2.0.0", isVulnerable: false},
|
||||||
{version: "2.3.1", constraint: "2.0", expected: false},
|
{version: "2.3.1", constraint: "< 2.0", isVulnerable: false},
|
||||||
{version: "2.3.1", constraint: "2", expected: false},
|
{version: "2.3.1", constraint: "< 2", isVulnerable: false},
|
||||||
{version: "2.3.1", constraint: "2.3", expected: false},
|
{version: "2.3.1", constraint: "< 2.3", isVulnerable: false},
|
||||||
{version: "2.3.1", constraint: "2.3.1", expected: false},
|
{version: "2.3.1", constraint: "< 2.3.1", isVulnerable: false},
|
||||||
{version: "2.3.1", constraint: "2.3.2", expected: true},
|
{version: "2.3.1", constraint: "< 2.3.2", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: "2.4", expected: true},
|
{version: "2.3.1", constraint: "< 2.4", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: "3", expected: true},
|
{version: "2.3.1", constraint: "< 3", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: "3.0", expected: true},
|
{version: "2.3.1", constraint: "< 3.0", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: "3.0.0", expected: true},
|
{version: "2.3.1", constraint: "< 3.0.0", isVulnerable: 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.0", isVulnerable: false},
|
||||||
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "2.0", expected: false},
|
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <2.0", isVulnerable: false},
|
||||||
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "2", expected: false},
|
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <2", isVulnerable: 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", isVulnerable: 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.1", isVulnerable: 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.3.2", isVulnerable: true},
|
||||||
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "2.4", expected: true},
|
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <2.4", isVulnerable: true},
|
||||||
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "3", expected: true},
|
{version: "2.3.1-1ubuntu0.14.04.1", constraint: " <3", isVulnerable: 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", isVulnerable: true},
|
||||||
{version: "2.3.1-1ubuntu0.14.04.1", constraint: "3.0.0", expected: 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", expected: false},
|
{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", expected: 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", expected: 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", expected: 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", expected: 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", expected: true},
|
{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", expected: 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", expected: 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", expected: false},
|
{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", expected: 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", expected: 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", expected: 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", expected: 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", expected: true},
|
{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", expected: 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", expected: 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", expected: true},
|
{version: "43.0.2357.81-0ubuntu0.14.04.1.1089", constraint: "<44-0ubuntu0.14.04.1.1089", isVulnerable: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|
|
@ -8,12 +8,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
version string
|
version string
|
||||||
constraint string
|
constraint string
|
||||||
expected bool
|
isVulnerable bool
|
||||||
createErr error
|
createErr error
|
||||||
constErr error
|
constErr error
|
||||||
checkErr error
|
checkErr error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *testCase) name() string {
|
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)
|
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) {
|
if !errors.Is(err, c.checkErr) {
|
||||||
t.Fatalf("unexpected check error: '%+v'!='%+v'", err, c.checkErr)
|
t.Fatalf("unexpected check error: '%+v'!='%+v'", err, c.checkErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if actual != c.expected {
|
if isVulnerable != c.isVulnerable {
|
||||||
t.Errorf("unexpected constraint check result: expected %+v, got %+v", c.expected, actual)
|
t.Errorf("unexpected constraint check result: expected %+v, got %+v", c.isVulnerable, isVulnerable)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,42 +7,42 @@ import (
|
||||||
|
|
||||||
func TestVersionSemantic(t *testing.T) {
|
func TestVersionSemantic(t *testing.T) {
|
||||||
tests := []testCase{
|
tests := []testCase{
|
||||||
{version: "2.3.1", constraint: "2.3.1", expected: true},
|
{version: "2.3.1", constraint: "2.3.1", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: "= 2.3.1", expected: true},
|
{version: "2.3.1", constraint: "= 2.3.1", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: " = 2.3.1", expected: true},
|
{version: "2.3.1", constraint: " = 2.3.1", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: ">= 2.3.1", expected: true},
|
{version: "2.3.1", constraint: ">= 2.3.1", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: "> 2.0.0", expected: true},
|
{version: "2.3.1", constraint: "> 2.0.0", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: "> 2.0", expected: true},
|
{version: "2.3.1", constraint: "> 2.0", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: "> 2", expected: true},
|
{version: "2.3.1", constraint: "> 2", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: "> 2, < 3", expected: true},
|
{version: "2.3.1", constraint: "> 2, < 3", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: "> 2.3, < 3.1", expected: true},
|
{version: "2.3.1", constraint: "> 2.3, < 3.1", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: "> 2.3.0, < 3.1", expected: true},
|
{version: "2.3.1", constraint: "> 2.3.0, < 3.1", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: ">= 2.3.1, < 3.1", expected: true},
|
{version: "2.3.1", constraint: ">= 2.3.1, < 3.1", isVulnerable: true},
|
||||||
{version: "2.3.1", constraint: " = 2.3.2", expected: false},
|
{version: "2.3.1", constraint: " = 2.3.2", isVulnerable: false},
|
||||||
{version: "2.3.1", constraint: ">= 2.3.2", expected: false},
|
{version: "2.3.1", constraint: ">= 2.3.2", isVulnerable: false},
|
||||||
{version: "2.3.1", constraint: "> 2.3.1", expected: false},
|
{version: "2.3.1", constraint: "> 2.3.1", isVulnerable: false},
|
||||||
{version: "2.3.1", constraint: "< 2.0.0", expected: false},
|
{version: "2.3.1", constraint: "< 2.0.0", isVulnerable: false},
|
||||||
{version: "2.3.1", constraint: "< 2.0", expected: false},
|
{version: "2.3.1", constraint: "< 2.0", isVulnerable: false},
|
||||||
{version: "2.3.1", constraint: "< 2", expected: false},
|
{version: "2.3.1", constraint: "< 2", isVulnerable: false},
|
||||||
{version: "2.3.1", constraint: "< 2, > 3", expected: false},
|
{version: "2.3.1", constraint: "< 2, > 3", isVulnerable: false},
|
||||||
{version: "2.3.1+meta", constraint: "2.3.1", expected: true},
|
{version: "2.3.1+meta", constraint: "2.3.1", isVulnerable: true},
|
||||||
{version: "2.3.1+meta", constraint: "= 2.3.1", expected: true},
|
{version: "2.3.1+meta", constraint: "= 2.3.1", isVulnerable: true},
|
||||||
{version: "2.3.1+meta", constraint: " = 2.3.1", expected: true},
|
{version: "2.3.1+meta", constraint: " = 2.3.1", isVulnerable: true},
|
||||||
{version: "2.3.1+meta", constraint: ">= 2.3.1", expected: true},
|
{version: "2.3.1+meta", constraint: ">= 2.3.1", isVulnerable: true},
|
||||||
{version: "2.3.1+meta", constraint: "> 2.0.0", expected: true},
|
{version: "2.3.1+meta", constraint: "> 2.0.0", isVulnerable: true},
|
||||||
{version: "2.3.1+meta", constraint: "> 2.0", expected: true},
|
{version: "2.3.1+meta", constraint: "> 2.0", isVulnerable: true},
|
||||||
{version: "2.3.1+meta", constraint: "> 2", expected: true},
|
{version: "2.3.1+meta", constraint: "> 2", isVulnerable: true},
|
||||||
{version: "2.3.1+meta", constraint: "> 2, < 3", expected: true},
|
{version: "2.3.1+meta", constraint: "> 2, < 3", isVulnerable: true},
|
||||||
{version: "2.3.1+meta", constraint: "> 2.3, < 3.1", expected: true},
|
{version: "2.3.1+meta", constraint: "> 2.3, < 3.1", isVulnerable: true},
|
||||||
{version: "2.3.1+meta", constraint: "> 2.3.0, < 3.1", expected: 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", expected: true},
|
{version: "2.3.1+meta", constraint: ">= 2.3.1, < 3.1", isVulnerable: true},
|
||||||
{version: "2.3.1+meta", constraint: " = 2.3.2", expected: false},
|
{version: "2.3.1+meta", constraint: " = 2.3.2", isVulnerable: false},
|
||||||
{version: "2.3.1+meta", constraint: ">= 2.3.2", expected: false},
|
{version: "2.3.1+meta", constraint: ">= 2.3.2", isVulnerable: false},
|
||||||
{version: "2.3.1+meta", constraint: "> 2.3.1", expected: false},
|
{version: "2.3.1+meta", constraint: "> 2.3.1", isVulnerable: false},
|
||||||
{version: "2.3.1+meta", constraint: "< 2.0.0", expected: false},
|
{version: "2.3.1+meta", constraint: "< 2.0.0", isVulnerable: false},
|
||||||
{version: "2.3.1+meta", constraint: "< 2.0", expected: false},
|
{version: "2.3.1+meta", constraint: "< 2.0", isVulnerable: false},
|
||||||
{version: "2.3.1+meta", constraint: "< 2", expected: false},
|
{version: "2.3.1+meta", constraint: "< 2", isVulnerable: false},
|
||||||
{version: "2.3.1+meta", constraint: "< 2, > 3", expected: false},
|
{version: "2.3.1+meta", constraint: "< 2, > 3", isVulnerable: false},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
|
|
@ -38,7 +38,6 @@ func NewVersionFromPkg(p *pkg.Package) (*Version, error) {
|
||||||
switch p.Type {
|
switch p.Type {
|
||||||
case pkg.DebPkg:
|
case pkg.DebPkg:
|
||||||
format = DpkgFormat
|
format = DpkgFormat
|
||||||
// ...
|
|
||||||
default:
|
default:
|
||||||
format = UnknownFormat
|
format = UnknownFormat
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,5 +6,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
|
ProviderByDistro
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProviderByDistro interface {
|
||||||
GetByDistro(distro.Distro, *pkg.Package) ([]*Vulnerability, error)
|
GetByDistro(distro.Distro, *pkg.Package) ([]*Vulnerability, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,14 @@ func (pr *StoreProvider) GetByDistro(d distro.Distro, p *pkg.Package) ([]*Vulner
|
||||||
for _, vuln := range allPkgVulns {
|
for _, vuln := range allPkgVulns {
|
||||||
format := version.ParseFormat(vuln.VersionFormat)
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("provider failed to parse constraint='%s' format='%s': %w", vuln.Version, format, err)
|
return nil, fmt.Errorf("provider failed to parse constraint='%s' format='%s': %w", vuln.Version, format, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,11 +32,11 @@ func TestGetByDistro(t *testing.T) {
|
||||||
|
|
||||||
expected := []Vulnerability{
|
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",
|
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",
|
ID: "CVE-2013-fake-2",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue