@@ -50,7 +50,7 @@ def _worker(self):
5050 try :
5151 task_id , fn , args , kwargs = self .tasks .get (block = False )
5252 self .results [task_id ] = fn (* args , ** kwargs )
53- except :
53+ except Exception :
5454 pass
5555
5656 def __enter__ (self ):
@@ -130,6 +130,13 @@ def __init__(
130130 def get_api_base_url (self , api_version = None ):
131131 return self .join_url_path (self .HOST , "/api/{}/" .format (api_version or self .api_version ))
132132
133+ _SENSITIVE_KEYS = frozenset ({"api_key" , "token" , "username" , "email" , "Authorization" })
134+
135+ @staticmethod
136+ def _redact_dict (d ):
137+ """Return a copy of dict *d* with sensitive values replaced by '***'."""
138+ return {k : ("***" if k in SyncSketchAPI ._SENSITIVE_KEYS else v ) for k , v in d .items ()}
139+
133140 @staticmethod
134141 def join_url_path (base , * path_segments ):
135142 """Takes one more more strings and returns a properly terminated url path. Handles strings regardless
@@ -206,8 +213,8 @@ def _get_json_response(
206213 "{method} URL: {url}, params: {params}, headers: {headers}, status_code: {status_code}" .format (
207214 method = method ,
208215 url = url ,
209- params = params ,
210- headers = headers ,
216+ params = self . _redact_dict ( params ) ,
217+ headers = self . _redact_dict ( headers ) ,
211218 status_code = r .status_code ,
212219 )
213220 )
@@ -221,8 +228,7 @@ def _get_json_response(
221228 except Exception as e :
222229 if self .debug :
223230 print (e )
224-
225- print ("Error: %s" % r .text )
231+ print ("Error: %s" % r .text )
226232
227233 return {"objects" : []}
228234
@@ -958,22 +964,22 @@ def add_media(
958964 if itemParentId :
959965 get_params .update ({"itemParentId" : itemParentId })
960966
961- uploadURL = "%s/items/uploadToReview/%s/?%s " % (
967+ uploadURL = "%s/items/uploadToReview/%s/" % (
962968 self .HOST ,
963969 review_id ,
964- urlencode (get_params ),
965970 )
966971
967972 files = {"reviewFile" : open (filepath , "rb" )}
968973 r = requests .post (
969974 uploadURL ,
975+ params = get_params ,
970976 files = files ,
971977 data = dict (artist = artist_name , name = file_name ),
972978 headers = self .headers ,
973979 )
974980
975981 if self .debug :
976- print ("URL: %s, params: %s" % (uploadURL , get_params ))
982+ print ("URL: %s, params: %s" % (uploadURL , self . _redact_dict ( get_params ) ))
977983
978984 try :
979985 return json .loads (r .text )
@@ -1002,15 +1008,15 @@ def add_media_by_url(self, review_id, media_url, artist_name="", noConvertFlag=F
10021008 if noConvertFlag :
10031009 get_params .update ({"noConvertFlag" : 1 })
10041010
1005- upload_url = "%s/items/uploadToReview/%s/?%s " % (
1011+ upload_url = "%s/items/uploadToReview/%s/" % (
10061012 self .HOST ,
10071013 review_id ,
1008- urlencode (get_params ),
10091014 )
10101015
10111016 r = requests .post (
10121017 upload_url ,
1013- {"media_url" : media_url , "artist" : artist_name },
1018+ params = get_params ,
1019+ data = {"media_url" : media_url , "artist" : artist_name },
10141020 headers = self .headers ,
10151021 )
10161022
@@ -1411,8 +1417,7 @@ def _get_s3_signed_url(
14111417 """
14121418 Internal method. Use to retrieve s3 signed url for file upload in `add_media_via_s3`.
14131419 """
1414- request_data = self .api_params .copy ()
1415- additional_request_data = {
1420+ post_data = {
14161421 "review_id" : review_id ,
14171422 "item_name" : item_name ,
14181423 "item_data" : {
@@ -1422,13 +1427,12 @@ def _get_s3_signed_url(
14221427 "noConvertFlag" : no_convert ,
14231428 },
14241429 }
1425- request_data .update (additional_request_data )
14261430
14271431 request_url = "{}/uploads/get-s3-signed-url/" .format (self .HOST )
14281432
14291433 return self ._get_json_response (
14301434 url = request_url ,
1431- postData = request_data ,
1435+ postData = post_data ,
14321436 raw_response = raw_response ,
14331437 )
14341438
@@ -1721,10 +1725,11 @@ def get_grease_pencil_overlays(self, review_id, item_id, homedir=None):
17211725 if result .get ("status" ) == "done" :
17221726 data = result .get ("data" )
17231727
1724- # storing locally
1725- local_filename = "/tmp/%s.zip" % data ["fileName" ]
1728+ # storing locally - sanitize fileName to prevent path traversal
1729+ safe_name = os .path .basename (data ["fileName" ])
1730+ local_filename = "/tmp/%s.zip" % safe_name
17261731 if homedir :
1727- local_filename = os .path .join (homedir , "{}.zip" .format (data [ "fileName" ] ))
1732+ local_filename = os .path .join (homedir , "{}.zip" .format (safe_name ))
17281733 r = requests .get (data ["s3Path" ], stream = True )
17291734 with open (local_filename , "wb" ) as f :
17301735 for chunk in r .iter_content (chunk_size = 1024 ):
@@ -1788,7 +1793,7 @@ def get_user_by_email(self, email, fields=None, raw_response=True):
17881793 try :
17891794 data = response .json ()
17901795 return data .get ("objects" )[0 ]
1791- except :
1796+ except Exception :
17921797 return None
17931798
17941799 def get_users_by_project_id (self , project_id , raw_response = False ):
0 commit comments