vulnsrc_oracle: one vulnerability per CVE

Get one vulnerability per CVE for Oracle instead of one per ELSA so we
can have NVD metadata added to the vulnerabilities.

Related: #495, #499.
This commit is contained in:
Geoff Baskwill 2018-11-02 19:28:54 -04:00
parent 93e7a4cfa8
commit 3503ddb96f
3 changed files with 66 additions and 51 deletions

View File

@ -63,11 +63,19 @@ type definition struct {
References []reference `xml:"metadata>reference"` References []reference `xml:"metadata>reference"`
Criteria criteria `xml:"criteria"` Criteria criteria `xml:"criteria"`
Severity string `xml:"metadata>advisory>severity"` Severity string `xml:"metadata>advisory>severity"`
CVEs []cve `xml:"metadata>advisory>cve"`
} }
type reference struct { type reference struct {
Source string `xml:"source,attr"` Source string `xml:"source,attr"`
URI string `xml:"ref_url,attr"` URI string `xml:"ref_url,attr"`
ID string `xml:"ref_id,attr"`
}
type cve struct {
Impact string `xml:"impact,attr"`
Href string `xml:"href,attr"`
ID string `xml:",chardata"`
} }
type criteria struct { type criteria struct {
@ -227,14 +235,31 @@ func parseELSA(ovalReader io.Reader) (vulnerabilities []database.VulnerabilityWi
Vulnerability: database.Vulnerability{ Vulnerability: database.Vulnerability{
Name: name(definition), Name: name(definition),
Link: link(definition), Link: link(definition),
Severity: severity(definition), Severity: severity(definition.Severity),
Description: description(definition), Description: description(definition),
}, },
} }
for _, p := range pkgs { for _, p := range pkgs {
vulnerability.Affected = append(vulnerability.Affected, p) vulnerability.Affected = append(vulnerability.Affected, p)
} }
// Only ELSA is present
if len(definition.CVEs) == 0 {
vulnerabilities = append(vulnerabilities, vulnerability) vulnerabilities = append(vulnerabilities, vulnerability)
continue
}
// Create one vulnerability per CVE
for _, currentCVE := range definition.CVEs {
vulnerability.Name = currentCVE.ID
vulnerability.Link = currentCVE.Href
if currentCVE.Impact != "" {
vulnerability.Severity = severity(currentCVE.Impact)
} else {
vulnerability.Severity = severity(definition.Severity)
}
vulnerabilities = append(vulnerabilities, vulnerability)
}
} }
} }
@ -396,20 +421,20 @@ func link(def definition) (link string) {
return return
} }
func severity(def definition) database.Severity { func severity(sev string) database.Severity {
switch strings.ToLower(def.Severity) { switch strings.ToLower(sev) {
case "n/a": case "n/a":
return database.NegligibleSeverity return database.NegligibleSeverity
case "low": case "low":
return database.LowSeverity return database.LowSeverity
case "moderate": case "moderate":
return database.MediumSeverity return database.MediumSeverity
case "important": case "important", "high": // some ELSAs have "high" instead of "important"
return database.HighSeverity return database.HighSeverity
case "critical": case "critical":
return database.CriticalSeverity return database.CriticalSeverity
default: default:
log.WithField("severity", def.Severity).Warning("could not determine vulnerability severity") log.WithField("severity", sev).Warning("could not determine vulnerability severity")
return database.UnknownSeverity return database.UnknownSeverity
} }
} }

View File

@ -15,6 +15,7 @@
package oracle package oracle
import ( import (
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"runtime" "runtime"
@ -25,7 +26,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestOracleParser(t *testing.T) { func TestOracleParserOneCve(t *testing.T) {
_, filename, _, _ := runtime.Caller(0) _, filename, _, _ := runtime.Caller(0)
path := filepath.Join(filepath.Dir(filename)) path := filepath.Join(filepath.Dir(filename))
@ -35,8 +36,8 @@ func TestOracleParser(t *testing.T) {
vulnerabilities, err := parseELSA(testFile) vulnerabilities, err := parseELSA(testFile)
if assert.Nil(t, err) && assert.Len(t, vulnerabilities, 1) { if assert.Nil(t, err) && assert.Len(t, vulnerabilities, 1) {
assert.Equal(t, "ELSA-2015-1193", vulnerabilities[0].Name) assert.Equal(t, "CVE-2015-0252", vulnerabilities[0].Name)
assert.Equal(t, "http://linux.oracle.com/errata/ELSA-2015-1193.html", vulnerabilities[0].Link) assert.Equal(t, "http://linux.oracle.com/cve/CVE-2015-0252.html", vulnerabilities[0].Link)
assert.Equal(t, database.MediumSeverity, vulnerabilities[0].Severity) assert.Equal(t, database.MediumSeverity, vulnerabilities[0].Severity)
assert.Equal(t, ` [3.1.1-7] Resolves: rhbz#1217104 CVE-2015-0252 `, vulnerabilities[0].Description) assert.Equal(t, ` [3.1.1-7] Resolves: rhbz#1217104 CVE-2015-0252 `, vulnerabilities[0].Description)
@ -77,41 +78,30 @@ func TestOracleParser(t *testing.T) {
assert.Contains(t, vulnerabilities[0].Affected, expectedFeature) assert.Contains(t, vulnerabilities[0].Affected, expectedFeature)
} }
} }
}
testFile2, _ := os.Open(filepath.Join(path, "/testdata/fetcher_oracle_test.2.xml")) func TestELSAParserMultipleCVE(t *testing.T) {
defer testFile2.Close() testFile, _ := os.Open("testdata/fetcher_oracle_test.2.xml")
defer testFile.Close()
vulnerabilities, err = parseELSA(testFile2) vulnerabilities, err := parseELSA(testFile)
if assert.Nil(t, err) && assert.Len(t, vulnerabilities, 1) {
assert.Equal(t, "ELSA-2015-1207", vulnerabilities[0].Name)
assert.Equal(t, "http://linux.oracle.com/errata/ELSA-2015-1207.html", vulnerabilities[0].Link)
assert.Equal(t, database.CriticalSeverity, vulnerabilities[0].Severity)
assert.Equal(t, ` [38.1.0-1.0.1.el7_1] - Add firefox-oracle-default-prefs.js and remove the corresponding Red Hat file [38.1.0-1] - Update to 38.1.0 ESR [38.0.1-2] - Fixed rhbz#1222807 by removing preun section `, vulnerabilities[0].Description)
expectedFeatures := []database.AffectedFeature{
{
AffectedType: affectedType,
Namespace: database.Namespace{
Name: "oracle:6",
VersionFormat: rpm.ParserName,
},
FeatureName: "firefox",
FixedInVersion: "0:38.1.0-1.0.1.el6_6",
AffectedVersion: "0:38.1.0-1.0.1.el6_6",
},
{
AffectedType: affectedType,
Namespace: database.Namespace{
Name: "oracle:7",
VersionFormat: rpm.ParserName,
},
FeatureName: "firefox",
FixedInVersion: "0:38.1.0-1.0.1.el7_1",
AffectedVersion: "0:38.1.0-1.0.1.el7_1",
},
}
for _, expectedFeature := range expectedFeatures { // Expected
assert.Contains(t, vulnerabilities[0].Affected, expectedFeature) expectedCve := []string{"CVE-2015-2722", "CVE-2015-2724", "CVE-2015-2725", "CVE-2015-2727",
"CVE-2015-2728", "CVE-2015-2729", "CVE-2015-2731", "CVE-2015-2733", "CVE-2015-2734",
"CVE-2015-2735", "CVE-2015-2736", "CVE-2015-2737", "CVE-2015-2738", "CVE-2015-2739",
"CVE-2015-2740", "CVE-2015-2741", "CVE-2015-2743"}
expectedSeverity := []string{"Negligible", "Low", "Medium", "High",
"Critical", "Unknown", "Critical", "Critical", "Critical",
"Critical", "Critical", "Critical", "Critical", "Critical",
"Critical", "Critical", "Critical"}
if assert.Nil(t, err) && assert.Len(t, vulnerabilities, len(expectedCve)) {
for i, vulnerability := range vulnerabilities {
assert.Equal(t, expectedCve[i], vulnerability.Name)
assert.Equal(t, fmt.Sprintf("http://linux.oracle.com/cve/%s.html", expectedCve[i]), vulnerability.Link)
assert.Equal(t, database.Severity(expectedSeverity[i]), vulnerability.Severity)
assert.Equal(t, ` [38.1.0-1.0.1.el7_1] - Add firefox-oracle-default-prefs.js and remove the corresponding Red Hat file [38.1.0-1] - Update to 38.1.0 ESR [38.0.1-2] - Fixed rhbz#1222807 by removing preun section `, vulnerability.Description)
} }
} }
} }

View File

@ -53,12 +53,12 @@ ELSA-2015-1207: firefox security update (CRITICAL)
<severity>CRITICAL</severity> <severity>CRITICAL</severity>
<rights>Copyright 2015 Oracle, Inc.</rights> <rights>Copyright 2015 Oracle, Inc.</rights>
<issued date="2015-07-03"/> <issued date="2015-07-03"/>
<cve href="http://linux.oracle.com/cve/CVE-2015-2722.html">CVE-2015-2722</cve> <cve href="http://linux.oracle.com/cve/CVE-2015-2722.html" impact="N/A">CVE-2015-2722</cve>
<cve href="http://linux.oracle.com/cve/CVE-2015-2724.html">CVE-2015-2724</cve> <cve href="http://linux.oracle.com/cve/CVE-2015-2724.html" impact="LOW">CVE-2015-2724</cve>
<cve href="http://linux.oracle.com/cve/CVE-2015-2725.html">CVE-2015-2725</cve> <cve href="http://linux.oracle.com/cve/CVE-2015-2725.html" impact="MODERATE">CVE-2015-2725</cve>
<cve href="http://linux.oracle.com/cve/CVE-2015-2727.html">CVE-2015-2727</cve> <cve href="http://linux.oracle.com/cve/CVE-2015-2727.html" impact="IMPORTANT">CVE-2015-2727</cve>
<cve href="http://linux.oracle.com/cve/CVE-2015-2728.html">CVE-2015-2728</cve> <cve href="http://linux.oracle.com/cve/CVE-2015-2728.html" impact="CRITICAL">CVE-2015-2728</cve>
<cve href="http://linux.oracle.com/cve/CVE-2015-2729.html">CVE-2015-2729</cve> <cve href="http://linux.oracle.com/cve/CVE-2015-2729.html" impact="OTHER">CVE-2015-2729</cve>
<cve href="http://linux.oracle.com/cve/CVE-2015-2731.html">CVE-2015-2731</cve> <cve href="http://linux.oracle.com/cve/CVE-2015-2731.html">CVE-2015-2731</cve>
<cve href="http://linux.oracle.com/cve/CVE-2015-2733.html">CVE-2015-2733</cve> <cve href="http://linux.oracle.com/cve/CVE-2015-2733.html">CVE-2015-2733</cve>
<cve href="http://linux.oracle.com/cve/CVE-2015-2734.html">CVE-2015-2734</cve> <cve href="http://linux.oracle.com/cve/CVE-2015-2734.html">CVE-2015-2734</cve>