Skip to content

Commit 6539804

Browse files
committed
Refactor Ruby importer and improver
Signed-off-by: ziadhany <ziadhany2016@gmail.com>
1 parent eeca595 commit 6539804

7 files changed

Lines changed: 376 additions & 54 deletions

File tree

vulnerabilities/importers/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@
6565
xen.XenImporter,
6666
ubuntu_usn.UbuntuUSNImporter,
6767
fireeye.FireyeImporter,
68-
ruby.RubyImporter,
6968
apache_kafka.ApacheKafkaImporter,
69+
ruby.RubyImporter,
7070
]
7171

7272
IMPORTERS_REGISTRY = {x.qualified_name: x for x in IMPORTERS_REGISTRY}

vulnerabilities/importers/ruby.py

Lines changed: 7 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -12,39 +12,29 @@
1212
from typing import Iterable
1313

1414
from dateutil.parser import parse
15-
from django.db.models import QuerySet
1615
from packageurl import PackageURL
1716
from pytz import UTC
1817
from univers.version_range import GemVersionRange
19-
from univers.versions import RubygemsVersion
2018

2119
from vulnerabilities.importer import AdvisoryData
2220
from vulnerabilities.importer import AffectedPackage
23-
from vulnerabilities.importer import GitImporter
21+
from vulnerabilities.importer import Importer
2422
from vulnerabilities.importer import Reference
2523
from vulnerabilities.importer import VulnerabilitySeverity
26-
from vulnerabilities.improver import Improver
27-
from vulnerabilities.improver import Inference
28-
from vulnerabilities.improvers.valid_versions import ValidVersionImprover
29-
from vulnerabilities.models import Advisory
30-
from vulnerabilities.package_managers import RubyVersionAPI
3124
from vulnerabilities.severity_systems import SCORING_SYSTEMS
3225
from vulnerabilities.utils import build_description
33-
from vulnerabilities.utils import evolve_purl
3426
from vulnerabilities.utils import load_yaml
3527

3628
logger = logging.getLogger(__name__)
3729

3830

39-
class RubyImporter(GitImporter):
31+
class RubyImporter(Importer):
4032
license_url = "https://github.com/rubysec/ruby-advisory-db/blob/master/LICENSE.txt"
4133
spdx_license_expression = "unknown"
42-
43-
def __init__(self):
44-
super().__init__(repo_url="git+https://github.com/rubysec/ruby-advisory-db")
34+
repo_url = "git+https://github.com/rubysec/ruby-advisory-db"
4535

4636
def advisory_data(self) -> Iterable[AdvisoryData]:
47-
self.clone()
37+
self.clone(self.repo_url)
4838
base_path = Path(self.vcs_response.dest_dir)
4939
supported_subdir = ["rubies", "gems"]
5040
for subdir in supported_subdir:
@@ -63,9 +53,9 @@ def parse_ruby_advisory(record, schema_type):
6353
"""
6454
if schema_type == "gems":
6555
package_name = record.get("gem")
66-
library = record.get("library")
67-
framework = record.get("framework")
68-
platform = record.get("platform")
56+
library = record.get("library") # not used
57+
framework = record.get("framework") # not used
58+
platform = record.get("platform") # not used
6959
purl = PackageURL(type="gem", name=package_name)
7060

7161
return AdvisoryData(
@@ -160,39 +150,3 @@ def get_summary(record):
160150
title = record.get("title")
161151
description = record.get("description", "")
162152
return build_description(summary=title, description=description)
163-
164-
165-
class RubyImprover(Improver):
166-
pkg_manager_api = RubyVersionAPI()
167-
168-
@property
169-
def interesting_advisories(self) -> QuerySet:
170-
return Advisory.objects.filter(created_by=RubyImporter.qualified_name)
171-
172-
def get_inferences(self, advisory_data) -> Iterable[Inference]:
173-
for affected_package in advisory_data.affected_packages:
174-
purl = affected_package.package
175-
pkg_name = purl.name
176-
all_vers_pkgs = self.pkg_manager_api.fetch(pkg_name)
177-
178-
safe_versions = []
179-
affected_purls = []
180-
for pkg_version in all_vers_pkgs:
181-
vobj = RubygemsVersion(pkg_version.value)
182-
try:
183-
if vobj in affected_package.affected_version_range:
184-
new_purl = evolve_purl(purl=purl, version=str(pkg_version.value))
185-
affected_purls.append(new_purl)
186-
else:
187-
safe_versions.append(pkg_version.value)
188-
except Exception as e:
189-
logger.error(f"{e}")
190-
191-
for fixed_version in safe_versions:
192-
fixed_purl = evolve_purl(purl=purl, version=str(fixed_version))
193-
yield Inference.from_advisory_data(
194-
advisory_data,
195-
confidence=90,
196-
affected_purls=affected_purls,
197-
fixed_purl=fixed_purl,
198-
)

vulnerabilities/improvers/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
valid_versions.IstioImprover,
2525
valid_versions.DebianOvalImprover,
2626
valid_versions.UbuntuOvalImprover,
27+
valid_versions.RubyImprover,
2728
]
2829

2930
IMPROVERS_REGISTRY = {x.qualified_name: x for x in IMPROVERS_REGISTRY}

vulnerabilities/improvers/valid_versions.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from django.db.models.query import QuerySet
2020
from packageurl import PackageURL
2121
from univers.versions import NginxVersion
22+
from univers.versions import RubygemsVersion
2223

2324
from vulnerabilities.importer import AdvisoryData
2425
from vulnerabilities.importer import AffectedPackage
@@ -35,6 +36,7 @@
3536
from vulnerabilities.importers.istio import IstioImporter
3637
from vulnerabilities.importers.nginx import NginxImporter
3738
from vulnerabilities.importers.npm import NpmImporter
39+
from vulnerabilities.importers.ruby import RubyImporter
3840
from vulnerabilities.importers.ubuntu import UbuntuImporter
3941
from vulnerabilities.improver import MAX_CONFIDENCE
4042
from vulnerabilities.improver import Improver
@@ -43,6 +45,7 @@
4345
from vulnerabilities.package_managers import GitHubTagsAPI
4446
from vulnerabilities.package_managers import GoproxyVersionAPI
4547
from vulnerabilities.package_managers import PackageVersion
48+
from vulnerabilities.package_managers import RubyVersionAPI
4649
from vulnerabilities.package_managers import VersionAPI
4750
from vulnerabilities.package_managers import get_api_package_name
4851
from vulnerabilities.package_managers import get_version_fetcher
@@ -477,3 +480,47 @@ class DebianOvalImprover(ValidVersionImprover):
477480
class UbuntuOvalImprover(ValidVersionImprover):
478481
importer = UbuntuImporter
479482
ignorable_versions = []
483+
484+
485+
class RubyImprover(ValidVersionImprover):
486+
importer = RubyImporter
487+
ignorable_versions = []
488+
489+
def get_inferences(self, advisory_data) -> Iterable[Inference]:
490+
491+
try:
492+
purl, affected_version_ranges, fixed_versions = AffectedPackage.merge(
493+
advisory_data.affected_packages
494+
)
495+
except UnMergeablePackageError:
496+
logger.error(
497+
f"RubyImprover: Cannot merge with different purls: "
498+
f"{advisory_data.affected_packages!r}"
499+
)
500+
return iter([])
501+
502+
all_vers_pkgs = self.get_package_versions(purl)
503+
affected_purls = []
504+
505+
for pkg_version in all_vers_pkgs:
506+
vobj = RubygemsVersion(pkg_version)
507+
508+
affected_version = True
509+
for affected_version_range in affected_version_ranges:
510+
if vobj not in affected_version_range:
511+
affected_version = False
512+
513+
if affected_version:
514+
new_purl = evolve_purl(purl=purl, version=str(pkg_version))
515+
affected_purls.append(new_purl)
516+
else:
517+
fixed_versions.append(RubygemsVersion(pkg_version))
518+
519+
for fixed_version in fixed_versions:
520+
fixed_purl = evolve_purl(purl=purl, version=str(fixed_version))
521+
yield Inference.from_advisory_data(
522+
advisory_data,
523+
confidence=90,
524+
affected_purls=affected_purls,
525+
fixed_purl=fixed_purl,
526+
)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
[
2+
{
3+
"aliases": [
4+
"CVE-2018-7212"
5+
],
6+
"summary": "sinatra ruby gem path traversal via backslash characters on Windows\nAn issue was discovered in rack-protection/lib/rack/protection/path_traversal.rb\nin Sinatra 2.x before 2.0.1 on Windows. Path traversal is possible via backslash\ncharacters.",
7+
"affected_packages": [
8+
{
9+
"package": {
10+
"type": "gem",
11+
"namespace": null,
12+
"name": "sinatra",
13+
"version": null,
14+
"qualifiers": null,
15+
"subpath": null
16+
},
17+
"affected_version_range": "vers:gem/<2.0.1",
18+
"fixed_version": null
19+
},
20+
{
21+
"package": {
22+
"type": "gem",
23+
"namespace": null,
24+
"name": "sinatra",
25+
"version": null,
26+
"qualifiers": null,
27+
"subpath": null
28+
},
29+
"affected_version_range": "vers:gem/>1.0.0",
30+
"fixed_version": null
31+
}
32+
],
33+
"references": [
34+
{
35+
"reference_id": "",
36+
"url": "https://github.com/sinatra/sinatra/pull/1379",
37+
"severities": [
38+
{
39+
"system": "cvssv2",
40+
"value": "5.0",
41+
"scoring_elements": ""
42+
}
43+
]
44+
},
45+
{
46+
"reference_id": "",
47+
"url": "https://github.com/sinatra/sinatra/pull/1379",
48+
"severities": [
49+
{
50+
"system": "cvssv3",
51+
"value": "5.3",
52+
"scoring_elements": ""
53+
}
54+
]
55+
}
56+
],
57+
"date_published": "2018-01-09T00:00:00+00:00",
58+
"weaknesses": []
59+
}
60+
]

0 commit comments

Comments
 (0)