Skip to content

Commit 8897af9

Browse files
committed
[WIP] Adding a TimeTravel improver for nginx
---------------------NOT READY FOR REVIEW YET-------------------- This is not the best way. Maybe we want a generic time travel improver which could run on multiple data source. This is highly experimental and is meant to serve as proof of work for current model. Currently, this is incomplete and doesn't work. The classes and functions used in time travel have not been ported properly. This commit might need a full rewrite Signed-off-by: Hritik Vijay <hritikxx8@gmail.com>
1 parent 54dcc51 commit 8897af9

File tree

3 files changed

+79
-24
lines changed

3 files changed

+79
-24
lines changed

vulnerabilities/helpers.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ def requests_with_5xx_retry(max_retries=5, backoff_factor=0.5):
124124

125125
def nearest_patched_package(
126126
vulnerable_packages: List[PackageURL], resolved_packages: List[PackageURL]
127-
) -> List[AffectedPackage]:
127+
) -> List[Tuple]:
128128
class PackageURLWithVersionComparator:
129129
"""
130130
This class is used to get around bisect module's lack of supplying custom
@@ -158,11 +158,12 @@ def __lt__(self, other):
158158
if patched_package_index < resolved_package_count:
159159
patched_package = resolved_packages[patched_package_index].package
160160

161-
affected_package_with_patched_package_objects.append(
162-
AffectedPackage(
163-
vulnerable_package=vulnerable_package.package, patched_package=patched_package
164-
)
165-
)
161+
# affected_package_with_patched_package_objects.append(
162+
# AffectedPackage(
163+
# vulnerable_package=vulnerable_package.package, patched_package=patched_package
164+
# )
165+
# )
166+
affected_package_with_patched_package_objects.append((vulnerable_package.package, patched_package))
166167

167168
return affected_package_with_patched_package_objects
168169

vulnerabilities/importers/nginx.py

Lines changed: 67 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@
3636
from vulnerabilities.data_source import DataSource
3737
from vulnerabilities.data_source import DataSourceConfiguration
3838
from vulnerabilities.data_source import Reference
39+
from vulnerabilities.data_inference import Inference
40+
from vulnerabilities.data_inference import Improver
3941
from vulnerabilities.package_managers import GitHubTagsAPI
4042
from vulnerabilities.package_managers import Version
4143
from vulnerabilities.helpers import nearest_patched_package
42-
44+
from vulnerabilities.models import Advisory
4345

4446
@dataclasses.dataclass
4547
class NginxDataSourceConfiguration(DataSourceConfiguration):
@@ -51,21 +53,6 @@ class NginxDataSource(DataSource):
5153

5254
url = "http://nginx.org/en/security_advisories.html"
5355

54-
def set_api(self):
55-
self.version_api = GitHubTagsAPI()
56-
asyncio.run(self.version_api.load_api(["nginx/nginx"]))
57-
58-
# For some reason nginx tags it's releases are in the form of `release-1.2.3`
59-
# Chop off the `release-` part here.
60-
normalized_versions = set()
61-
while self.version_api.cache["nginx/nginx"]:
62-
version = self.version_api.cache["nginx/nginx"].pop()
63-
normalized_version = Version(
64-
version.value.replace("release-", ""), version.release_date
65-
)
66-
normalized_versions.add(normalized_version)
67-
self.version_api.cache["nginx/nginx"] = normalized_versions
68-
6956
def advisory_data(self) -> List[AdvisoryData]:
7057
adv_data = []
7158
# self.set_api()
@@ -170,7 +157,9 @@ def extract_vuln_pkgs(self, vuln_info):
170157
if "-" not in version_info:
171158
# These are discrete versions
172159
version_ranges.append(
173-
VersionSpecifier.from_scheme_version_spec_string("semver", version_info[0])
160+
VersionSpecifier.from_scheme_version_spec_string(
161+
"semver", version_info[0]
162+
)
174163
)
175164
continue
176165

@@ -195,6 +184,67 @@ def extract_vuln_pkgs(self, vuln_info):
195184
]
196185

197186

187+
class NginxTimeTravel(Improver):
188+
def infer(self):
189+
self.set_api()
190+
advisories = Advisory.objects.filter(
191+
source="vulnerabilities.importers.nginx.NginxDataSource"
192+
)
193+
inferences = []
194+
for advisory in advisories:
195+
advisory_data = AdvisoryData.from_json(advisory.data)
196+
197+
affected_package_ranges = [
198+
pkg.version_specifier for pkg in advisory_data.affected_packages
199+
]
200+
affected_package_versions = find_valid_versions(
201+
self.version_api.get("nginx/nginx").valid_versions,
202+
affected_package_ranges,
203+
)
204+
affected_packages = []
205+
for pkg in advisory_data.affected_packages:
206+
for
207+
affected_packages.extend([])
208+
affected_packages = [advisory_data.affected_packages]
209+
210+
fixed_package_ranges = [
211+
pkg.version_specifier for pkg in advisory_data.affected_packages
212+
]
213+
fixed_packages = find_valid_versions(
214+
self.version_api.get("nginx/nginx").valid_versions, fixed_package_ranges
215+
)
216+
217+
pkgs = nearest_patched_package(affected_package_versions, fixed_package_ranges)
218+
for pkg in pkgs:
219+
print(pkg)
220+
print(type(pkg))
221+
inferences.append(
222+
Inference(
223+
confidence=90, # TODO: Decide properly
224+
vulnerability_id=advisory_data.vulnerability_id,
225+
affected_packages=pkg[0],
226+
fixed_packages=pkg[1],
227+
)
228+
)
229+
230+
return inferences
231+
232+
def set_api(self):
233+
self.version_api = GitHubTagsAPI()
234+
asyncio.run(self.version_api.load_api(["nginx/nginx"]))
235+
236+
# For some reason nginx tags it's releases are in the form of `release-1.2.3`
237+
# Chop off the `release-` part here.
238+
normalized_versions = set()
239+
while self.version_api.cache["nginx/nginx"]:
240+
version = self.version_api.cache["nginx/nginx"].pop()
241+
normalized_version = Version(
242+
version.value.replace("release-", ""), version.release_date
243+
)
244+
normalized_versions.add(normalized_version)
245+
self.version_api.cache["nginx/nginx"] = normalized_versions
246+
247+
198248
def find_valid_versions(versions, version_ranges):
199249
valid_versions = set()
200250
for version in versions:

vulnerabilities/improvers/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
from vulnerabilities import importers
12
from . import nginx
23
from . import default
34

4-
IMPROVER_REGISTRY = [default.DefaultImprover]
5+
IMPROVER_REGISTRY = [
6+
default.DefaultImprover,
7+
importers.nginx.NginxTimeTravel,
8+
]
59

610
improver_mapping = {f"{x.__module__}.{x.__name__}": x for x in IMPROVER_REGISTRY}

0 commit comments

Comments
 (0)