Skip to content

Commit

Permalink
Refactor Ruby importer and improver
Browse files Browse the repository at this point in the history
Signed-off-by: ziadhany <ziadhany2016@gmail.com>
  • Loading branch information
ziadhany committed May 16, 2023
1 parent eeca595 commit 6539804
Show file tree
Hide file tree
Showing 7 changed files with 376 additions and 54 deletions.
2 changes: 1 addition & 1 deletion vulnerabilities/importers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@
xen.XenImporter,
ubuntu_usn.UbuntuUSNImporter,
fireeye.FireyeImporter,
ruby.RubyImporter,
apache_kafka.ApacheKafkaImporter,
ruby.RubyImporter,
]

IMPORTERS_REGISTRY = {x.qualified_name: x for x in IMPORTERS_REGISTRY}
60 changes: 7 additions & 53 deletions vulnerabilities/importers/ruby.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,39 +12,29 @@
from typing import Iterable

from dateutil.parser import parse
from django.db.models import QuerySet
from packageurl import PackageURL
from pytz import UTC
from univers.version_range import GemVersionRange
from univers.versions import RubygemsVersion

from vulnerabilities.importer import AdvisoryData
from vulnerabilities.importer import AffectedPackage
from vulnerabilities.importer import GitImporter
from vulnerabilities.importer import Importer
from vulnerabilities.importer import Reference
from vulnerabilities.importer import VulnerabilitySeverity
from vulnerabilities.improver import Improver
from vulnerabilities.improver import Inference
from vulnerabilities.improvers.valid_versions import ValidVersionImprover
from vulnerabilities.models import Advisory
from vulnerabilities.package_managers import RubyVersionAPI
from vulnerabilities.severity_systems import SCORING_SYSTEMS
from vulnerabilities.utils import build_description
from vulnerabilities.utils import evolve_purl
from vulnerabilities.utils import load_yaml

logger = logging.getLogger(__name__)


class RubyImporter(GitImporter):
class RubyImporter(Importer):
license_url = "https://github.com/rubysec/ruby-advisory-db/blob/master/LICENSE.txt"
spdx_license_expression = "unknown"

def __init__(self):
super().__init__(repo_url="git+https://github.com/rubysec/ruby-advisory-db")
repo_url = "git+https://github.com/rubysec/ruby-advisory-db"

def advisory_data(self) -> Iterable[AdvisoryData]:
self.clone()
self.clone(self.repo_url)
base_path = Path(self.vcs_response.dest_dir)
supported_subdir = ["rubies", "gems"]
for subdir in supported_subdir:
Expand All @@ -63,9 +53,9 @@ def parse_ruby_advisory(record, schema_type):
"""
if schema_type == "gems":
package_name = record.get("gem")
library = record.get("library")
framework = record.get("framework")
platform = record.get("platform")
library = record.get("library") # not used
framework = record.get("framework") # not used
platform = record.get("platform") # not used
purl = PackageURL(type="gem", name=package_name)

return AdvisoryData(
Expand Down Expand Up @@ -160,39 +150,3 @@ def get_summary(record):
title = record.get("title")
description = record.get("description", "")
return build_description(summary=title, description=description)


class RubyImprover(Improver):
pkg_manager_api = RubyVersionAPI()

@property
def interesting_advisories(self) -> QuerySet:
return Advisory.objects.filter(created_by=RubyImporter.qualified_name)

def get_inferences(self, advisory_data) -> Iterable[Inference]:
for affected_package in advisory_data.affected_packages:
purl = affected_package.package
pkg_name = purl.name
all_vers_pkgs = self.pkg_manager_api.fetch(pkg_name)

safe_versions = []
affected_purls = []
for pkg_version in all_vers_pkgs:
vobj = RubygemsVersion(pkg_version.value)
try:
if vobj in affected_package.affected_version_range:
new_purl = evolve_purl(purl=purl, version=str(pkg_version.value))
affected_purls.append(new_purl)
else:
safe_versions.append(pkg_version.value)
except Exception as e:
logger.error(f"{e}")

for fixed_version in safe_versions:
fixed_purl = evolve_purl(purl=purl, version=str(fixed_version))
yield Inference.from_advisory_data(
advisory_data,
confidence=90,
affected_purls=affected_purls,
fixed_purl=fixed_purl,
)
1 change: 1 addition & 0 deletions vulnerabilities/improvers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
valid_versions.IstioImprover,
valid_versions.DebianOvalImprover,
valid_versions.UbuntuOvalImprover,
valid_versions.RubyImprover,
]

IMPROVERS_REGISTRY = {x.qualified_name: x for x in IMPROVERS_REGISTRY}
47 changes: 47 additions & 0 deletions vulnerabilities/improvers/valid_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from django.db.models.query import QuerySet
from packageurl import PackageURL
from univers.versions import NginxVersion
from univers.versions import RubygemsVersion

from vulnerabilities.importer import AdvisoryData
from vulnerabilities.importer import AffectedPackage
Expand All @@ -35,6 +36,7 @@
from vulnerabilities.importers.istio import IstioImporter
from vulnerabilities.importers.nginx import NginxImporter
from vulnerabilities.importers.npm import NpmImporter
from vulnerabilities.importers.ruby import RubyImporter
from vulnerabilities.importers.ubuntu import UbuntuImporter
from vulnerabilities.improver import MAX_CONFIDENCE
from vulnerabilities.improver import Improver
Expand All @@ -43,6 +45,7 @@
from vulnerabilities.package_managers import GitHubTagsAPI
from vulnerabilities.package_managers import GoproxyVersionAPI
from vulnerabilities.package_managers import PackageVersion
from vulnerabilities.package_managers import RubyVersionAPI
from vulnerabilities.package_managers import VersionAPI
from vulnerabilities.package_managers import get_api_package_name
from vulnerabilities.package_managers import get_version_fetcher
Expand Down Expand Up @@ -477,3 +480,47 @@ class DebianOvalImprover(ValidVersionImprover):
class UbuntuOvalImprover(ValidVersionImprover):
importer = UbuntuImporter
ignorable_versions = []


class RubyImprover(ValidVersionImprover):
importer = RubyImporter
ignorable_versions = []

def get_inferences(self, advisory_data) -> Iterable[Inference]:

try:
purl, affected_version_ranges, fixed_versions = AffectedPackage.merge(
advisory_data.affected_packages
)
except UnMergeablePackageError:
logger.error(
f"RubyImprover: Cannot merge with different purls: "
f"{advisory_data.affected_packages!r}"
)
return iter([])

all_vers_pkgs = self.get_package_versions(purl)
affected_purls = []

for pkg_version in all_vers_pkgs:
vobj = RubygemsVersion(pkg_version)

affected_version = True
for affected_version_range in affected_version_ranges:
if vobj not in affected_version_range:
affected_version = False

if affected_version:
new_purl = evolve_purl(purl=purl, version=str(pkg_version))
affected_purls.append(new_purl)
else:
fixed_versions.append(RubygemsVersion(pkg_version))

for fixed_version in fixed_versions:
fixed_purl = evolve_purl(purl=purl, version=str(fixed_version))
yield Inference.from_advisory_data(
advisory_data,
confidence=90,
affected_purls=affected_purls,
fixed_purl=fixed_purl,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
[
{
"aliases": [
"CVE-2018-7212"
],
"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.",
"affected_packages": [
{
"package": {
"type": "gem",
"namespace": null,
"name": "sinatra",
"version": null,
"qualifiers": null,
"subpath": null
},
"affected_version_range": "vers:gem/<2.0.1",
"fixed_version": null
},
{
"package": {
"type": "gem",
"namespace": null,
"name": "sinatra",
"version": null,
"qualifiers": null,
"subpath": null
},
"affected_version_range": "vers:gem/>1.0.0",
"fixed_version": null
}
],
"references": [
{
"reference_id": "",
"url": "https://github.com/sinatra/sinatra/pull/1379",
"severities": [
{
"system": "cvssv2",
"value": "5.0",
"scoring_elements": ""
}
]
},
{
"reference_id": "",
"url": "https://github.com/sinatra/sinatra/pull/1379",
"severities": [
{
"system": "cvssv3",
"value": "5.3",
"scoring_elements": ""
}
]
}
],
"date_published": "2018-01-09T00:00:00+00:00",
"weaknesses": []
}
]
Loading

0 comments on commit 6539804

Please sign in to comment.