diff --git a/report/util.go b/report/util.go index 45f5c258..f53c4bf8 100644 --- a/report/util.go +++ b/report/util.go @@ -344,14 +344,14 @@ func getDiffCves(previous, current models.ScanResult) models.VulnInfos { updated := models.VulnInfos{} for _, v := range current.ScannedCves { if previousCveIDsSet[v.CveID] { - if isCveInfoUpdated(v.CveID, previous, current) { + if isCveInfoUpdated(v.CveID, previous, current) || isCveFixed(v, previous) { updated[v.CveID] = v - util.Log.Debugf("updated: %s", v.CveID) + util.Log.Debugf("updated or new release: %s", v.CveID) } else { - util.Log.Debugf("same: %s", v.CveID) + util.Log.Debugf("same and not new Release: %s", v.CveID) } } else { - util.Log.Debugf("newsame: %s", v.CveID) + util.Log.Debugf("new: %s", v.CveID) new[v.CveID] = v } } @@ -362,6 +362,21 @@ func getDiffCves(previous, current models.ScanResult) models.VulnInfos { return updated } +func isCveFixed(current models.VulnInfo, previous models.ScanResult) bool { + preVinfo, _ := previous.ScannedCves[current.CveID] + pre := map[string]bool{} + for _, h := range preVinfo.AffectedPackages { + pre[h.Name] = h.NotFixedYet + } + + cur := map[string]bool{} + for _, h := range current.AffectedPackages { + cur[h.Name] = h.NotFixedYet + } + + return !reflect.DeepEqual(pre, cur) +} + func isCveInfoUpdated(cveID string, previous, current models.ScanResult) bool { cTypes := []models.CveContentType{ models.NVD, diff --git a/report/util_test.go b/report/util_test.go index b5868a73..b169820e 100644 --- a/report/util_test.go +++ b/report/util_test.go @@ -334,3 +334,104 @@ func TestDiff(t *testing.T) { } } } + +func TestIsCveFixed(t *testing.T) { + type In struct { + v models.VulnInfo + prev models.ScanResult + } + var tests = []struct { + in In + expected bool + }{ + { + in: In{ + v: models.VulnInfo{ + CveID: "CVE-2016-6662", + AffectedPackages: models.PackageStatuses{ + { + Name: "mysql-libs", + NotFixedYet: false, + }, + }, + CveContents: models.NewCveContents( + models.CveContent{ + Type: models.NVD, + CveID: "CVE-2016-6662", + LastModified: time.Time{}, + }, + ), + }, + prev: models.ScanResult{ + ScannedCves: models.VulnInfos{ + "CVE-2016-6662": { + CveID: "CVE-2016-6662", + AffectedPackages: models.PackageStatuses{ + { + Name: "mysql-libs", + NotFixedYet: true, + }, + }, + CveContents: models.NewCveContents( + models.CveContent{ + Type: models.NVD, + CveID: "CVE-2016-6662", + LastModified: time.Time{}, + }, + ), + }, + }, + }, + }, + expected: true, + }, + { + in: In{ + v: models.VulnInfo{ + CveID: "CVE-2016-6662", + AffectedPackages: models.PackageStatuses{ + { + Name: "mysql-libs", + NotFixedYet: true, + }, + }, + CveContents: models.NewCveContents( + models.CveContent{ + Type: models.NVD, + CveID: "CVE-2016-6662", + LastModified: time.Time{}, + }, + ), + }, + prev: models.ScanResult{ + ScannedCves: models.VulnInfos{ + "CVE-2016-6662": { + CveID: "CVE-2016-6662", + AffectedPackages: models.PackageStatuses{ + { + Name: "mysql-libs", + NotFixedYet: true, + }, + }, + CveContents: models.NewCveContents( + models.CveContent{ + Type: models.NVD, + CveID: "CVE-2016-6662", + LastModified: time.Time{}, + }, + ), + }, + }, + }, + }, + expected: false, + }, + } + + for i, tt := range tests { + actual := isCveFixed(tt.in.v, tt.in.prev) + if actual != tt.expected { + t.Errorf("[%d] actual: %t, expected: %t", i, actual, tt.expected) + } + } +}