2030 lines
40 KiB
Go
2030 lines
40 KiB
Go
package models
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestTitles(t *testing.T) {
|
|
type in struct {
|
|
lang string
|
|
cont VulnInfo
|
|
}
|
|
var tests = []struct {
|
|
in in
|
|
out []CveContentStr
|
|
}{
|
|
// lang: ja
|
|
{
|
|
in: in{
|
|
lang: "ja",
|
|
cont: VulnInfo{
|
|
CveContents: CveContents{
|
|
Jvn: []CveContent{{
|
|
Type: Jvn,
|
|
Title: "Title1",
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Summary: "Summary RedHat",
|
|
}},
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Summary: "Summary NVD",
|
|
// Severity is NOT included in NVD
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
out: []CveContentStr{
|
|
{
|
|
Type: Jvn,
|
|
Value: "Title1",
|
|
},
|
|
{
|
|
Type: Nvd,
|
|
Value: "Summary NVD",
|
|
},
|
|
{
|
|
Type: RedHat,
|
|
Value: "Summary RedHat",
|
|
},
|
|
},
|
|
},
|
|
// lang: en
|
|
{
|
|
in: in{
|
|
lang: "en",
|
|
cont: VulnInfo{
|
|
CveContents: CveContents{
|
|
Jvn: []CveContent{{
|
|
Type: Jvn,
|
|
Title: "Title1",
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Summary: "Summary RedHat",
|
|
}},
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Summary: "Summary NVD",
|
|
// Severity is NOT included in NVD
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
out: []CveContentStr{
|
|
{
|
|
Type: Nvd,
|
|
Value: "Summary NVD",
|
|
},
|
|
{
|
|
Type: RedHat,
|
|
Value: "Summary RedHat",
|
|
},
|
|
},
|
|
},
|
|
// lang: empty
|
|
{
|
|
in: in{
|
|
lang: "en",
|
|
cont: VulnInfo{},
|
|
},
|
|
out: []CveContentStr{
|
|
{
|
|
Type: Unknown,
|
|
Value: "-",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for i, tt := range tests {
|
|
actual := tt.in.cont.Titles(tt.in.lang, "redhat")
|
|
if !reflect.DeepEqual(tt.out, actual) {
|
|
t.Errorf("[%d]\nexpected: %v\n actual: %v\n", i, tt.out, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSummaries(t *testing.T) {
|
|
type in struct {
|
|
lang string
|
|
cont VulnInfo
|
|
}
|
|
var tests = []struct {
|
|
in in
|
|
out []CveContentStr
|
|
}{
|
|
// lang: ja
|
|
{
|
|
in: in{
|
|
lang: "ja",
|
|
cont: VulnInfo{
|
|
CveContents: CveContents{
|
|
Jvn: []CveContent{{
|
|
Type: Jvn,
|
|
Title: "Title JVN",
|
|
Summary: "Summary JVN",
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Summary: "Summary RedHat",
|
|
}},
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Summary: "Summary NVD",
|
|
// Severity is NOT included in NVD
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
out: []CveContentStr{
|
|
{
|
|
Type: Jvn,
|
|
Value: "Title JVN\nSummary JVN",
|
|
},
|
|
{
|
|
Type: RedHat,
|
|
Value: "Summary RedHat",
|
|
},
|
|
{
|
|
Type: Nvd,
|
|
Value: "Summary NVD",
|
|
},
|
|
},
|
|
},
|
|
// lang: en
|
|
{
|
|
in: in{
|
|
lang: "en",
|
|
cont: VulnInfo{
|
|
CveContents: CveContents{
|
|
Jvn: []CveContent{{
|
|
Type: Jvn,
|
|
Title: "Title JVN",
|
|
Summary: "Summary JVN",
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Summary: "Summary RedHat",
|
|
}},
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Summary: "Summary NVD",
|
|
// Severity is NOT included in NVD
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
out: []CveContentStr{
|
|
{
|
|
Type: RedHat,
|
|
Value: "Summary RedHat",
|
|
},
|
|
{
|
|
Type: Nvd,
|
|
Value: "Summary NVD",
|
|
},
|
|
},
|
|
},
|
|
// lang: empty
|
|
{
|
|
in: in{
|
|
lang: "en",
|
|
cont: VulnInfo{},
|
|
},
|
|
out: []CveContentStr{
|
|
{
|
|
Type: Unknown,
|
|
Value: "-",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
actual := tt.in.cont.Summaries(tt.in.lang, "redhat")
|
|
if !reflect.DeepEqual(tt.out, actual) {
|
|
t.Errorf("\nexpected: %v\n actual: %v\n", tt.out, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCountGroupBySeverity(t *testing.T) {
|
|
var tests = []struct {
|
|
in VulnInfos
|
|
out map[string]int
|
|
}{
|
|
{
|
|
in: VulnInfos{
|
|
"CVE-2017-0002": {
|
|
CveID: "CVE-2017-0002",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss3Score: 6.0,
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Score: 7.0,
|
|
}},
|
|
},
|
|
},
|
|
"CVE-2017-0003": {
|
|
CveID: "CVE-2017-0003",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss3Score: 2.0,
|
|
}},
|
|
},
|
|
},
|
|
"CVE-2017-0004": {
|
|
CveID: "CVE-2017-0004",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss3Score: 5.0,
|
|
}},
|
|
},
|
|
},
|
|
"CVE-2017-0005": {
|
|
CveID: "CVE-2017-0005",
|
|
},
|
|
"CVE-2017-0006": {
|
|
CveID: "CVE-2017-0005",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss3Score: 10.0,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
out: map[string]int{
|
|
"Critical": 1,
|
|
"High": 1,
|
|
"Medium": 1,
|
|
"Low": 1,
|
|
"Unknown": 1,
|
|
},
|
|
},
|
|
{
|
|
in: VulnInfos{
|
|
"CVE-2017-0002": {
|
|
CveID: "CVE-2017-0002",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 1.0,
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Score: 7.0,
|
|
}},
|
|
},
|
|
},
|
|
"CVE-2017-0003": {
|
|
CveID: "CVE-2017-0003",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 2.0,
|
|
}},
|
|
},
|
|
},
|
|
"CVE-2017-0004": {
|
|
CveID: "CVE-2017-0004",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 5.0,
|
|
}},
|
|
},
|
|
},
|
|
"CVE-2017-0005": {
|
|
CveID: "CVE-2017-0005",
|
|
},
|
|
"CVE-2017-0006": {
|
|
CveID: "CVE-2017-0005",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 10.0,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
out: map[string]int{
|
|
"Critical": 1,
|
|
"High": 1,
|
|
"Medium": 1,
|
|
"Low": 1,
|
|
"Unknown": 1,
|
|
},
|
|
},
|
|
}
|
|
for i, tt := range tests {
|
|
actual := tt.in.CountGroupBySeverity()
|
|
for k := range tt.out {
|
|
if tt.out[k] != actual[k] {
|
|
t.Errorf("[%d]\nexpected %s: %d\n actual %d\n",
|
|
i, k, tt.out[k], actual[k])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestToSortedSlice(t *testing.T) {
|
|
var tests = []struct {
|
|
in VulnInfos
|
|
out []VulnInfo
|
|
}{
|
|
//0
|
|
{
|
|
in: VulnInfos{
|
|
"CVE-2017-0002": {
|
|
CveID: "CVE-2017-0002",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 6.0,
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Score: 7.0,
|
|
}},
|
|
},
|
|
},
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 7.0,
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Score: 8.0,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
out: []VulnInfo{
|
|
{
|
|
CveID: "CVE-2017-0001",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 7.0,
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Score: 8.0,
|
|
}},
|
|
},
|
|
},
|
|
{
|
|
CveID: "CVE-2017-0002",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 6.0,
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Score: 7.0,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
//[1] When max scores are the same, sort by CVE-ID
|
|
{
|
|
in: VulnInfos{
|
|
"CVE-2017-0002": {
|
|
CveID: "CVE-2017-0002",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 6.0,
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Score: 7.0,
|
|
}},
|
|
},
|
|
},
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
CveContents: CveContents{
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Score: 7.0,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
out: []VulnInfo{
|
|
{
|
|
CveID: "CVE-2017-0001",
|
|
CveContents: CveContents{
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Score: 7.0,
|
|
}},
|
|
},
|
|
},
|
|
{
|
|
CveID: "CVE-2017-0002",
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 6.0,
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Score: 7.0,
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
//[2] When there are no cvss scores, sort by severity
|
|
{
|
|
in: VulnInfos{
|
|
"CVE-2017-0002": {
|
|
CveID: "CVE-2017-0002",
|
|
CveContents: CveContents{
|
|
Ubuntu: []CveContent{{
|
|
Type: Ubuntu,
|
|
Cvss3Severity: "High",
|
|
}},
|
|
},
|
|
},
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
CveContents: CveContents{
|
|
Ubuntu: []CveContent{{
|
|
Type: Ubuntu,
|
|
Cvss3Severity: "Low",
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
out: []VulnInfo{
|
|
{
|
|
CveID: "CVE-2017-0002",
|
|
CveContents: CveContents{
|
|
Ubuntu: []CveContent{{
|
|
Type: Ubuntu,
|
|
Cvss3Severity: "High",
|
|
}},
|
|
},
|
|
},
|
|
{
|
|
CveID: "CVE-2017-0001",
|
|
CveContents: CveContents{
|
|
Ubuntu: []CveContent{{
|
|
Type: Ubuntu,
|
|
Cvss3Severity: "Low",
|
|
}},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for i, tt := range tests {
|
|
actual := tt.in.ToSortedSlice()
|
|
if !reflect.DeepEqual(tt.out, actual) {
|
|
t.Errorf("[%d]\nexpected: %v\n actual: %v\n", i, tt.out, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCvss2Scores(t *testing.T) {
|
|
var tests = []struct {
|
|
in VulnInfo
|
|
out []CveContentCvss
|
|
}{
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
Jvn: []CveContent{{
|
|
Type: Jvn,
|
|
Cvss2Severity: "HIGH",
|
|
Cvss2Score: 8.2,
|
|
Cvss2Vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss2Severity: "HIGH",
|
|
Cvss2Score: 8.0,
|
|
Cvss2Vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
|
|
}},
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 8.1,
|
|
Cvss2Vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
|
|
Cvss2Severity: "HIGH",
|
|
}},
|
|
//v3
|
|
RedHatAPI: []CveContent{{
|
|
Type: RedHatAPI,
|
|
Cvss3Score: 8.1,
|
|
Cvss3Vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
|
|
Cvss3Severity: "HIGH",
|
|
}},
|
|
},
|
|
},
|
|
out: []CveContentCvss{
|
|
{
|
|
Type: RedHat,
|
|
Value: Cvss{
|
|
Type: CVSS2,
|
|
Score: 8.0,
|
|
Vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
|
|
Severity: "HIGH",
|
|
},
|
|
},
|
|
{
|
|
Type: Nvd,
|
|
Value: Cvss{
|
|
Type: CVSS2,
|
|
Score: 8.1,
|
|
Vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
|
|
Severity: "HIGH",
|
|
},
|
|
},
|
|
{
|
|
Type: Jvn,
|
|
Value: Cvss{
|
|
Type: CVSS2,
|
|
Score: 8.2,
|
|
Vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
|
|
Severity: "HIGH",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
// Empty
|
|
{
|
|
in: VulnInfo{},
|
|
out: nil,
|
|
},
|
|
}
|
|
for i, tt := range tests {
|
|
actual := tt.in.Cvss2Scores()
|
|
if !reflect.DeepEqual(tt.out, actual) {
|
|
t.Errorf("[%d]\nexpected: %v\n actual: %v\n", i, tt.out, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMaxCvss2Scores(t *testing.T) {
|
|
var tests = []struct {
|
|
in VulnInfo
|
|
out CveContentCvss
|
|
}{
|
|
// 0
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
Jvn: []CveContent{{
|
|
Type: Jvn,
|
|
Cvss2Severity: "HIGH",
|
|
Cvss2Score: 8.2,
|
|
Cvss2Vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss2Severity: "HIGH",
|
|
Cvss2Score: 8.0,
|
|
Cvss2Vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
|
|
}},
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 8.1,
|
|
Cvss2Vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
|
|
// Severity is NOT included in NVD
|
|
}},
|
|
},
|
|
},
|
|
out: CveContentCvss{
|
|
Type: Jvn,
|
|
Value: Cvss{
|
|
Type: CVSS2,
|
|
Score: 8.2,
|
|
Vector: "AV:N/AC:L/Au:N/C:N/I:N/A:P",
|
|
Severity: "HIGH",
|
|
},
|
|
},
|
|
},
|
|
// Empty
|
|
{
|
|
in: VulnInfo{},
|
|
out: CveContentCvss{
|
|
Type: Unknown,
|
|
Value: Cvss{
|
|
Type: CVSS2,
|
|
Score: 0.0,
|
|
Vector: "",
|
|
Severity: "",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for i, tt := range tests {
|
|
actual := tt.in.MaxCvss2Score()
|
|
if !reflect.DeepEqual(tt.out, actual) {
|
|
t.Errorf("[%d] expected: %v\n actual: %v\n", i, tt.out, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCvss3Scores(t *testing.T) {
|
|
var tests = []struct {
|
|
in VulnInfo
|
|
out []CveContentCvss
|
|
}{
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Severity: "HIGH",
|
|
Cvss3Score: 8.0,
|
|
Cvss3Vector: "AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L",
|
|
}},
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 8.1,
|
|
Cvss2Vector: "AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L",
|
|
Cvss2Severity: "HIGH",
|
|
}},
|
|
},
|
|
},
|
|
out: []CveContentCvss{
|
|
{
|
|
Type: RedHat,
|
|
Value: Cvss{
|
|
Type: CVSS3,
|
|
Score: 8.0,
|
|
Vector: "AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L",
|
|
Severity: "HIGH",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
// [1] Severity in OVAL
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
Ubuntu: []CveContent{{
|
|
Type: Ubuntu,
|
|
Cvss3Severity: "HIGH",
|
|
}},
|
|
},
|
|
},
|
|
out: []CveContentCvss{
|
|
{
|
|
Type: Ubuntu,
|
|
Value: Cvss{
|
|
Type: CVSS3,
|
|
Score: 8.9,
|
|
CalculatedBySeverity: true,
|
|
Severity: "HIGH",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
// [2] Multiple Severities in Debian Security Tracker
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
DebianSecurityTracker: []CveContent{{
|
|
Type: DebianSecurityTracker,
|
|
Cvss3Severity: "not yet assigned|low",
|
|
}},
|
|
},
|
|
},
|
|
out: []CveContentCvss{{
|
|
Type: DebianSecurityTracker,
|
|
Value: Cvss{
|
|
Type: CVSS3,
|
|
Score: 3.9,
|
|
CalculatedBySeverity: true,
|
|
Severity: "NOT YET ASSIGNED|LOW",
|
|
},
|
|
}},
|
|
},
|
|
// Empty
|
|
{
|
|
in: VulnInfo{},
|
|
out: nil,
|
|
},
|
|
}
|
|
for i, tt := range tests {
|
|
actual := tt.in.Cvss3Scores()
|
|
if !reflect.DeepEqual(tt.out, actual) {
|
|
t.Errorf("[%d]\nexpected: %v\n actual: %v\n", i, tt.out, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMaxCvss3Scores(t *testing.T) {
|
|
var tests = []struct {
|
|
in VulnInfo
|
|
out CveContentCvss
|
|
}{
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Severity: "HIGH",
|
|
Cvss3Score: 8.0,
|
|
Cvss3Vector: "AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L",
|
|
}},
|
|
},
|
|
},
|
|
out: CveContentCvss{
|
|
Type: RedHat,
|
|
Value: Cvss{
|
|
Type: CVSS3,
|
|
Score: 8.0,
|
|
Vector: "AV:N/AC:H/PR:N/UI:N/S:U/C:L/I:L/A:L",
|
|
Severity: "HIGH",
|
|
},
|
|
},
|
|
},
|
|
// Empty
|
|
{
|
|
in: VulnInfo{},
|
|
out: CveContentCvss{
|
|
Type: Unknown,
|
|
Value: Cvss{
|
|
Type: CVSS3,
|
|
Score: 0.0,
|
|
Vector: "",
|
|
Severity: "",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
actual := tt.in.MaxCvss3Score()
|
|
if !reflect.DeepEqual(tt.out, actual) {
|
|
t.Errorf("\nexpected: %v\n actual: %v\n", tt.out, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestMaxCvssScores(t *testing.T) {
|
|
var tests = []struct {
|
|
in VulnInfo
|
|
out CveContentCvss
|
|
}{
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss3Score: 7.0,
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss2Score: 8.0,
|
|
}},
|
|
},
|
|
},
|
|
out: CveContentCvss{
|
|
Type: Nvd,
|
|
Value: Cvss{
|
|
Type: CVSS3,
|
|
Score: 7.0,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Score: 8.0,
|
|
}},
|
|
},
|
|
},
|
|
out: CveContentCvss{
|
|
Type: RedHat,
|
|
Value: Cvss{
|
|
Type: CVSS3,
|
|
Score: 8.0,
|
|
},
|
|
},
|
|
},
|
|
//2
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
Ubuntu: []CveContent{{
|
|
Type: Ubuntu,
|
|
Cvss3Severity: "HIGH",
|
|
}},
|
|
},
|
|
},
|
|
out: CveContentCvss{
|
|
Type: Ubuntu,
|
|
Value: Cvss{
|
|
Type: CVSS3,
|
|
Score: 8.9,
|
|
CalculatedBySeverity: true,
|
|
Severity: "HIGH",
|
|
},
|
|
},
|
|
},
|
|
//3
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
Ubuntu: []CveContent{{
|
|
Type: Ubuntu,
|
|
Cvss3Severity: "MEDIUM",
|
|
}},
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 7.0,
|
|
Cvss2Severity: "HIGH",
|
|
}},
|
|
},
|
|
},
|
|
out: CveContentCvss{
|
|
Type: Ubuntu,
|
|
Value: Cvss{
|
|
Type: CVSS3,
|
|
Score: 6.9,
|
|
Severity: "MEDIUM",
|
|
CalculatedBySeverity: true,
|
|
},
|
|
},
|
|
},
|
|
//4
|
|
{
|
|
in: VulnInfo{
|
|
DistroAdvisories: []DistroAdvisory{
|
|
{
|
|
Severity: "HIGH",
|
|
},
|
|
},
|
|
},
|
|
out: CveContentCvss{
|
|
Type: "Vendor",
|
|
Value: Cvss{
|
|
Type: CVSS3,
|
|
Score: 8.9,
|
|
CalculatedBySeverity: true,
|
|
Severity: "HIGH",
|
|
},
|
|
},
|
|
},
|
|
//5
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
Ubuntu: []CveContent{{
|
|
Type: Ubuntu,
|
|
Cvss3Severity: "MEDIUM",
|
|
}},
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 4.0,
|
|
Cvss2Severity: "MEDIUM",
|
|
}},
|
|
},
|
|
DistroAdvisories: []DistroAdvisory{
|
|
{
|
|
Severity: "HIGH",
|
|
},
|
|
},
|
|
},
|
|
out: CveContentCvss{
|
|
Type: "Vendor",
|
|
Value: Cvss{
|
|
Type: CVSS3,
|
|
Score: 8.9,
|
|
Severity: "HIGH",
|
|
CalculatedBySeverity: true,
|
|
},
|
|
},
|
|
},
|
|
// 6 : CVSSv4.0 and CVSSv3.1
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
Mitre: []CveContent{
|
|
{
|
|
Type: Mitre,
|
|
Cvss40Score: 6.9,
|
|
Cvss40Vector: "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
|
|
Cvss40Severity: "MEDIUM",
|
|
Cvss3Score: 7.3,
|
|
Cvss3Vector: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
|
|
Cvss3Severity: "HIGH",
|
|
Optional: map[string]string{"source": "CNA"},
|
|
},
|
|
},
|
|
Nvd: []CveContent{
|
|
{
|
|
Type: Nvd,
|
|
Cvss3Score: 9.8,
|
|
Cvss3Vector: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
|
|
Cvss3Severity: "CRITICAL",
|
|
Optional: map[string]string{"source": "nvd@nist.gov"},
|
|
},
|
|
{
|
|
Type: Nvd,
|
|
Cvss3Score: 7.3,
|
|
Cvss3Vector: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
|
|
Cvss3Severity: "HIGH",
|
|
Optional: map[string]string{"source": "cna@vuldb.com"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
out: CveContentCvss{
|
|
Type: Mitre,
|
|
Value: Cvss{
|
|
Type: CVSS40,
|
|
Score: 6.9,
|
|
Severity: "MEDIUM",
|
|
Vector: "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
|
|
},
|
|
},
|
|
},
|
|
// Empty
|
|
{
|
|
in: VulnInfo{},
|
|
out: CveContentCvss{
|
|
Type: Unknown,
|
|
Value: Cvss{
|
|
Type: CVSS2,
|
|
Score: 0,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for i, tt := range tests {
|
|
actual := tt.in.MaxCvssScore()
|
|
if !reflect.DeepEqual(tt.out, actual) {
|
|
t.Errorf("\n[%d] expected: %v\n actual: %v\n", i, tt.out, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFormatMaxCvssScore(t *testing.T) {
|
|
var tests = []struct {
|
|
in VulnInfo
|
|
out string
|
|
}{
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
Jvn: []CveContent{{
|
|
Type: Jvn,
|
|
Cvss2Severity: "HIGH",
|
|
Cvss2Score: 8.3,
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss3Severity: "HIGH",
|
|
Cvss3Score: 8.0,
|
|
}},
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 8.1,
|
|
// Severity is NOT included in NVD
|
|
}},
|
|
},
|
|
},
|
|
out: "8.0 HIGH (redhat)",
|
|
},
|
|
{
|
|
in: VulnInfo{
|
|
CveContents: CveContents{
|
|
Jvn: []CveContent{{
|
|
Type: Jvn,
|
|
Cvss2Severity: "HIGH",
|
|
Cvss2Score: 8.3,
|
|
}},
|
|
RedHat: []CveContent{{
|
|
Type: RedHat,
|
|
Cvss2Severity: "HIGH",
|
|
Cvss2Score: 8.0,
|
|
Cvss3Severity: "HIGH",
|
|
Cvss3Score: 9.9,
|
|
}},
|
|
Nvd: []CveContent{{
|
|
Type: Nvd,
|
|
Cvss2Score: 8.1,
|
|
}},
|
|
},
|
|
},
|
|
out: "9.9 HIGH (redhat)",
|
|
},
|
|
}
|
|
for i, tt := range tests {
|
|
actual := tt.in.FormatMaxCvssScore()
|
|
if !reflect.DeepEqual(tt.out, actual) {
|
|
t.Errorf("[%d]\nexpected: %v\n actual: %v\n", i, tt.out, actual)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSortPackageStatues(t *testing.T) {
|
|
var tests = []struct {
|
|
in PackageFixStatuses
|
|
out PackageFixStatuses
|
|
}{
|
|
{
|
|
in: PackageFixStatuses{
|
|
{Name: "b"},
|
|
{Name: "a"},
|
|
},
|
|
out: PackageFixStatuses{
|
|
{Name: "a"},
|
|
{Name: "b"},
|
|
},
|
|
},
|
|
{
|
|
in: PackageFixStatuses{
|
|
{
|
|
Name: "libzstd1",
|
|
FixedIn: "1.3.1+dfsg-1~ubuntu0.16.04.1+esm1",
|
|
},
|
|
{
|
|
Name: "libzstd1",
|
|
FixedIn: "1.3.1+dfsg-1~ubuntu0.16.04.1+esm2",
|
|
},
|
|
},
|
|
out: PackageFixStatuses{
|
|
{
|
|
Name: "libzstd1",
|
|
FixedIn: "1.3.1+dfsg-1~ubuntu0.16.04.1+esm2",
|
|
},
|
|
{
|
|
Name: "libzstd1",
|
|
FixedIn: "1.3.1+dfsg-1~ubuntu0.16.04.1+esm1",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tt.in.Sort()
|
|
if !reflect.DeepEqual(tt.in, tt.out) {
|
|
t.Errorf("\nexpected: %v\n actual: %v\n", tt.out, tt.in)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestStorePackageStatuses(t *testing.T) {
|
|
var tests = []struct {
|
|
pkgstats PackageFixStatuses
|
|
in PackageFixStatus
|
|
out PackageFixStatuses
|
|
}{
|
|
{
|
|
pkgstats: PackageFixStatuses{
|
|
{Name: "a"},
|
|
{Name: "b"},
|
|
},
|
|
in: PackageFixStatus{
|
|
Name: "c",
|
|
},
|
|
out: PackageFixStatuses{
|
|
{Name: "a"},
|
|
{Name: "b"},
|
|
{Name: "c"},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
out := tt.pkgstats.Store(tt.in)
|
|
if ok := reflect.DeepEqual(tt.out, out); !ok {
|
|
t.Errorf("\nexpected: %v\n actual: %v\n", tt.out, out)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestAppendIfMissing(t *testing.T) {
|
|
var tests = []struct {
|
|
in Confidences
|
|
arg Confidence
|
|
out Confidences
|
|
}{
|
|
{
|
|
in: Confidences{
|
|
NvdExactVersionMatch,
|
|
},
|
|
arg: NvdExactVersionMatch,
|
|
out: Confidences{
|
|
NvdExactVersionMatch,
|
|
},
|
|
},
|
|
{
|
|
in: Confidences{
|
|
NvdExactVersionMatch,
|
|
},
|
|
arg: ChangelogExactMatch,
|
|
out: Confidences{
|
|
NvdExactVersionMatch,
|
|
ChangelogExactMatch,
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
tt.in.AppendIfMissing(tt.arg)
|
|
if !reflect.DeepEqual(tt.in, tt.out) {
|
|
t.Errorf("\nexpected: %v\n actual: %v\n", tt.out, tt.in)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestSortByConfident(t *testing.T) {
|
|
var tests = []struct {
|
|
in Confidences
|
|
out Confidences
|
|
}{
|
|
{
|
|
in: Confidences{
|
|
OvalMatch,
|
|
NvdExactVersionMatch,
|
|
},
|
|
out: Confidences{
|
|
OvalMatch,
|
|
NvdExactVersionMatch,
|
|
},
|
|
},
|
|
{
|
|
in: Confidences{
|
|
NvdExactVersionMatch,
|
|
OvalMatch,
|
|
},
|
|
out: Confidences{
|
|
OvalMatch,
|
|
NvdExactVersionMatch,
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
act := tt.in.SortByConfident()
|
|
if !reflect.DeepEqual(tt.out, act) {
|
|
t.Errorf("\nexpected: %v\n actual: %v\n", tt.out, act)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestDistroAdvisories_AppendIfMissing(t *testing.T) {
|
|
type args struct {
|
|
adv *DistroAdvisory
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
advs DistroAdvisories
|
|
args args
|
|
want bool
|
|
after DistroAdvisories
|
|
}{
|
|
{
|
|
name: "duplicate no append",
|
|
advs: DistroAdvisories{
|
|
DistroAdvisory{
|
|
AdvisoryID: "ALASs-2019-1214",
|
|
}},
|
|
args: args{
|
|
adv: &DistroAdvisory{
|
|
AdvisoryID: "ALASs-2019-1214",
|
|
},
|
|
},
|
|
want: false,
|
|
after: DistroAdvisories{
|
|
DistroAdvisory{
|
|
AdvisoryID: "ALASs-2019-1214",
|
|
}},
|
|
},
|
|
{
|
|
name: "append",
|
|
advs: DistroAdvisories{
|
|
DistroAdvisory{
|
|
AdvisoryID: "ALASs-2019-1214",
|
|
}},
|
|
args: args{
|
|
adv: &DistroAdvisory{
|
|
AdvisoryID: "ALASs-2019-1215",
|
|
},
|
|
},
|
|
want: true,
|
|
after: DistroAdvisories{
|
|
{
|
|
AdvisoryID: "ALASs-2019-1214",
|
|
},
|
|
{
|
|
AdvisoryID: "ALASs-2019-1215",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := tt.advs.AppendIfMissing(tt.args.adv); got != tt.want {
|
|
t.Errorf("DistroAdvisories.AppendIfMissing() = %v, want %v", got, tt.want)
|
|
}
|
|
if !reflect.DeepEqual(tt.advs, tt.after) {
|
|
t.Errorf("\nexpected: %v\n actual: %v\n", tt.after, tt.advs)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVulnInfo_AttackVector(t *testing.T) {
|
|
type fields struct {
|
|
CveContents CveContents
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
want string
|
|
}{
|
|
{
|
|
name: "2.0:N",
|
|
fields: fields{
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: "foo",
|
|
Cvss2Vector: "AV:N/AC:L/Au:N/C:C/I:C/A:C",
|
|
},
|
|
),
|
|
},
|
|
want: "AV:N",
|
|
},
|
|
{
|
|
name: "2.0:A",
|
|
fields: fields{
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: "foo",
|
|
Cvss2Vector: "AV:A/AC:L/Au:N/C:C/I:C/A:C",
|
|
},
|
|
),
|
|
},
|
|
want: "AV:A",
|
|
},
|
|
{
|
|
name: "2.0:L",
|
|
fields: fields{
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: "foo",
|
|
Cvss2Vector: "AV:L/AC:L/Au:N/C:C/I:C/A:C",
|
|
},
|
|
),
|
|
},
|
|
want: "AV:L",
|
|
},
|
|
|
|
{
|
|
name: "3.0:N",
|
|
fields: fields{
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: "foo",
|
|
Cvss3Vector: "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
|
|
},
|
|
),
|
|
},
|
|
want: "AV:N",
|
|
},
|
|
{
|
|
name: "3.1:N",
|
|
fields: fields{
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: "foo",
|
|
Cvss3Vector: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H",
|
|
},
|
|
),
|
|
},
|
|
want: "AV:N",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
v := VulnInfo{
|
|
CveContents: tt.fields.CveContents,
|
|
}
|
|
if got := v.AttackVector(); got != tt.want {
|
|
t.Errorf("VulnInfo.AttackVector() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVulnInfos_FilterByCvssOver(t *testing.T) {
|
|
type args struct {
|
|
over float64
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
v VulnInfos
|
|
args args
|
|
want VulnInfos
|
|
nwant int
|
|
}{
|
|
{
|
|
name: "over 7.0",
|
|
args: args{over: 7.0},
|
|
v: VulnInfos{
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: Nvd,
|
|
CveID: "CVE-2017-0001",
|
|
Cvss2Score: 7.1,
|
|
LastModified: time.Time{},
|
|
},
|
|
),
|
|
},
|
|
"CVE-2017-0002": {
|
|
CveID: "CVE-2017-0002",
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: Nvd,
|
|
CveID: "CVE-2017-0002",
|
|
Cvss2Score: 6.9,
|
|
LastModified: time.Time{},
|
|
},
|
|
),
|
|
},
|
|
"CVE-2017-0003": {
|
|
CveID: "CVE-2017-0003",
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: Nvd,
|
|
CveID: "CVE-2017-0003",
|
|
Cvss2Score: 6.9,
|
|
LastModified: time.Time{},
|
|
},
|
|
CveContent{
|
|
Type: Jvn,
|
|
CveID: "CVE-2017-0003",
|
|
Cvss2Score: 7.2,
|
|
LastModified: time.Time{},
|
|
},
|
|
),
|
|
},
|
|
},
|
|
nwant: 1,
|
|
want: VulnInfos{
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: Nvd,
|
|
CveID: "CVE-2017-0001",
|
|
Cvss2Score: 7.1,
|
|
LastModified: time.Time{},
|
|
},
|
|
),
|
|
},
|
|
"CVE-2017-0003": {
|
|
CveID: "CVE-2017-0003",
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: Nvd,
|
|
CveID: "CVE-2017-0003",
|
|
Cvss2Score: 6.9,
|
|
LastModified: time.Time{},
|
|
},
|
|
CveContent{
|
|
Type: Jvn,
|
|
CveID: "CVE-2017-0003",
|
|
Cvss2Score: 7.2,
|
|
LastModified: time.Time{},
|
|
},
|
|
),
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "over high",
|
|
args: args{over: 7.0},
|
|
v: VulnInfos{
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: Ubuntu,
|
|
CveID: "CVE-2017-0001",
|
|
Cvss3Severity: "HIGH",
|
|
LastModified: time.Time{},
|
|
},
|
|
),
|
|
},
|
|
"CVE-2017-0002": {
|
|
CveID: "CVE-2017-0002",
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: Debian,
|
|
CveID: "CVE-2017-0002",
|
|
Cvss3Severity: "CRITICAL",
|
|
LastModified: time.Time{},
|
|
},
|
|
),
|
|
},
|
|
"CVE-2017-0003": {
|
|
CveID: "CVE-2017-0003",
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: GitHub,
|
|
CveID: "CVE-2017-0003",
|
|
Cvss3Severity: "IMPORTANT",
|
|
LastModified: time.Time{},
|
|
},
|
|
),
|
|
},
|
|
},
|
|
want: VulnInfos{
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: Ubuntu,
|
|
CveID: "CVE-2017-0001",
|
|
Cvss3Severity: "HIGH",
|
|
LastModified: time.Time{},
|
|
},
|
|
),
|
|
},
|
|
"CVE-2017-0002": {
|
|
CveID: "CVE-2017-0002",
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: Debian,
|
|
CveID: "CVE-2017-0002",
|
|
Cvss3Severity: "CRITICAL",
|
|
LastModified: time.Time{},
|
|
},
|
|
),
|
|
},
|
|
"CVE-2017-0003": {
|
|
CveID: "CVE-2017-0003",
|
|
CveContents: NewCveContents(
|
|
CveContent{
|
|
Type: GitHub,
|
|
CveID: "CVE-2017-0003",
|
|
Cvss3Severity: "IMPORTANT",
|
|
LastModified: time.Time{},
|
|
},
|
|
),
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, ngot := tt.v.FilterByCvssOver(tt.args.over)
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("VulnInfos.FindByCvssOver() = %v, want %v", got, tt.want)
|
|
}
|
|
if ngot != tt.nwant {
|
|
t.Errorf("VulnInfos.FindByCvssOver() = %d, want %d", ngot, tt.nwant)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVulnInfos_FilterIgnoreCves(t *testing.T) {
|
|
type args struct {
|
|
ignoreCveIDs []string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
v VulnInfos
|
|
args args
|
|
want VulnInfos
|
|
nwant int
|
|
}{
|
|
{
|
|
name: "filter ignored",
|
|
args: args{ignoreCveIDs: []string{"CVE-2017-0002"}},
|
|
v: VulnInfos{
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
},
|
|
"CVE-2017-0002": {
|
|
CveID: "CVE-2017-0002",
|
|
},
|
|
"CVE-2017-0003": {
|
|
CveID: "CVE-2017-0003",
|
|
},
|
|
},
|
|
nwant: 1,
|
|
want: VulnInfos{
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
},
|
|
"CVE-2017-0003": {
|
|
CveID: "CVE-2017-0003",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, ngot := tt.v.FilterIgnoreCves(tt.args.ignoreCveIDs)
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("VulnInfos.FindIgnoreCves() = %v, want %v", got, tt.want)
|
|
}
|
|
if ngot != tt.nwant {
|
|
t.Errorf("VulnInfos.FindByCvssOver() = %d, want %d", ngot, tt.nwant)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVulnInfos_FilterUnfixed(t *testing.T) {
|
|
type args struct {
|
|
ignoreUnfixed bool
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
v VulnInfos
|
|
args args
|
|
want VulnInfos
|
|
nwant int
|
|
}{
|
|
{
|
|
name: "filter ok",
|
|
args: args{ignoreUnfixed: true},
|
|
v: VulnInfos{
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
AffectedPackages: PackageFixStatuses{
|
|
{
|
|
Name: "a",
|
|
NotFixedYet: true,
|
|
},
|
|
},
|
|
},
|
|
"CVE-2017-0002": {
|
|
CveID: "CVE-2017-0002",
|
|
AffectedPackages: PackageFixStatuses{
|
|
{
|
|
Name: "b",
|
|
NotFixedYet: false,
|
|
},
|
|
},
|
|
},
|
|
"CVE-2017-0003": {
|
|
CveID: "CVE-2017-0003",
|
|
AffectedPackages: PackageFixStatuses{
|
|
{
|
|
Name: "c",
|
|
NotFixedYet: true,
|
|
},
|
|
{
|
|
Name: "d",
|
|
NotFixedYet: false,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
nwant: 1,
|
|
want: VulnInfos{
|
|
"CVE-2017-0002": {
|
|
CveID: "CVE-2017-0002",
|
|
AffectedPackages: PackageFixStatuses{
|
|
{
|
|
Name: "b",
|
|
NotFixedYet: false,
|
|
},
|
|
},
|
|
},
|
|
"CVE-2017-0003": {
|
|
CveID: "CVE-2017-0003",
|
|
AffectedPackages: PackageFixStatuses{
|
|
{
|
|
Name: "c",
|
|
NotFixedYet: true,
|
|
},
|
|
{
|
|
Name: "d",
|
|
NotFixedYet: false,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, ngot := tt.v.FilterUnfixed(tt.args.ignoreUnfixed)
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("VulnInfos.FilterUnfixed() = %v, want %v", got, tt.want)
|
|
}
|
|
if ngot != tt.nwant {
|
|
t.Errorf("VulnInfos.FindByCvssOver() = %d, want %d", ngot, tt.nwant)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVulnInfos_FilterIgnorePkgs(t *testing.T) {
|
|
type args struct {
|
|
ignorePkgsRegexps []string
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
v VulnInfos
|
|
args args
|
|
want VulnInfos
|
|
nwant int
|
|
}{
|
|
{
|
|
name: "filter pkgs 1",
|
|
args: args{ignorePkgsRegexps: []string{"^kernel"}},
|
|
v: VulnInfos{
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
AffectedPackages: PackageFixStatuses{
|
|
{Name: "kernel"},
|
|
},
|
|
},
|
|
"CVE-2017-0002": {
|
|
CveID: "CVE-2017-0002",
|
|
},
|
|
},
|
|
nwant: 1,
|
|
want: VulnInfos{
|
|
"CVE-2017-0002": {
|
|
CveID: "CVE-2017-0002",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "filter pkgs 2",
|
|
args: args{ignorePkgsRegexps: []string{"^kernel"}},
|
|
v: VulnInfos{
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
AffectedPackages: PackageFixStatuses{
|
|
{Name: "kernel"},
|
|
{Name: "vim"},
|
|
},
|
|
},
|
|
},
|
|
nwant: 0,
|
|
want: VulnInfos{
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
AffectedPackages: PackageFixStatuses{
|
|
{Name: "kernel"},
|
|
{Name: "vim"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "filter pkgs 3",
|
|
args: args{ignorePkgsRegexps: []string{"^kernel", "^vim", "^bind"}},
|
|
v: VulnInfos{
|
|
"CVE-2017-0001": {
|
|
CveID: "CVE-2017-0001",
|
|
AffectedPackages: PackageFixStatuses{
|
|
{Name: "kernel"},
|
|
{Name: "vim"},
|
|
},
|
|
},
|
|
},
|
|
nwant: 1,
|
|
want: VulnInfos{},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, ngot := tt.v.FilterIgnorePkgs(tt.args.ignorePkgsRegexps)
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("VulnInfos.FilterIgnorePkgs() = %v, want %v", got, tt.want)
|
|
}
|
|
if ngot != tt.nwant {
|
|
t.Errorf("VulnInfos.FilterIgnorePkgs() = %d, want %d", ngot, tt.nwant)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVulnInfos_FilterByConfidenceOver(t *testing.T) {
|
|
type args struct {
|
|
over int
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
v VulnInfos
|
|
args args
|
|
want VulnInfos
|
|
nwant int
|
|
}{
|
|
{
|
|
name: "over 0",
|
|
v: map[string]VulnInfo{
|
|
"CVE-2021-1111": {
|
|
CveID: "CVE-2021-1111",
|
|
Confidences: Confidences{JvnVendorProductMatch},
|
|
},
|
|
},
|
|
args: args{
|
|
over: 0,
|
|
},
|
|
want: map[string]VulnInfo{
|
|
"CVE-2021-1111": {
|
|
CveID: "CVE-2021-1111",
|
|
Confidences: Confidences{JvnVendorProductMatch},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "over 20",
|
|
v: map[string]VulnInfo{
|
|
"CVE-2021-1111": {
|
|
CveID: "CVE-2021-1111",
|
|
Confidences: Confidences{JvnVendorProductMatch},
|
|
},
|
|
},
|
|
args: args{
|
|
over: 20,
|
|
},
|
|
nwant: 1,
|
|
want: map[string]VulnInfo{},
|
|
},
|
|
{
|
|
name: "over 100",
|
|
v: map[string]VulnInfo{
|
|
"CVE-2021-1111": {
|
|
CveID: "CVE-2021-1111",
|
|
Confidences: Confidences{
|
|
NvdExactVersionMatch,
|
|
JvnVendorProductMatch,
|
|
},
|
|
},
|
|
},
|
|
args: args{
|
|
over: 20,
|
|
},
|
|
want: map[string]VulnInfo{
|
|
"CVE-2021-1111": {
|
|
CveID: "CVE-2021-1111",
|
|
Confidences: Confidences{
|
|
NvdExactVersionMatch,
|
|
JvnVendorProductMatch,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, ngot := tt.v.FilterByConfidenceOver(tt.args.over)
|
|
if !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("VulnInfos.FilterByConfidenceOver() = %v, want %v", got, tt.want)
|
|
}
|
|
if ngot != tt.nwant {
|
|
t.Errorf("VulnInfos.FilterByConfidenceOver() = %d, want %d", ngot, tt.nwant)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVulnInfo_PatchStatus(t *testing.T) {
|
|
type fields struct {
|
|
Confidences Confidences
|
|
AffectedPackages PackageFixStatuses
|
|
CpeURIs []string
|
|
WindowsKBFixedIns []string
|
|
}
|
|
type args struct {
|
|
packs Packages
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
args args
|
|
want string
|
|
}{
|
|
{
|
|
name: "cpe",
|
|
fields: fields{
|
|
CpeURIs: []string{"cpe:/a:microsoft:internet_explorer:10"},
|
|
},
|
|
want: "",
|
|
},
|
|
{
|
|
name: "package unfixed",
|
|
fields: fields{
|
|
AffectedPackages: PackageFixStatuses{
|
|
{
|
|
Name: "bash",
|
|
NotFixedYet: true,
|
|
},
|
|
},
|
|
},
|
|
want: "unfixed",
|
|
},
|
|
{
|
|
name: "package unknown",
|
|
fields: fields{
|
|
AffectedPackages: PackageFixStatuses{
|
|
{
|
|
Name: "bash",
|
|
},
|
|
},
|
|
},
|
|
args: args{
|
|
packs: Packages{"bash": {
|
|
Name: "bash",
|
|
}},
|
|
},
|
|
want: "unknown",
|
|
},
|
|
{
|
|
name: "package fixed",
|
|
fields: fields{
|
|
AffectedPackages: PackageFixStatuses{
|
|
{
|
|
Name: "bash",
|
|
},
|
|
},
|
|
},
|
|
args: args{
|
|
packs: Packages{"bash": {
|
|
Name: "bash",
|
|
Version: "4.3-9.1",
|
|
NewVersion: "5.0-4",
|
|
}},
|
|
},
|
|
want: "fixed",
|
|
},
|
|
{
|
|
name: "windows unfixed",
|
|
fields: fields{
|
|
Confidences: Confidences{WindowsUpdateSearch},
|
|
},
|
|
want: "unfixed",
|
|
},
|
|
{
|
|
name: "windows fixed",
|
|
fields: fields{
|
|
Confidences: Confidences{WindowsUpdateSearch},
|
|
WindowsKBFixedIns: []string{"000000"},
|
|
},
|
|
want: "fixed",
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
v := VulnInfo{
|
|
Confidences: tt.fields.Confidences,
|
|
AffectedPackages: tt.fields.AffectedPackages,
|
|
CpeURIs: tt.fields.CpeURIs,
|
|
WindowsKBFixedIns: tt.fields.WindowsKBFixedIns,
|
|
}
|
|
if got := v.PatchStatus(tt.args.packs); got != tt.want {
|
|
t.Errorf("VulnInfo.PatchStatus() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVulnInfo_Cvss40Scores(t *testing.T) {
|
|
type fields struct {
|
|
CveID string
|
|
CveContents CveContents
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
want []CveContentCvss
|
|
}{
|
|
{
|
|
name: "happy",
|
|
fields: fields{
|
|
CveID: "CVE-2024-5732",
|
|
CveContents: CveContents{
|
|
Mitre: []CveContent{
|
|
{
|
|
Type: Mitre,
|
|
Cvss40Score: 6.9,
|
|
Cvss40Vector: "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
|
|
Cvss40Severity: "MEDIUM",
|
|
Cvss3Score: 7.3,
|
|
Cvss3Vector: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
|
|
Cvss3Severity: "HIGH",
|
|
Optional: map[string]string{"source": "CNA"},
|
|
},
|
|
},
|
|
Nvd: []CveContent{
|
|
{
|
|
Type: Nvd,
|
|
Cvss40Score: 6.9,
|
|
Cvss40Vector: "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
|
|
Cvss40Severity: "MEDIUM",
|
|
Optional: map[string]string{"source": "cna@vuldb.com"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
want: []CveContentCvss{
|
|
{
|
|
Type: Mitre,
|
|
Value: Cvss{
|
|
Type: CVSS40,
|
|
Score: 6.9,
|
|
Severity: "MEDIUM",
|
|
Vector: "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
|
|
},
|
|
},
|
|
{
|
|
Type: Nvd,
|
|
Value: Cvss{
|
|
Type: CVSS40,
|
|
Score: 6.9,
|
|
Severity: "MEDIUM",
|
|
Vector: "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := (VulnInfo{
|
|
CveID: tt.fields.CveID,
|
|
CveContents: tt.fields.CveContents,
|
|
}).Cvss40Scores(); !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("VulnInfo.Cvss40Scores() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestVulnInfo_MaxCvss40Score(t *testing.T) {
|
|
type fields struct {
|
|
CveID string
|
|
CveContents CveContents
|
|
}
|
|
tests := []struct {
|
|
name string
|
|
fields fields
|
|
want CveContentCvss
|
|
}{
|
|
{
|
|
name: "happy",
|
|
fields: fields{
|
|
CveID: "CVE-2024-5732",
|
|
CveContents: CveContents{
|
|
Mitre: []CveContent{
|
|
{
|
|
Type: Mitre,
|
|
Cvss40Score: 6.9,
|
|
Cvss40Vector: "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
|
|
Cvss40Severity: "MEDIUM",
|
|
Cvss3Score: 7.3,
|
|
Cvss3Vector: "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:L",
|
|
Cvss3Severity: "HIGH",
|
|
Optional: map[string]string{"source": "CNA"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
want: CveContentCvss{
|
|
Type: Mitre,
|
|
Value: Cvss{
|
|
Type: CVSS40,
|
|
Score: 6.9,
|
|
Severity: "MEDIUM",
|
|
Vector: "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:L/VA:L/SC:N/SI:N/SA:N",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if got := (VulnInfo{
|
|
CveID: tt.fields.CveID,
|
|
CveContents: tt.fields.CveContents,
|
|
}).MaxCvss40Score(); !reflect.DeepEqual(got, tt.want) {
|
|
t.Errorf("VulnInfo.MaxsCvss40Score() = %v, want %v", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|