Skip to content

Commit 742a40d

Browse files
committed
Refactor oval data sources to use universal versions
Signed-off-by: Shivam Sandbhor <shivam.sandbhor@gmail.com>
1 parent 8fdb6e1 commit 742a40d

6 files changed

Lines changed: 43 additions & 39 deletions

File tree

vulnerabilities/data_source.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141

4242
import pygit2
4343
from packageurl import PackageURL
44+
from universal_versions.version_specifier import VersionSpecifier
45+
from universal_versions.versions import version_class_by_package_type
4446

4547
from vulnerabilities.oval_parser import OvalParser
4648
from vulnerabilities.severity_systems import ScoringSystem
@@ -514,7 +516,7 @@ def get_data_from_xml_doc(self, xml_doc: ET.ElementTree, pkg_metadata={}) -> Lis
514516
"type" key.
515517
516518
Example value of pkg_metadata:
517-
{"type":"deb","qualifiers":{"distro":"buster"} }
519+
{"type":"deb","qualifiers":{"distro":"buster"} }
518520
"""
519521

520522
all_adv = []
@@ -536,7 +538,14 @@ def get_data_from_xml_doc(self, xml_doc: ET.ElementTree, pkg_metadata={}) -> Lis
536538
for package_name in test_data["package_list"]:
537539
if package_name and len(package_name) >= 50:
538540
continue
539-
aff_ver_range = test_data["version_ranges"] or set()
541+
542+
affected_version_range = test_data["version_ranges"] or set()
543+
version_class = version_class_by_package_type[pkg_metadata["type"]]
544+
version_scheme = version_class.scheme
545+
546+
affected_version_range = VersionSpecifier.from_scheme_version_spec_string(
547+
version_scheme, affected_version_range
548+
)
540549
all_versions = self.pkg_manager_api.get(package_name)
541550

542551
# FIXME: what is this 50 DB limit? that's too small for versions
@@ -546,7 +555,9 @@ def get_data_from_xml_doc(self, xml_doc: ET.ElementTree, pkg_metadata={}) -> Lis
546555
all_versions = set(filter(lambda x: len(x) < 50, all_versions))
547556
if not all_versions:
548557
continue
549-
affected_versions = set(filter(lambda x: x in aff_ver_range, all_versions))
558+
affected_versions = set(
559+
filter(lambda x: version_class(x) in affected_version_range, all_versions)
560+
)
550561
safe_versions = all_versions - affected_versions
551562

552563
for version in affected_versions:

vulnerabilities/importers/github.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,9 @@
3131
from typing import Optional
3232

3333
import requests
34-
from dephell_specifier import RangeSpecifier
34+
from packageurl import PackageURL
3535
from universal_versions.version_specifier import VersionSpecifier
3636
from universal_versions.versions import version_class_by_package_type
37-
from packageurl import PackageURL
3837

3938
from vulnerabilities.data_source import Advisory
4039
from vulnerabilities.data_source import DataSource

vulnerabilities/oval_parser.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@
2828
from typing import Set
2929
import xml.etree.ElementTree as ET
3030

31-
from dephell_specifier import RangeSpecifier
32-
3331
from vulnerabilities.lib_oval import OvalDefinition
3432
from vulnerabilities.lib_oval import OvalDocument
3533
from vulnerabilities.lib_oval import OvalObject
@@ -68,7 +66,7 @@ def get_data(self) -> List[Dict]:
6866
continue
6967
test_data = {"package_list": []}
7068
test_data["package_list"].extend(self.get_pkgs_from_obj(test_obj))
71-
version_ranges = self.get_version_ranges_from_state(test_state)
69+
version_ranges = self.get_version_range_from_state(test_state)
7270
test_data["version_ranges"] = version_ranges
7371
definition_data["test_data"].append(test_data)
7472

@@ -131,9 +129,9 @@ def get_pkgs_from_obj(self, obj: OvalObject) -> List[str]:
131129

132130
return pkg_list
133131

134-
def get_version_ranges_from_state(self, state: OvalState) -> Optional[RangeSpecifier]:
132+
def get_version_range_from_state(self, state: OvalState) -> Optional[str]:
135133
"""
136-
Return a version range(s)? from a state
134+
Return a version range from a state
137135
"""
138136
for var in state.element:
139137
operation = var.get("operation")
@@ -160,7 +158,7 @@ def get_version_ranges_from_state(self, state: OvalState) -> Optional[RangeSpeci
160158
if version_range in x_version_ranges:
161159
version_range = x_version_ranges[version_range]
162160

163-
return RangeSpecifier(version_range)
161+
return version_range
164162

165163
@staticmethod
166164
def get_urls_from_definition(definition: OvalDefinition) -> Set[str]:

vulnerabilities/tests/test_debian_oval.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from collections import OrderedDict
77
import asyncio
88

9-
from dephell_specifier import RangeSpecifier
109
from packageurl import PackageURL
1110

1211
from vulnerabilities.oval_parser import OvalParser
@@ -73,35 +72,35 @@ def test_get_data_from_xml_doc(self, mock_write):
7372
),
7473
Advisory(
7574
summary="security update",
75+
vulnerability_id="CVE-2001-1593",
7676
impacted_package_urls={
7777
PackageURL(
7878
type="deb",
7979
namespace=None,
8080
name="a2ps",
81-
version="0.11.1+dfsg-5+deb7u1",
82-
qualifiers=OrderedDict([("distro", "wheezy")]),
81+
version="1.11.1+dfsg-5+deb7u1",
82+
qualifiers={"distro": "wheezy"},
8383
subpath=None,
84-
)
85-
},
86-
resolved_package_urls={
84+
),
8785
PackageURL(
8886
type="deb",
8987
namespace=None,
9088
name="a2ps",
9189
version="2.3.9",
92-
qualifiers=OrderedDict([("distro", "wheezy")]),
90+
qualifiers={"distro": "wheezy"},
9391
subpath=None,
9492
),
9593
PackageURL(
9694
type="deb",
9795
namespace=None,
9896
name="a2ps",
99-
version="1.11.1+dfsg-5+deb7u1",
100-
qualifiers=OrderedDict([("distro", "wheezy")]),
97+
version="0.11.1+dfsg-5+deb7u1",
98+
qualifiers={"distro": "wheezy"},
10199
subpath=None,
102100
),
103101
},
104-
vulnerability_id="CVE-2001-1593",
102+
resolved_package_urls=set(),
103+
references=[],
105104
),
106105
]
107106

vulnerabilities/tests/test_suse.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
import unittest
33
import xml.etree.ElementTree as ET
44

5-
from dephell_specifier import RangeSpecifier
6-
75

86
from vulnerabilities.oval_parser import OvalParser
97

@@ -95,19 +93,19 @@ def test_get_pkgs_from_obj(self):
9593
# it's object due to filters to avoid such tests in the first place
9694
assert pkg_set2 == {"cacti"}
9795

98-
def test_get_version_ranges_from_state(self):
96+
def test_get_version_range_from_state(self):
9997

10098
assert len(self.parsed_oval.oval_document.getStates()) == 4
10199

102100
state_1 = self.parsed_oval.oval_document.getStates()[0]
103101
state_2 = self.parsed_oval.oval_document.getStates()[1]
104102

105103
exp_range_1 = None
106-
exp_range_2 = RangeSpecifier("<1.2.11-lp151.3.6")
104+
exp_range_2 = "<1.2.11-lp151.3.6"
107105
# In a full run we wont get exp_range1 because we won't obtain
108106
# it's state due to filters to avoid such tests in the first place
109-
assert self.parsed_oval.get_version_ranges_from_state(state_1) == exp_range_1
110-
assert self.parsed_oval.get_version_ranges_from_state(state_2) == exp_range_2
107+
assert self.parsed_oval.get_version_range_from_state(state_1) == exp_range_1
108+
assert self.parsed_oval.get_version_range_from_state(state_2) == exp_range_2
111109

112110
def test_get_urls_from_definition(self):
113111

@@ -135,11 +133,11 @@ def test_get_data(self):
135133
"test_data": [
136134
{
137135
"package_list": ["cacti"],
138-
"version_ranges": RangeSpecifier("<1.2.11-lp151.3.6"),
136+
"version_ranges": "<1.2.11-lp151.3.6",
139137
},
140138
{
141139
"package_list": ["cacti-spine"],
142-
"version_ranges": RangeSpecifier("<1.2.11-lp151.3.6"),
140+
"version_ranges": "<1.2.11-lp151.3.6",
143141
},
144142
],
145143
"description": '\n Cacti 0.8.7e and earlier allows remote authenticated administrators to gain privileges by modifying the "Data Input Method" for the "Linux - Get Memory Usage" setting to contain arbitrary commands.\n ',
@@ -155,11 +153,11 @@ def test_get_data(self):
155153
"test_data": [
156154
{
157155
"package_list": ["apache2-mod_perl"],
158-
"version_ranges": RangeSpecifier("<2.0.11-lp151.3.3"),
156+
"version_ranges": "<2.0.11-lp151.3.3",
159157
},
160158
{
161159
"package_list": ["apache2-mod_perl-devel"],
162-
"version_ranges": RangeSpecifier("<2.0.11-lp151.3.3"),
160+
"version_ranges": "<2.0.11-lp151.3.3",
163161
},
164162
],
165163
"description": "\n mod_perl 2.0 through 2.0.10 allows attackers to execute arbitrary Perl code by placing it in a user-owned .htaccess file, because (contrary to the documentation) there is no configuration option that permits Perl code for the administrator's control of HTTP request processing without also permitting unprivileged users to run Perl code in the context of the user account that runs Apache HTTP Server processes.\n ",

vulnerabilities/tests/test_ubuntu.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from collections import OrderedDict
77
import asyncio
88

9-
from dephell_specifier import RangeSpecifier
109
from packageurl import PackageURL
1110

1211
from vulnerabilities.oval_parser import OvalParser
@@ -90,18 +89,18 @@ def test_get_pkgs_from_obj(self):
9089
assert pkg_set1 == {"potrace"}
9190
assert pkg_set2 == {"tor"}
9291

93-
def test_get_version_ranges_from_state(self):
92+
def test_get_version_range_from_state(self):
9493

9594
assert len(self.parsed_oval.oval_document.getStates()) == 2
9695

9796
state_1 = self.parsed_oval.oval_document.getStates()[0]
9897
state_2 = self.parsed_oval.oval_document.getStates()[1]
9998

100-
exp_range_1 = RangeSpecifier("<1.14-2")
101-
exp_range_2 = RangeSpecifier("<0.2.8.9-1ubuntu1")
99+
exp_range_1 = "<1.14-2"
100+
exp_range_2 = "<0.2.8.9-1ubuntu1"
102101

103-
assert self.parsed_oval.get_version_ranges_from_state(state_1) == exp_range_1
104-
assert self.parsed_oval.get_version_ranges_from_state(state_2) == exp_range_2
102+
assert self.parsed_oval.get_version_range_from_state(state_1) == exp_range_1
103+
assert self.parsed_oval.get_version_range_from_state(state_2) == exp_range_2
105104

106105
def test_get_urls_from_definition(self):
107106

@@ -131,7 +130,7 @@ def test_get_data(self):
131130
"test_data": [
132131
{
133132
"package_list": ["potrace"],
134-
"version_ranges": RangeSpecifier("<1.14-2"),
133+
"version_ranges": "<1.14-2",
135134
}
136135
],
137136
"description": "Heap-based buffer overflow in the bm_readbody_bmp function in bitmap_io.c in potrace before 1.13 allows remote attackers to have unspecified impact via a crafted BMP image, a different vulnerability than CVE-2016-8698, CVE-2016-8699, CVE-2016-8700, CVE-2016-8701, and CVE-2016-8702.",
@@ -146,7 +145,7 @@ def test_get_data(self):
146145
"test_data": [
147146
{
148147
"package_list": ["tor"],
149-
"version_ranges": RangeSpecifier("<0.2.8.9-1ubuntu1"),
148+
"version_ranges": "<0.2.8.9-1ubuntu1",
150149
}
151150
],
152151
"description": "Tor before 0.2.8.9 and 0.2.9.x before 0.2.9.4-alpha had internal functions that were entitled to expect that buf_t data had NUL termination, but the implementation of or/buffers.c did not ensure that NUL termination was present, which allows remote attackers to cause a denial of service (client, hidden service, relay, or authority crash) via crafted data.",

0 commit comments

Comments
 (0)