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 severity_systems
4543from vulnerabilities .improver import Improver
4644from vulnerabilities .improver import Inference
4745from vulnerabilities .models import Advisory
48- from vulnerabilities .package_managers import ComposerVersionAPI
46+ from vulnerabilities .package_managers import VERSION_API_CLASSES_BY_PACKAGE_TYPE
4947from vulnerabilities .package_managers import GoproxyVersionAPI
50- from vulnerabilities .package_managers import MavenVersionAPI
51- from vulnerabilities .package_managers import NugetVersionAPI
52- from vulnerabilities .package_managers import PypiVersionAPI
53- from vulnerabilities .package_managers import RubyVersionAPI
5448from vulnerabilities .package_managers import VersionAPI
49+ from vulnerabilities .package_managers import get_api_package_name
5550from vulnerabilities .utils import AffectedPackage as LegacyAffectedPackage
5651from vulnerabilities .utils import get_affected_packages_by_patched_package
5752from vulnerabilities .utils import get_item
5853from vulnerabilities .utils import nearest_patched_package
54+ from vulnerabilities .utils import resolve_version_range
5955
6056logger = logging .getLogger (__name__ )
6157
129125 "COMPOSER" : "composer" ,
130126 "PIP" : "pypi" ,
131127 "RUBYGEMS" : "gem" ,
132- "GO" : "golang" ,
128+ # "GO": "golang",
133129}
134130
135131GITHUB_ECOSYSTEM_BY_PACKAGE_TYPE = {
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.
@@ -255,8 +208,7 @@ def get_purl(pkg_type: str, github_name: str) -> Optional[PackageURL]:
255208
256209 if pkg_type == "composer" :
257210 if "/" not in github_name :
258- logger .error (f"get_purl: Invalid composer package name { github_name } " )
259- return
211+ return PackageURL (type = pkg_type , name = github_name )
260212 vendor , _ , name = github_name .partition ("/" )
261213 return PackageURL (type = pkg_type , namespace = vendor , name = name )
262214
@@ -272,26 +224,6 @@ class InvalidVersionRange(Exception):
272224 """
273225
274226
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-
295227def process_response (resp : dict , package_type : str ) -> Iterable [AdvisoryData ]:
296228 """
297229 Yield `AdvisoryData` by taking `resp` and `ecosystem` as input
@@ -349,7 +281,8 @@ def process_response(resp: dict, package_type: str) -> Iterable[AdvisoryData]:
349281
350282 references = get_item (advisory , "references" ) or []
351283 if references :
352- references : List [Reference ] = list (extract_references (references ))
284+ urls = (ref ["url" ] for ref in references )
285+ references = [Reference .from_url (u ) for u in urls ]
353286
354287 summary = get_item (advisory , "summary" )
355288 identifiers = get_item (advisory , "identifiers" ) or []
@@ -451,6 +384,7 @@ def get_inferences(self, advisory_data: AdvisoryData) -> Iterable[Inference]:
451384 aff_vers , unaff_vers = resolve_version_range (
452385 affected_version_range = affected_version_range ,
453386 package_versions = valid_versions ,
387+ ignorable_versions = WEIRD_IGNORABLE_VERSIONS ,
454388 )
455389 affected_purls = [
456390 PackageURL (type = pkg_type , namespace = pkg_namespace , name = pkg_name , version = version )
@@ -476,37 +410,3 @@ def get_inferences(self, advisory_data: AdvisoryData) -> Iterable[Inference]:
476410 affected_purls = affected_packages ,
477411 fixed_purl = fixed_package ,
478412 )
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