1616from packageurl import PackageURL
1717from pytz import UTC
1818from univers .version_range import GemVersionRange
19+ from univers .version_range import InvalidVersionRange
1920
20- from vulnerabilities .importer import AdvisoryData , AffectedPackageV2
21+ from vulnerabilities .importer import AdvisoryData
22+ from vulnerabilities .importer import AffectedPackageV2
2123from vulnerabilities .importer import ReferenceV2
2224from vulnerabilities .importer import VulnerabilitySeverity
2325from vulnerabilities .pipelines import VulnerableCodeBaseImporterPipelineV2
@@ -68,24 +70,30 @@ def clone(self):
6870 self .vcs_response = fetch_via_vcs (self .repo_url )
6971
7072 def advisories_count (self ):
71- return 10
73+ base_path = Path (self .vcs_response .dest_dir )
74+ return sum (1 for _ in base_path .rglob ("*.yml" ))
7275
7376 def collect_advisories (self ) -> Iterable [AdvisoryData ]:
7477 base_path = Path (self .vcs_response .dest_dir )
75- supported_subdir = ["rubies" , "gems" ]
76- for subdir in supported_subdir :
77- for file_path in base_path .glob (f"{ subdir } /**/*.yml" ):
78- if file_path .name .startswith ("OSVDB-" ):
79- continue
80-
81- raw_data = load_yaml (file_path )
82- advisory_id = file_path .stem
83- advisory_url = get_advisory_url (
84- file = file_path ,
85- base_path = base_path ,
86- url = "https://github.com/rubysec/ruby-advisory-db/blob/master/" ,
87- )
88- yield parse_ruby_advisory (advisory_id , raw_data , subdir , advisory_url )
78+ for file_path in base_path .rglob ("*.yml" ):
79+ if file_path .name .startswith ("OSVDB-" ):
80+ continue
81+
82+ if "gems" in file_path .parts :
83+ subdir = "gems"
84+ elif "rubies" in file_path .parts :
85+ subdir = "rubies"
86+ else :
87+ continue
88+
89+ raw_data = load_yaml (file_path )
90+ advisory_id = file_path .stem
91+ advisory_url = get_advisory_url (
92+ file = file_path ,
93+ base_path = base_path ,
94+ url = "https://github.com/rubysec/ruby-advisory-db/blob/master/" ,
95+ )
96+ yield parse_ruby_advisory (advisory_id , raw_data , subdir , advisory_url )
8997
9098 def clean_downloads (self ):
9199 if self .vcs_response :
@@ -107,36 +115,37 @@ def parse_ruby_advisory(advisory_id, record, schema_type, advisory_url):
107115
108116 if not package_name :
109117 logger .error ("Invalid package name" )
110- else :
111- purl = PackageURL ( type = "gem" , name = package_name )
112-
113- return AdvisoryData (
114- advisory_id = advisory_id ,
115- aliases = get_aliases (record ),
116- summary = get_summary (record ),
117- affected_packages = get_affected_packages (record , purl ),
118- references = get_references (record ),
119- severities = get_severities (record ),
120- date_published = get_publish_time (record ),
121- url = advisory_url ,
122- )
118+ return
119+
120+ purl = PackageURL ( type = "gem" , name = package_name )
121+ return AdvisoryData (
122+ advisory_id = advisory_id ,
123+ aliases = get_aliases (record ),
124+ summary = get_summary (record ),
125+ affected_packages = get_affected_packages (record , purl ),
126+ references = get_references (record ),
127+ severities = get_severities (record ),
128+ date_published = get_publish_time (record ),
129+ url = advisory_url ,
130+ )
123131
124132 elif schema_type == "rubies" :
125133 engine = record .get ("engine" ) # engine enum: [jruby, rbx, ruby]
126134 if not engine :
127135 logger .error ("Invalid engine name" )
128- else :
129- purl = PackageURL (type = "ruby" , name = engine )
130- return AdvisoryData (
131- advisory_id = advisory_id ,
132- aliases = get_aliases (record ),
133- summary = get_summary (record ),
134- affected_packages = get_affected_packages (record , purl ),
135- severities = get_severities (record ),
136- references = get_references (record ),
137- date_published = get_publish_time (record ),
138- url = advisory_url ,
139- )
136+ return
137+
138+ purl = PackageURL (type = "ruby" , name = engine )
139+ return AdvisoryData (
140+ advisory_id = advisory_id ,
141+ aliases = get_aliases (record ),
142+ summary = get_summary (record ),
143+ affected_packages = get_affected_packages (record , purl ),
144+ severities = get_severities (record ),
145+ references = get_references (record ),
146+ date_published = get_publish_time (record ),
147+ url = advisory_url ,
148+ )
140149
141150
142151def get_affected_packages (record , purl ):
@@ -145,27 +154,32 @@ def get_affected_packages(record, purl):
145154 ( patched_versions , unaffected_versions ) then passing the purl and the inverted safe_version_range
146155 to the AffectedPackage object
147156 """
148- safe_version_ranges = record .get ("patched_versions" , [])
149- # this case happens when the advisory contain only 'patched_versions' field
150- # and it has value None(i.e it is empty :( ).
151- if not safe_version_ranges :
152- safe_version_ranges = []
153- safe_version_ranges += record .get ("unaffected_versions" , [])
154- safe_version_ranges = [i for i in safe_version_ranges if i ]
155-
156157 affected_packages = []
157- affected_version_ranges = [
158- GemVersionRange .from_native (elem ).invert () for elem in safe_version_ranges
159- ]
160-
161- for affected_version_range in affected_version_ranges :
162- affected_packages .append (
163- AffectedPackageV2 (
164- package = purl ,
165- affected_version_range = affected_version_range ,
166- fixed_version_range = None
158+ for unaffected_version in record .get ("unaffected_versions" , []):
159+ try :
160+ affected_version_range = GemVersionRange .from_native (unaffected_version ).invert ()
161+ affected_packages .append (
162+ AffectedPackageV2 (
163+ package = purl ,
164+ affected_version_range = affected_version_range ,
165+ fixed_version_range = None ,
166+ )
167167 )
168- )
168+ except InvalidVersionRange as e :
169+ logger .error (f"InvalidVersionRange { e } " )
170+
171+ for patched_version in record .get ("patched_versions" , []):
172+ try :
173+ fixed_version_range = GemVersionRange .from_native (patched_version )
174+ affected_packages .append (
175+ AffectedPackageV2 (
176+ package = purl ,
177+ affected_version_range = None ,
178+ fixed_version_range = fixed_version_range ,
179+ )
180+ )
181+ except InvalidVersionRange as e :
182+ logger .error (f"InvalidVersionRange { e } " )
169183 return affected_packages
170184
171185
@@ -205,7 +219,7 @@ def get_severities(record):
205219
206220 cvss_v3 = record .get ("cvss_v3" )
207221 if cvss_v3 :
208- severities .append (VulnerabilitySeverity (system = CVSSV3 , value = cvss_v4 ))
222+ severities .append (VulnerabilitySeverity (system = CVSSV3 , value = cvss_v3 ))
209223
210224 cvss_v2 = record .get ("cvss_v2" )
211225 if cvss_v2 :
0 commit comments