Merge ~litios/ubuntu-cve-tracker:oval-cve-tag into ubuntu-cve-tracker:master

Proposed by David Fernandez Gonzalez
Status: Merged
Merge reported by: David Fernandez Gonzalez
Merged at revision: 349332baab42728fef77dc722637e3dbecf2f017
Proposed branch: ~litios/ubuntu-cve-tracker:oval-cve-tag
Merge into: ubuntu-cve-tracker:master
Diff against target: 157 lines (+57/-19)
2 files modified
scripts/generate-oval (+0/-1)
scripts/oval_lib.py (+57/-18)
Reviewer Review Type Date Requested Status
Eduardo Barretto Approve
Review via email: mp+440876@code.launchpad.net

Description of the change

This change will add a new tag: <cve>

This tag will be used to represent the cve in the advisory, as this is especially needed for OVAL for packages. This cve tag tries to follow Red Hat approach:

<cve cvss3="5.4/CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:L/A:N" cwe="CWE-285" href="https://access.redhat.com/security/cve/CVE-2019-0816" impact="moderate" public="20190305">CVE-2019-0816</cve>

Some comments:

* Severity is extracted from Ubuntu's priority.
* Severity and public date are omitted in CVE format as they are already on the advisory.
* USNs are also added as a comma-separated list of elements.
* The most recent CVSS vector and score are added.

Examples:

- OVAL PKG advisory:

<rights>Copyright (C) 2023 Canonical Ltd.</rights>
<component>main</component>
<current_version>2.4.52-1ubuntu4.4</current_version>
<cve href="https://ubuntu.com/security/CVE-2023-25690" severity="medium" public="20230307" cvss_score="9.8" cvss_vector="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H" usns="942-1,942-2">CVE-2023-25690</cve>
<cve href="https://ubuntu.com/security/CVE-2023-27522" severity="medium" public="20230307" cvss_score="7.5" cvss_vector="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:N" usns="942-1">CVE-2023-27522</cve>

- OVAL CVE advisory:

<severity>Medium</severity>
<rights>Copyright (C) 2023 Canonical Ltd.</rights>
<public_date>2023-01-11</public_date>
<public_date_at_usn>2023-01-11</public_date_at_usn>
<cve href="https://ubuntu.com/security/CVE-2023-0210" cvss_score="7.5" cvss_vector="CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H" usns="915-1,982-1,987-1,004-1">CVE-2023-0210</cve>

To post a comment you must log in.
32f0063... by David Fernandez Gonzalez

oval_lib: add cve tag to usns

Revision history for this message
Eduardo Barretto (ebarretto) wrote :

overall lgtm, but I do have a doubt if we decided to not have severity in the <cve> tag for CVE-based OVAL and USN-based OVAL. Do you remember?

review: Approve
Revision history for this message
David Fernandez Gonzalez (litios) wrote :

Yeah, for CVE-based OVAL we decided to not add it as it was redundant.

> we already have severity on the top, I wonder if we keep severity from us, and in the cve tag whatever is from cvss

For USN-based OVAL we didn't discuss it but the severity we are using is computed from all the CVEs to represent the general severity. I think it would be useful to have the severities for each of the CVEs on the USN.

349332b... by David Fernandez Gonzalez

oval_lib: refactor cve tag generation to unify across formats

Revision history for this message
David Fernandez Gonzalez (litios) wrote :

As discussed with Eduardo, it's best to keep a stable format for all OVAL formats. The format follows the structure as described in the PKG format in the description:

<cve href="https://ubuntu.com/security/CVE-2022-21427" severity="medium" public="20220419" cvss_score="4.9" cvss_vector="CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H" usns="400-1,400-2,739-1">CVE-2022-21427</cve>

Revision history for this message
Eduardo Barretto (ebarretto) wrote :

lgtm, thanks for addressing the last changes!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/scripts/generate-oval b/scripts/generate-oval
index f703733..d168786 100755
--- a/scripts/generate-oval
+++ b/scripts/generate-oval
@@ -234,7 +234,6 @@ def parse_cve_file(filepath, cache, pkg_filter=None):
234 cve_header_data['References'].insert(0, get_cve_url(filepath))234 cve_header_data['References'].insert(0, get_cve_url(filepath))
235 cve_header_data['Bugs'] = [bug.strip() for bug in cve_header_data['Bugs'].split('\n') if len(bug.strip()) > 0]235 cve_header_data['Bugs'] = [bug.strip() for bug in cve_header_data['Bugs'].split('\n') if len(bug.strip()) > 0]
236 cve_header_data['Notes'] = ' '.join(user + '> ' + note.replace('\n', ' ') for user, note in cve_header_data['Notes'])236 cve_header_data['Notes'] = ' '.join(user + '> ' + note.replace('\n', ' ') for user, note in cve_header_data['Notes'])
237 cve_header_data['CVSS'] = ' '.join(cvss['source'] + ': ' + cvss['vector'] for cvss in cve_header_data['CVSS'])
238237
239 packages = {}238 packages = {}
240 for pkg in data['pkgs']:239 for pkg in data['pkgs']:
diff --git a/scripts/oval_lib.py b/scripts/oval_lib.py
index d8365c2..a08edab 100644
--- a/scripts/oval_lib.py
+++ b/scripts/oval_lib.py
@@ -120,6 +120,26 @@ def debug(message):
120 if debug_level > 0:120 if debug_level > 0:
121 sys.stdout.write('\rDEBUG: {0}\n'.format(message))121 sys.stdout.write('\rDEBUG: {0}\n'.format(message))
122122
123def generate_cve_tag(cve):
124 cve_ref = '<cve href="https://ubuntu.com/security/{0}" severity="{1}" public="{2}"'.format(cve['Candidate'], cve['Priority'], cve['PublicDate'].split(' ')[0].replace('-', ''))
125
126 if cve['CVSS']:
127 cve_ref += ' cvss_score="{0}" cvss_vector="{1}"'.format(cve['CVSS'][0]['baseScore'], cve['CVSS'][0]['vector'])
128
129 cve_ref_usns = False
130 for ref in cve['References']:
131 if 'https://ubuntu.com/security/notices/USN' in ref:
132 if not cve_ref_usns:
133 cve_ref_usns = True
134 cve_ref += ' usns="'
135 cve_ref += '{0},'.format(ref[41:])
136
137 if cve_ref_usns:
138 cve_ref = '{0}"'.format(cve_ref[:-1])
139
140 cve_ref += '>{0}</cve>'.format(cve['Candidate'])
141 return cve_ref
142
123class OvalGenerator:143class OvalGenerator:
124 supported_oval_elements = ('definition', 'test', 'object', 'state', 'variable')144 supported_oval_elements = ('definition', 'test', 'object', 'state', 'variable')
125 generator_version = '1.1'145 generator_version = '1.1'
@@ -424,6 +444,13 @@ class CVE:
424 def __init__(self, number, info, pkgs=[]) -> None:444 def __init__(self, number, info, pkgs=[]) -> None:
425 self.number = number445 self.number = number
426 self.description = info['Description']446 self.description = info['Description']
447 self.severity = info['Priority']
448 self.public_date = info['PublicDate']
449 self.cvss = info['CVSS']
450 self.usns = []
451 for url in info['References'].split('\n'):
452 if 'https://ubuntu.com/security/notices/USN-' in url:
453 self.usns.append(url[41:])
427 self.pkg_rel_entries = {}454 self.pkg_rel_entries = {}
428 self.pkgs = pkgs455 self.pkgs = pkgs
429456
@@ -501,6 +528,10 @@ class OvalGeneratorPkg(OvalGenerator):
501 component = etree.SubElement(advisory, "component")528 component = etree.SubElement(advisory, "component")
502 version = etree.SubElement(advisory, "current_version")529 version = etree.SubElement(advisory, "current_version")
503530
531 for cve in package.cves:
532 cve_obj = self._generate_cve_object(cve)
533 advisory.append(cve_obj)
534
504 rights.text = f"Copyright (C) {datetime.now().year} Canonical Ltd."535 rights.text = f"Copyright (C) {datetime.now().year} Canonical Ltd."
505 component.text = package.section536 component.text = package.section
506 version.text = package.version537 version.text = package.version
@@ -558,6 +589,22 @@ class OvalGeneratorPkg(OvalGenerator):
558 definition.append(criteria)589 definition.append(criteria)
559 return definition590 return definition
560591
592 def _generate_cve_object(self, cve: CVE) -> etree.Element:
593 cve_tag = etree.Element("cve",
594 attrib={
595 'href' : f"https://ubuntu.com/security/{cve.number}",
596 'severity': cve.severity,
597 'public': cve.public_date.split(' ')[0].replace('-', '')
598 })
599
600 cve_tag.text = cve.number
601 if cve.cvss:
602 cve_tag.set('cvss_score', cve.cvss[0]['baseScore'])
603 cve_tag.set('cvss_vector', cve.cvss[0]['vector'])
604 if cve.usns:
605 cve_tag.set('usns', ','.join(cve.usns))
606
607 return cve_tag
561 def _generate_var_object(self, comment, id, binaries) -> etree.Element:608 def _generate_var_object(self, comment, id, binaries) -> etree.Element:
562 var = etree.Element("constant_variable",609 var = etree.Element("constant_variable",
563 attrib={610 attrib={
@@ -1297,8 +1344,9 @@ class OvalGeneratorCVE:
1297 continue1344 continue
1298 mapping['cve_title'] = escape(cve_title)1345 mapping['cve_title'] = escape(cve_title)
1299 mapping['references'] = '\n <reference source="CVE" ref_id="{0}" ref_url="{1}" />'.format(mapping['cve_title'], escape(ref))1346 mapping['references'] = '\n <reference source="CVE" ref_id="{0}" ref_url="{1}" />'.format(mapping['cve_title'], escape(ref))
1300 else:1347
1301 advisory.append('<ref>{0}</ref>'.format(escape(ref)))1348 cve_ref = generate_cve_tag(header)
1349 advisory.append(cve_ref)
1302 mapping['advisory_elements'] = '\n '.join(advisory)1350 mapping['advisory_elements'] = '\n '.join(advisory)
13031351
1304 if self.oval_format == 'dpkg':1352 if self.oval_format == 'dpkg':
@@ -1993,10 +2041,10 @@ class OvalGeneratorUSN():
1993 def create_cves_references(self, cves):2041 def create_cves_references(self, cves):
1994 references = ""2042 references = ""
1995 for cve in cves:2043 for cve in cves:
2044 cve_ref = generate_cve_tag(cve)
1996 references += \2045 references += \
1997 """ <reference source="CVE" ref_url="{}" ref_id="{}"/>2046 """{0}
1998""".format(cve['CVE_URL'], cve['Candidate'])2047 """.format(cve_ref)
1999
2000 return references.strip()2048 return references.strip()
20012049
2002 def get_usn_severity(self, cves):2050 def get_usn_severity(self, cves):
@@ -2075,11 +2123,11 @@ class OvalGeneratorUSN():
2075 <platform>{platform}</platform>2123 <platform>{platform}</platform>
2076 </affected>2124 </affected>
2077 <reference source="USN" ref_url="{usn_url}" ref_id="{usn_id}"/>2125 <reference source="USN" ref_url="{usn_url}" ref_id="{usn_id}"/>
2078 {cves_references}
2079 <description>{description}</description>2126 <description>{description}</description>
2080 <advisory from="security@ubuntu.com">2127 <advisory from="security@ubuntu.com">
2081 <severity>{severity}</severity>2128 <severity>{severity}</severity>
2082 <issued date="{usn_timestamp}"/>2129 <issued date="{usn_timestamp}"/>
2130 {cves_references}
2083 {bug_references}2131 {bug_references}
2084 </advisory>2132 </advisory>
2085 </metadata>2133 </metadata>
@@ -2342,23 +2390,14 @@ class OvalGeneratorUSN():
23422390
2343 public_date = cve_object['PublicDate']2391 public_date = cve_object['PublicDate']
2344 priority = cve_object['Priority']2392 priority = cve_object['Priority']
23452393 references = cve_object['References']
2346 # TODO: deal with multiple CVSS?2394 # TODO: deal with multiple CVSS?
2347 cvss = None
2348 baseScore = None
2349 baseSeverity = None
2350 if cve_object['CVSS']:
2351 cvss = cve_object['CVSS'][0]['vector']
2352 baseScore = cve_object['CVSS'][0]['baseScore']
2353 baseSeverity = cve_object['CVSS'][0]['baseSeverity'].title()
2354
2355 cve_info = {2395 cve_info = {
2356 'Candidate': cve,2396 'Candidate': cve,
2357 'PublicDate': public_date,2397 'PublicDate': public_date,
2358 'Priority': priority,2398 'Priority': priority,
2359 'CVSS': cvss,2399 'CVSS': cve_object['CVSS'],
2360 'CVSS_SEVERITY_LEVEL': baseSeverity,2400 'References': references.split('\n'),
2361 'CVSS_SCORE': baseScore,
2362 'CVE_URL': self.cve_base_url.format(cve),2401 'CVE_URL': self.cve_base_url.format(cve),
2363 'MITRE_URL': self.mitre_base_url.format(cve)2402 'MITRE_URL': self.mitre_base_url.format(cve)
2364 }2403 }

Subscribers

People subscribed via source and target branches