diff --git a/commands/tui.go b/commands/tui.go index 254f3bfecd..3372552030 100644 --- a/commands/tui.go +++ b/commands/tui.go @@ -197,6 +197,7 @@ func (p *TuiCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) s c.Conf.CvssScoreOver = p.cvssScoreOver c.Conf.IgnoreUnscoredCves = p.ignoreUnscoredCves c.Conf.IgnoreUnfixed = p.ignoreUnfixed + c.Conf.RefreshCve = p.refreshCve log.Info("Validating config...") if !c.Conf.ValidateOnTui() { diff --git a/oval/redhat.go b/oval/redhat.go index 42385bf137..9965730d58 100644 --- a/oval/redhat.go +++ b/oval/redhat.go @@ -67,6 +67,35 @@ func (o RedHatBase) FillWithOval(r *models.ScanResult) (err error) { return nil } +var kernelRelatedPackNames = map[string]bool{ + "kernel": true, + "kernel-aarch64": true, + "kernel-abi-whitelists": true, + "kernel-bootwrapper": true, + "kernel-debug": true, + "kernel-debug-devel": true, + "kernel-devel": true, + "kernel-doc": true, + "kernel-headers": true, + "kernel-kdump": true, + "kernel-kdump-devel": true, + "kernel-rt": true, + "kernel-rt-debug": true, + "kernel-rt-debug-devel": true, + "kernel-rt-debug-kvm": true, + "kernel-rt-devel": true, + "kernel-rt-doc": true, + "kernel-rt-kvm": true, + "kernel-rt-trace": true, + "kernel-rt-trace-devel": true, + "kernel-rt-trace-kvm": true, + "kernel-rt-virt": true, + "kernel-rt-virt-devel": true, + "kernel-tools": true, + "kernel-tools-libs": true, + "kernel-tools-libs-devel": true, +} + func (o RedHatBase) update(r *models.ScanResult, defPacks defPacks) { ctype := models.NewCveContentType(o.family) for _, cve := range defPacks.def.Advisory.Cves { diff --git a/oval/util.go b/oval/util.go index ccd112fdf2..d1c6626c64 100644 --- a/oval/util.go +++ b/oval/util.go @@ -22,6 +22,7 @@ import ( "fmt" "net/http" "regexp" + "strings" "time" "github.com/cenkalti/backoff" @@ -146,7 +147,7 @@ func getDefsByPackNameViaHTTP(r *models.ScanResult) ( select { case res := <-resChan: for _, def := range res.defs { - affected, notFixedYet := isOvalDefAffected(def, r.Family, res.request) + affected, notFixedYet := isOvalDefAffected(def, res.request, r.Family, r.RunningKernel) if !affected { continue } @@ -253,7 +254,7 @@ func getDefsByPackNameFromOvalDB(r *models.ScanResult) (relatedDefs ovalResult, return relatedDefs, fmt.Errorf("Failed to get %s OVAL info by package name: %v", r.Family, err) } for _, def := range definitions { - affected, notFixedYet := isOvalDefAffected(def, r.Family, req) + affected, notFixedYet := isOvalDefAffected(def, req, r.Family, r.RunningKernel) if !affected { continue } @@ -270,12 +271,35 @@ func getDefsByPackNameFromOvalDB(r *models.ScanResult) (relatedDefs ovalResult, return } -func isOvalDefAffected(def ovalmodels.Definition, family string, req request) (affected, notFixedYet bool) { +func major(version string) string { + ss := strings.SplitN(version, ":", 2) + ver := "" + if len(ss) == 1 { + ver = ss[0] + } else { + ver = ss[1] + } + return ver[0:strings.Index(ver, ".")] +} + +func isOvalDefAffected(def ovalmodels.Definition, req request, family string, running models.Kernel) (affected, notFixedYet bool) { for _, ovalPack := range def.AffectedPacks { if req.packName != ovalPack.Name { continue } + if running.Release != "" { + switch family { + case config.RedHat, config.CentOS: + // For kernel related packages, ignore OVAL information with different major versions + if _, ok := kernelRelatedPackNames[ovalPack.Name]; ok { + if major(ovalPack.Version) != major(running.Release) { + continue + } + } + } + } + if ovalPack.NotFixedYet { return true, true } diff --git a/oval/util_test.go b/oval/util_test.go index e536de6711..fa63c3ca1c 100644 --- a/oval/util_test.go +++ b/oval/util_test.go @@ -5,6 +5,7 @@ import ( "sort" "testing" + "github.com/future-architect/vuls/config" "github.com/future-architect/vuls/models" ovalmodels "github.com/kotakanbe/goval-dictionary/models" ) @@ -167,8 +168,9 @@ func TestDefpacksToPackStatuses(t *testing.T) { func TestIsOvalDefAffected(t *testing.T) { type in struct { def ovalmodels.Definition - family string req request + family string + kernel models.Kernel } var tests = []struct { in in @@ -932,9 +934,58 @@ func TestIsOvalDefAffected(t *testing.T) { affected: false, notFixedYet: false, }, + // For kernel related packages, ignore OVAL with different major versions + { + in: in{ + family: config.CentOS, + def: ovalmodels.Definition{ + AffectedPacks: []ovalmodels.Package{ + { + Name: "kernel", + Version: "4.1.0", + NotFixedYet: false, + }, + }, + }, + req: request{ + packName: "kernel", + versionRelease: "3.0.0", + NewVersionRelease: "3.2.0", + }, + kernel: models.Kernel{ + Release: "3.0.0", + }, + }, + affected: false, + notFixedYet: false, + }, + { + in: in{ + family: config.CentOS, + def: ovalmodels.Definition{ + AffectedPacks: []ovalmodels.Package{ + { + Name: "kernel", + Version: "3.1.0", + NotFixedYet: false, + }, + }, + }, + req: request{ + packName: "kernel", + versionRelease: "3.0.0", + NewVersionRelease: "3.2.0", + }, + kernel: models.Kernel{ + Release: "3.0.0", + }, + }, + affected: true, + notFixedYet: false, + }, } for i, tt := range tests { - affected, notFixedYet := isOvalDefAffected(tt.in.def, tt.in.family, tt.in.req) + affected, notFixedYet := isOvalDefAffected(tt.in.def, tt.in.req, tt.in.family, tt.in.kernel) if tt.affected != affected { t.Errorf("[%d] affected\nexpected: %v\n actual: %v\n", i, tt.affected, affected) } @@ -943,3 +994,25 @@ func TestIsOvalDefAffected(t *testing.T) { } } } + +func TestMajor(t *testing.T) { + var tests = []struct { + in string + expected string + }{ + { + in: "4.1", + expected: "4", + }, + { + in: "0:4.1", + expected: "4", + }, + } + for i, tt := range tests { + a := major(tt.in) + if tt.expected != a { + t.Errorf("[%d]\nexpected: %s\n actual: %s\n", i, tt.expected, a) + } + } +}