2626from typing import List
2727from typing import Mapping
2828from typing import Optional
29- from typing import Tuple
3029
3130from dateutil import parser as dateparser
3231from django .db .models .query import QuerySet
3332from packageurl import PackageURL
34- from univers .version_range import VersionRange
3533from univers .version_range import build_range_from_github_advisory_constraint
3634
3735from vulnerabilities import helpers
4038from vulnerabilities .helpers import get_affected_packages_by_patched_package
4139from vulnerabilities .helpers import get_item
4240from vulnerabilities .helpers import nearest_patched_package
41+ from vulnerabilities .helpers import resolve_version_range
4342from vulnerabilities .importer import AdvisoryData
4443from vulnerabilities .importer import AffectedPackage
4544from vulnerabilities .importer import Importer
4948from vulnerabilities .improver import Improver
5049from vulnerabilities .improver import Inference
5150from vulnerabilities .models import Advisory
52- from vulnerabilities .package_managers import ComposerVersionAPI
51+ from vulnerabilities .package_managers import VERSION_API_CLASSES_BY_PACKAGE_TYPE
5352from vulnerabilities .package_managers import GoproxyVersionAPI
54- from vulnerabilities .package_managers import MavenVersionAPI
55- from vulnerabilities .package_managers import NugetVersionAPI
56- from vulnerabilities .package_managers import PypiVersionAPI
57- from vulnerabilities .package_managers import RubyVersionAPI
5853from vulnerabilities .package_managers import VersionAPI
54+ from vulnerabilities .package_managers import get_api_package_name
5955
6056logger = logging .getLogger (__name__ )
6157
171167}
172168"""
173169
174- VERSION_API_CLASSES = [
175- MavenVersionAPI ,
176- NugetVersionAPI ,
177- ComposerVersionAPI ,
178- PypiVersionAPI ,
179- RubyVersionAPI ,
180- GoproxyVersionAPI ,
181- ]
182-
183- VERSION_API_CLASSES_BY_PACKAGE_TYPE = {cls .package_type : cls for cls in VERSION_API_CLASSES }
184-
185170
186171class GitHubAPIImporter (Importer ):
187172 spdx_license_expression = "CC-BY-4.0"
@@ -205,38 +190,6 @@ def advisory_data(self) -> Iterable[AdvisoryData]:
205190 break
206191
207192
208- def get_reference_id (url : str ):
209- """
210- Return the reference id from a URL
211- For example:
212- >>> get_reference_id("https://github.com/advisories/GHSA-c9hw-wf7x-jp9j")
213- 'GHSA-c9hw-wf7x-jp9j'
214- """
215- url_parts = url .split ("/" )
216- last_url_part = url_parts [- 1 ]
217- return last_url_part
218-
219-
220- def extract_references (reference_data : List [dict ]) -> Iterable [Reference ]:
221- """
222- Yield `reference` by iterating over `reference_data`
223- >>> list(extract_references([{'url': "https://github.com/advisories/GHSA-c9hw-wf7x-jp9j"}]))
224- [Reference(url="https://github.com/advisories/GHSA-c9hw-wf7x-jp9j"), reference_id = "GHSA-c9hw-wf7x-jp9j" ]
225- >>> list(extract_references([{'url': "https://github.com/advisories/c9hw-wf7x-jp9j"}]))
226- [Reference(url="https://github.com/advisories/c9hw-wf7x-jp9j")]
227- """
228- for ref in reference_data :
229- url = ref ["url" ]
230- if not isinstance (url , str ):
231- logger .error (f"extract_references: url is not of type `str`: { url } " )
232- continue
233- if "GHSA-" in url .upper ():
234- reference = Reference (url = url , reference_id = get_reference_id (url ))
235- else :
236- reference = Reference (url = url )
237- yield reference
238-
239-
240193def get_purl (pkg_type : str , github_name : str ) -> Optional [PackageURL ]:
241194 """
242195 Return a PackageURL by splitting the `github_name` using the `pkg_type` convention.
@@ -272,26 +225,6 @@ class InvalidVersionRange(Exception):
272225 """
273226
274227
275- def get_api_package_name (purl : PackageURL ) -> str :
276- """
277- Return the package name expected by the GitHub API given a PackageURL
278- >>> get_api_package_name(PackageURL(type="maven", namespace="org.apache.commons", name="commons-lang3"))
279- "org.apache.commons:commons-lang3"
280- >>> get_api_package_name(PackageURL(type="composer", namespace="foo", name="bar"))
281- "foo/bar"
282- """
283- if purl .type == "maven" :
284- return f"{ purl .namespace } :{ purl .name } "
285-
286- if purl .type == "composer" :
287- return f"{ purl .namespace } /{ purl .name } "
288-
289- if purl .type in ("nuget" , "pypi" , "gem" , "golang" ):
290- return purl .name
291-
292- logger .error (f"get_api_package_name: Unknown PURL { purl !r} " )
293-
294-
295228def process_response (resp : dict , package_type : str ) -> Iterable [AdvisoryData ]:
296229 """
297230 Yield `AdvisoryData` by taking `resp` and `ecosystem` as input
@@ -349,7 +282,8 @@ def process_response(resp: dict, package_type: str) -> Iterable[AdvisoryData]:
349282
350283 references = get_item (advisory , "references" ) or []
351284 if references :
352- references : List [Reference ] = list (extract_references (references ))
285+ urls = (ref ["url" ] for ref in references )
286+ references = [Reference .from_url (u ) for u in urls ]
353287
354288 summary = get_item (advisory , "summary" )
355289 identifiers = get_item (advisory , "identifiers" ) or []
@@ -451,6 +385,7 @@ def get_inferences(self, advisory_data: AdvisoryData) -> Iterable[Inference]:
451385 aff_vers , unaff_vers = resolve_version_range (
452386 affected_version_range = affected_version_range ,
453387 package_versions = valid_versions ,
388+ ignorable_versions = WEIRD_IGNORABLE_VERSIONS ,
454389 )
455390 affected_purls = [
456391 PackageURL (type = pkg_type , namespace = pkg_namespace , name = pkg_name , version = version )
@@ -476,37 +411,3 @@ def get_inferences(self, advisory_data: AdvisoryData) -> Iterable[Inference]:
476411 affected_purls = affected_packages ,
477412 fixed_purl = fixed_package ,
478413 )
479-
480-
481- def resolve_version_range (
482- affected_version_range : VersionRange ,
483- package_versions : List [str ],
484- ignorable_versions = WEIRD_IGNORABLE_VERSIONS ,
485- ) -> Tuple [List [str ], List [str ]]:
486- """
487- Given an affected version range and a list of `package_versions`, resolve
488- which versions are in this range and return a tuple of two lists of
489- `affected_versions` and `unaffected_versions`.
490- """
491- if not affected_version_range :
492- logger .error (f"affected version range is { affected_version_range !r} " )
493- return [], []
494- affected_versions = []
495- unaffected_versions = []
496- for package_version in package_versions or []:
497- if package_version in ignorable_versions :
498- continue
499- # Remove whitespace
500- package_version = package_version .replace (" " , "" )
501- # Remove leading 'v'
502- package_version = package_version .lstrip ("vV" )
503- try :
504- version = affected_version_range .version_class (package_version )
505- except Exception :
506- logger .error (f"Could not parse version { package_version !r} " )
507- continue
508- if version in affected_version_range :
509- affected_versions .append (package_version )
510- else :
511- unaffected_versions .append (package_version )
512- return affected_versions , unaffected_versions
0 commit comments