Display summary of advisory when no entry in NVD, OVAL
This commit is contained in:
@@ -58,72 +58,6 @@ func (v CveContents) Except(exceptCtypes ...CveContentType) (values CveContents)
|
||||
return
|
||||
}
|
||||
|
||||
// Titles returns tilte (TUI)
|
||||
func (v CveContents) Titles(lang, myFamily string) (values []CveContentStr) {
|
||||
if lang == "ja" {
|
||||
if cont, found := v[JVN]; found && 0 < len(cont.Title) {
|
||||
values = append(values, CveContentStr{JVN, cont.Title})
|
||||
}
|
||||
}
|
||||
|
||||
order := CveContentTypes{NVD, NewCveContentType(myFamily)}
|
||||
order = append(order, AllCveContetTypes.Except(append(order, JVN)...)...)
|
||||
for _, ctype := range order {
|
||||
// Only JVN has meaningful title. so return first 100 char of summary
|
||||
if cont, found := v[ctype]; found && 0 < len(cont.Summary) {
|
||||
summary := strings.Replace(cont.Summary, "\n", " ", -1)
|
||||
index := 75
|
||||
if index < len(summary) {
|
||||
summary = summary[0:index] + "..."
|
||||
}
|
||||
values = append(values, CveContentStr{
|
||||
Type: ctype,
|
||||
Value: summary,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(values) == 0 {
|
||||
values = []CveContentStr{{
|
||||
Type: Unknown,
|
||||
Value: "-",
|
||||
}}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Summaries returns summaries
|
||||
func (v CveContents) Summaries(lang, myFamily string) (values []CveContentStr) {
|
||||
if lang == "ja" {
|
||||
if cont, found := v[JVN]; found && 0 < len(cont.Summary) {
|
||||
summary := cont.Title
|
||||
summary += "\n" + strings.Replace(
|
||||
strings.Replace(cont.Summary, "\n", " ", -1), "\r", " ", -1)
|
||||
values = append(values, CveContentStr{JVN, summary})
|
||||
}
|
||||
}
|
||||
|
||||
order := CveContentTypes{NVD, NewCveContentType(myFamily)}
|
||||
order = append(order, AllCveContetTypes.Except(append(order, JVN)...)...)
|
||||
for _, ctype := range order {
|
||||
if cont, found := v[ctype]; found && 0 < len(cont.Summary) {
|
||||
summary := strings.Replace(cont.Summary, "\n", " ", -1)
|
||||
values = append(values, CveContentStr{
|
||||
Type: ctype,
|
||||
Value: summary,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(values) == 0 {
|
||||
values = []CveContentStr{{
|
||||
Type: Unknown,
|
||||
Value: "-",
|
||||
}}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// SourceLinks returns link of source
|
||||
func (v CveContents) SourceLinks(lang, myFamily, cveID string) (values []CveContentStr) {
|
||||
if lang == "ja" {
|
||||
|
||||
@@ -44,202 +44,6 @@ func TestExcept(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTitles(t *testing.T) {
|
||||
type in struct {
|
||||
lang string
|
||||
cont CveContents
|
||||
}
|
||||
var tests = []struct {
|
||||
in in
|
||||
out []CveContentStr
|
||||
}{
|
||||
// lang: ja
|
||||
{
|
||||
in: in{
|
||||
lang: "ja",
|
||||
cont: CveContents{
|
||||
JVN: {
|
||||
Type: JVN,
|
||||
Title: "Title1",
|
||||
},
|
||||
RedHat: {
|
||||
Type: RedHat,
|
||||
Summary: "Summary RedHat",
|
||||
},
|
||||
NVD: {
|
||||
Type: NVD,
|
||||
Summary: "Summary NVD",
|
||||
// Severity is NIOT 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: CveContents{
|
||||
JVN: {
|
||||
Type: JVN,
|
||||
Title: "Title1",
|
||||
},
|
||||
RedHat: {
|
||||
Type: RedHat,
|
||||
Summary: "Summary RedHat",
|
||||
},
|
||||
NVD: {
|
||||
Type: NVD,
|
||||
Summary: "Summary NVD",
|
||||
// Severity is NIOT included in NVD
|
||||
},
|
||||
},
|
||||
},
|
||||
out: []CveContentStr{
|
||||
{
|
||||
Type: NVD,
|
||||
Value: "Summary NVD",
|
||||
},
|
||||
{
|
||||
Type: RedHat,
|
||||
Value: "Summary RedHat",
|
||||
},
|
||||
},
|
||||
},
|
||||
// lang: empty
|
||||
{
|
||||
in: in{
|
||||
lang: "en",
|
||||
cont: CveContents{},
|
||||
},
|
||||
out: []CveContentStr{
|
||||
{
|
||||
Type: Unknown,
|
||||
Value: "-",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
actual := tt.in.cont.Titles(tt.in.lang, "redhat")
|
||||
if !reflect.DeepEqual(tt.out, actual) {
|
||||
t.Errorf("\nexpected: %v\n actual: %v\n", tt.out, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSummaries(t *testing.T) {
|
||||
type in struct {
|
||||
lang string
|
||||
cont CveContents
|
||||
}
|
||||
var tests = []struct {
|
||||
in in
|
||||
out []CveContentStr
|
||||
}{
|
||||
// lang: ja
|
||||
{
|
||||
in: in{
|
||||
lang: "ja",
|
||||
cont: CveContents{
|
||||
JVN: {
|
||||
Type: JVN,
|
||||
Title: "Title JVN",
|
||||
Summary: "Summary JVN",
|
||||
},
|
||||
RedHat: {
|
||||
Type: RedHat,
|
||||
Summary: "Summary RedHat",
|
||||
},
|
||||
NVD: {
|
||||
Type: NVD,
|
||||
Summary: "Summary NVD",
|
||||
// Severity is NIOT included in NVD
|
||||
},
|
||||
},
|
||||
},
|
||||
out: []CveContentStr{
|
||||
{
|
||||
Type: JVN,
|
||||
Value: "Title JVN\nSummary JVN",
|
||||
},
|
||||
{
|
||||
Type: NVD,
|
||||
Value: "Summary NVD",
|
||||
},
|
||||
{
|
||||
Type: RedHat,
|
||||
Value: "Summary RedHat",
|
||||
},
|
||||
},
|
||||
},
|
||||
// lang: en
|
||||
{
|
||||
in: in{
|
||||
lang: "en",
|
||||
cont: CveContents{
|
||||
JVN: {
|
||||
Type: JVN,
|
||||
Title: "Title JVN",
|
||||
Summary: "Summary JVN",
|
||||
},
|
||||
RedHat: {
|
||||
Type: RedHat,
|
||||
Summary: "Summary RedHat",
|
||||
},
|
||||
NVD: {
|
||||
Type: NVD,
|
||||
Summary: "Summary NVD",
|
||||
// Severity is NIOT included in NVD
|
||||
},
|
||||
},
|
||||
},
|
||||
out: []CveContentStr{
|
||||
{
|
||||
Type: NVD,
|
||||
Value: "Summary NVD",
|
||||
},
|
||||
{
|
||||
Type: RedHat,
|
||||
Value: "Summary RedHat",
|
||||
},
|
||||
},
|
||||
},
|
||||
// lang: empty
|
||||
{
|
||||
in: in{
|
||||
lang: "en",
|
||||
cont: CveContents{},
|
||||
},
|
||||
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 TestSourceLinks(t *testing.T) {
|
||||
type in struct {
|
||||
lang string
|
||||
|
||||
@@ -114,6 +114,83 @@ type VulnInfo struct {
|
||||
CveContents CveContents
|
||||
}
|
||||
|
||||
// Titles returns tilte (TUI)
|
||||
func (v VulnInfo) Titles(lang, myFamily string) (values []CveContentStr) {
|
||||
if lang == "ja" {
|
||||
if cont, found := v.CveContents[JVN]; found && 0 < len(cont.Title) {
|
||||
values = append(values, CveContentStr{JVN, cont.Title})
|
||||
}
|
||||
}
|
||||
|
||||
order := CveContentTypes{NVD, NewCveContentType(myFamily)}
|
||||
order = append(order, AllCveContetTypes.Except(append(order, JVN)...)...)
|
||||
for _, ctype := range order {
|
||||
// Only JVN has meaningful title. so return first 100 char of summary
|
||||
if cont, found := v.CveContents[ctype]; found && 0 < len(cont.Summary) {
|
||||
summary := strings.Replace(cont.Summary, "\n", " ", -1)
|
||||
values = append(values, CveContentStr{
|
||||
Type: ctype,
|
||||
Value: summary,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for _, adv := range v.DistroAdvisories {
|
||||
values = append(values, CveContentStr{
|
||||
Type: "Vendor",
|
||||
Value: strings.Replace(adv.Description, "\n", " ", -1),
|
||||
})
|
||||
}
|
||||
|
||||
if len(values) == 0 {
|
||||
values = []CveContentStr{{
|
||||
Type: Unknown,
|
||||
Value: "-",
|
||||
}}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Summaries returns summaries
|
||||
func (v VulnInfo) Summaries(lang, myFamily string) (values []CveContentStr) {
|
||||
if lang == "ja" {
|
||||
if cont, found := v.CveContents[JVN]; found && 0 < len(cont.Summary) {
|
||||
summary := cont.Title
|
||||
summary += "\n" + strings.Replace(
|
||||
strings.Replace(cont.Summary, "\n", " ", -1), "\r", " ", -1)
|
||||
values = append(values, CveContentStr{JVN, summary})
|
||||
}
|
||||
}
|
||||
|
||||
order := CveContentTypes{NVD, NewCveContentType(myFamily)}
|
||||
order = append(order, AllCveContetTypes.Except(append(order, JVN)...)...)
|
||||
for _, ctype := range order {
|
||||
if cont, found := v.CveContents[ctype]; found && 0 < len(cont.Summary) {
|
||||
summary := strings.Replace(cont.Summary, "\n", " ", -1)
|
||||
values = append(values, CveContentStr{
|
||||
Type: ctype,
|
||||
Value: summary,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for _, adv := range v.DistroAdvisories {
|
||||
values = append(values, CveContentStr{
|
||||
Type: "Vendor",
|
||||
Value: adv.Description,
|
||||
})
|
||||
}
|
||||
|
||||
if len(values) == 0 {
|
||||
return []CveContentStr{{
|
||||
Type: Unknown,
|
||||
Value: "-",
|
||||
}}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Cvss2Scores returns CVSS V2 Scores
|
||||
func (v VulnInfo) Cvss2Scores() (values []CveContentCvss) {
|
||||
order := []CveContentType{NVD, RedHat, JVN}
|
||||
|
||||
@@ -21,6 +21,210 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
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: {
|
||||
Type: JVN,
|
||||
Title: "Title1",
|
||||
},
|
||||
RedHat: {
|
||||
Type: RedHat,
|
||||
Summary: "Summary RedHat",
|
||||
},
|
||||
NVD: {
|
||||
Type: NVD,
|
||||
Summary: "Summary NVD",
|
||||
// Severity is NIOT 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: {
|
||||
Type: JVN,
|
||||
Title: "Title1",
|
||||
},
|
||||
RedHat: {
|
||||
Type: RedHat,
|
||||
Summary: "Summary RedHat",
|
||||
},
|
||||
NVD: {
|
||||
Type: NVD,
|
||||
Summary: "Summary NVD",
|
||||
// Severity is NIOT 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 _, tt := range tests {
|
||||
actual := tt.in.cont.Titles(tt.in.lang, "redhat")
|
||||
if !reflect.DeepEqual(tt.out, actual) {
|
||||
t.Errorf("\nexpected: %v\n actual: %v\n", 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: {
|
||||
Type: JVN,
|
||||
Title: "Title JVN",
|
||||
Summary: "Summary JVN",
|
||||
},
|
||||
RedHat: {
|
||||
Type: RedHat,
|
||||
Summary: "Summary RedHat",
|
||||
},
|
||||
NVD: {
|
||||
Type: NVD,
|
||||
Summary: "Summary NVD",
|
||||
// Severity is NIOT included in NVD
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
out: []CveContentStr{
|
||||
{
|
||||
Type: JVN,
|
||||
Value: "Title JVN\nSummary JVN",
|
||||
},
|
||||
{
|
||||
Type: NVD,
|
||||
Value: "Summary NVD",
|
||||
},
|
||||
{
|
||||
Type: RedHat,
|
||||
Value: "Summary RedHat",
|
||||
},
|
||||
},
|
||||
},
|
||||
// lang: en
|
||||
{
|
||||
in: in{
|
||||
lang: "en",
|
||||
cont: VulnInfo{
|
||||
CveContents: CveContents{
|
||||
JVN: {
|
||||
Type: JVN,
|
||||
Title: "Title JVN",
|
||||
Summary: "Summary JVN",
|
||||
},
|
||||
RedHat: {
|
||||
Type: RedHat,
|
||||
Summary: "Summary RedHat",
|
||||
},
|
||||
NVD: {
|
||||
Type: NVD,
|
||||
Summary: "Summary NVD",
|
||||
// Severity is NIOT 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 _, 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
|
||||
@@ -578,6 +782,24 @@ func TestMaxCvssScores(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
in: VulnInfo{
|
||||
DistroAdvisories: []DistroAdvisory{
|
||||
{
|
||||
Severity: "HIGH",
|
||||
},
|
||||
},
|
||||
},
|
||||
out: CveContentCvss{
|
||||
Type: "Vendor",
|
||||
Value: Cvss{
|
||||
Type: CVSS2,
|
||||
Score: 8.9,
|
||||
Vector: "-",
|
||||
Severity: "HIGH",
|
||||
},
|
||||
},
|
||||
},
|
||||
// Empty
|
||||
{
|
||||
in: VulnInfo{},
|
||||
|
||||
@@ -270,7 +270,7 @@ func attachmentText(vinfo models.VulnInfo, osFamily string) string {
|
||||
severity,
|
||||
cweIDs(vinfo, osFamily),
|
||||
strings.Join(vectors, "\n"),
|
||||
vinfo.CveContents.Summaries(config.Conf.Lang, osFamily)[0].Value,
|
||||
vinfo.Summaries(config.Conf.Lang, osFamily)[0].Value,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -638,7 +638,7 @@ func summaryLines() string {
|
||||
}
|
||||
|
||||
for i, vinfo := range vinfos {
|
||||
summary := vinfo.CveContents.Summaries(
|
||||
summary := vinfo.Titles(
|
||||
config.Conf.Lang, currentScanResult.Family)[0].Value
|
||||
cvssScore := fmt.Sprintf("| %4.1f",
|
||||
vinfo.MaxCvssScore().Value.Score)
|
||||
@@ -790,7 +790,7 @@ func detailLines() (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
summary := vinfo.CveContents.Summaries(r.Lang, r.Family)[0]
|
||||
summary := vinfo.Summaries(r.Lang, r.Family)[0]
|
||||
|
||||
data := dataForTmpl{
|
||||
CveID: vinfo.CveID,
|
||||
|
||||
@@ -110,7 +110,7 @@ func formatShortPlainText(r models.ScanResult) string {
|
||||
stable.MaxColWidth = maxColWidth
|
||||
stable.Wrap = true
|
||||
for _, vuln := range vulns.ToSortedSlice() {
|
||||
summaries := vuln.CveContents.Summaries(config.Conf.Lang, r.Family)
|
||||
summaries := vuln.Summaries(config.Conf.Lang, r.Family)
|
||||
links := vuln.CveContents.SourceLinks(
|
||||
config.Conf.Lang, r.Family, vuln.CveID)
|
||||
|
||||
@@ -199,7 +199,7 @@ func formatFullPlainText(r models.ScanResult) string {
|
||||
if 0 < len(vuln.Cvss3Scores()) {
|
||||
table.AddRow("CVSSv3 Calc", vuln.Cvss3CalcURL())
|
||||
}
|
||||
table.AddRow("Summary", vuln.CveContents.Summaries(
|
||||
table.AddRow("Summary", vuln.Summaries(
|
||||
config.Conf.Lang, r.Family)[0].Value)
|
||||
|
||||
links := vuln.CveContents.SourceLinks(
|
||||
|
||||
Reference in New Issue
Block a user