2727from typing import Set
2828from typing import Tuple
2929from typing import List
30+ from typing import Mapping
31+ from typing import Optional
3032import xml .etree .ElementTree as ET
3133
3234import requests
3840from vulnerabilities .data_source import DataSourceConfiguration
3941
4042
43+ # set of all possible values of first '%s' = {'MAVEN','COMPOSER', 'NUGET'}
44+ # second '%s' is interesting, it will have the value '' for the first request,
45+ # since we don't have any value for endCursor at the beginning
46+ # for all the subsequent requests it will have value 'after: "{endCursor}"'
47+ query = """
48+ query MyQuery {
49+ securityVulnerabilities(first: 100, ecosystem: %s, %s) {
50+ edges {
51+ node {
52+ advisory {
53+ identifiers {
54+ type
55+ value
56+ }
57+ summary
58+ }
59+ package {
60+ name
61+ }
62+ vulnerableVersionRange
63+ }
64+ }
65+ pageInfo {
66+ hasNextPage
67+ endCursor
68+ }
69+ }
70+ }
71+ """
72+
73+
4174class GitHubTokenError (Exception ):
4275 pass
4376
@@ -65,36 +98,8 @@ def __enter__(self):
6598 def updated_advisories (self ) -> Set [Advisory ]:
6699 return self .batch_advisories (self .process_response ())
67100
68- def fetch (self ):
69- # set of all possible values of first '%s' = {'MAVEN','COMPOSER', 'NUGET'}
70- # second '%s' is interesting, it will have the value '' for the first request,
71- # since we don't have any value for endCursor at the beginning
72- # for all the subsequent requests it will have value 'after: "{endCursor}"'
73- query = """
74- query MyQuery {
75- securityVulnerabilities(first: 100, ecosystem: %s, %s) {
76- edges {
77- node {
78- advisory {
79- identifiers {
80- type
81- value
82- }
83- summary
84- }
85- package {
86- name
87- }
88- vulnerableVersionRange
89- }
90- }
91- pageInfo {
92- hasNextPage
93- endCursor
94- }
95- }
96- }
97- """
101+ def fetch (self ) -> Mapping [str , List [Mapping ]]:
102+
98103 headers = {"Authorization" : "token " + self .gh_token }
99104 api_data = {}
100105 for ecosystem in self .config .ecosystems :
@@ -122,10 +127,9 @@ def fetch(self):
122127 "hasNextPage"
123128 ]:
124129 break
125-
126130 return api_data
127131
128- def set_version_api (self , ecosystem ) :
132+ def set_version_api (self , ecosystem : str ) -> None :
129133
130134 if ecosystem == "MAVEN" :
131135 self .version_api = MavenVersionAPI ()
@@ -137,7 +141,9 @@ def set_version_api(self, ecosystem):
137141 self .version_api = ComposerVersionAPI ()
138142
139143 @staticmethod
140- def process_name (ecosystem , pkg_name ):
144+ def process_name (
145+ ecosystem : str , pkg_name : str
146+ ) -> Optional [Tuple [Optional [str ], str ]]:
141147
142148 if ecosystem == "MAVEN" :
143149
@@ -206,7 +212,6 @@ def process_response(self) -> List[Advisory]:
206212 reference_ids = ref_ids ,
207213 )
208214 )
209- # print(adv_list[-1])
210215 return adv_list
211216
212217 @staticmethod
@@ -227,7 +232,7 @@ def __init__(self):
227232 def get (self , pkg_name : str ) -> Set [str ]:
228233 return self .cache .get (pkg_name , set ())
229234
230- def load_to_api (self , pkg_name : str ):
235+ def load_to_api (self , pkg_name : str ) -> None :
231236
232237 if pkg_name in self .cache :
233238 return
@@ -270,30 +275,30 @@ class NugetVersionAPI:
270275 def __init__ (self ):
271276 self .cache = {}
272277
273- def get (self , pkg_name ) :
278+ def get (self , pkg_name : str ) -> Set [ str ] :
274279 return self .cache .get (pkg_name .lower (), set ())
275280
276- def load_to_api (self , pkg_name : str ):
281+ def load_to_api (self , pkg_name : str ) -> None :
277282 if pkg_name in self .cache :
278283 return
279284 endpoint = self .nuget_url (pkg_name )
280285 try :
281286 resp = requests .get (endpoint ).json ()
282287 # pkg_name=Microsoft.NETCore.UniversalWindowsPlatform triggers
283288 # JSONDecodeError.
284- except ( json .decoder .JSONDecodeError , KeyError ) :
289+ except json .decoder .JSONDecodeError :
285290 self .cache [pkg_name .lower ()] = set ()
286291 return
287292
288293 self .cache [pkg_name .lower ()] = self .extract_versions (resp )
289294
290295 @staticmethod
291- def nuget_url (pkg_name ) :
296+ def nuget_url (pkg_name : str ) -> str :
292297 base_url = "https://api.nuget.org/v3/registration5-semver1/{}/index.json"
293298 return base_url .format (pkg_name .lower ())
294299
295300 @staticmethod
296- def extract_versions (json_resp ) :
301+ def extract_versions (json_resp : dict ) -> Set [ str ] :
297302 all_versions = set ()
298303 try :
299304 for entry in json_resp ["items" ][0 ]["items" ]:
@@ -309,33 +314,28 @@ class ComposerVersionAPI:
309314 def __init__ (self ):
310315 self .cache = {}
311316
312- def get (self , pkg_name ) :
317+ def get (self , pkg_name : str ) -> Set [ str ] :
313318 return self .cache .get (pkg_name .lower (), set ())
314319
315- def load_to_api (self , pkg_name ) :
320+ def load_to_api (self , pkg_name : str ) -> None :
316321 if pkg_name in self .cache :
317322 return
318323 endpoint = self .composer_url (pkg_name )
319324 json_resp = requests .get (endpoint ).json ()
320325 self .cache [pkg_name ] = self .extract_versions (json_resp , pkg_name )
321326
322327 @staticmethod
323- def composer_url (pkg_name ) :
328+ def composer_url (pkg_name : str ) -> str :
324329 vendor , name = pkg_name .split ("/" )
325330 return f"https://repo.packagist.org/p/{ vendor } /{ name } .json"
326331
327332 @staticmethod
328- def extract_versions (json_resp , pkg_name ) :
333+ def extract_versions (json_resp : dict , pkg_name : str ) -> Set [ str ] :
329334 all_versions = json_resp ["packages" ][pkg_name ].keys ()
330335 # This filter ensures, that all_versions contains only released versions
331336 all_versions = set (filter (lambda x : "dev" not in x , all_versions ))
332- # more_versions ensures that we have a version with and without version tag for
333- # each version present in all_versions
334- more_versions = set ()
335- for version in all_versions :
336- if version .startswith ("v" ):
337- more_versions .add (version [1 :])
338- else :
339- more_versions .add ("v" + version )
340-
341- return all_versions .union (more_versions )
337+ # See https://github.com/composer/composer/blob/44a4429978d1b3c6223277b875762b2930e83e8c/doc/articles/versions.md#tags # nopep8
338+ # for explanation of removing 'v'
339+ all_versions = set (map (lambda x : x .replace ("v" , "" ), all_versions ))
340+
341+ return all_versions
0 commit comments