77from pathlib import Path
88import json
99import platform
10+ import re
1011from flask_cors import CORS , cross_origin
1112
13+ # Input validation pattern for safe names (alphanumeric, dash, underscore, slash, dot, space)
14+ SAFE_INPUT_PATTERN = re .compile (r'^[a-zA-Z0-9_\-/. ]+$' )
15+
16+ def validate_input (value , field_name ):
17+ """Validate that input contains only safe characters."""
18+ if value is None :
19+ return True
20+ if not isinstance (value , str ):
21+ raise ValueError (f"Invalid { field_name } : must be a string" )
22+ if len (value ) > 0 and not SAFE_INPUT_PATTERN .match (value ):
23+ raise ValueError (f"Invalid { field_name } : contains unsafe characters" )
24+ return True
25+
1226cur_path = os .path .dirname (os .path .abspath (__file__ ))
1327concore_path = os .path .abspath (os .path .join (cur_path , '../../' ))
1428
@@ -304,14 +318,24 @@ def contribute():
304318 STUDY_NAME = data .get ('study' )
305319 STUDY_NAME_PATH = data .get ('path' )
306320 BRANCH_NAME = data .get ('branch' )
321+
322+ # Validate all user inputs to prevent command injection
323+ validate_input (STUDY_NAME , 'study' )
324+ validate_input (STUDY_NAME_PATH , 'path' )
325+ validate_input (AUTHOR_NAME , 'auth' )
326+ validate_input (BRANCH_NAME , 'branch' )
327+ validate_input (PR_TITLE , 'title' )
328+ validate_input (PR_BODY , 'desc' )
329+
307330 if (platform .uname ()[0 ]== 'Windows' ):
308- proc = check_output (["contribute" ,STUDY_NAME ,STUDY_NAME_PATH ,AUTHOR_NAME ,BRANCH_NAME ,PR_TITLE ,PR_BODY ],cwd = concore_path ,shell = True )
331+ proc = subprocess .run (["contribute" ,STUDY_NAME ,STUDY_NAME_PATH ,AUTHOR_NAME ,BRANCH_NAME ,PR_TITLE ,PR_BODY ],cwd = concore_path ,check = True ,capture_output = True ,text = True )
332+ output_string = proc .stdout
309333 else :
310334 if len (BRANCH_NAME )== 0 :
311335 proc = check_output ([r"./contribute" ,STUDY_NAME ,STUDY_NAME_PATH ,AUTHOR_NAME ],cwd = concore_path )
312336 else :
313337 proc = check_output ([r"./contribute" ,STUDY_NAME ,STUDY_NAME_PATH ,AUTHOR_NAME ,BRANCH_NAME ,PR_TITLE ,PR_BODY ],cwd = concore_path )
314- output_string = proc .decode ()
338+ output_string = proc .decode ()
315339 status = 200
316340 if output_string .find ("/pulls/" )!= - 1 :
317341 status = 200
@@ -320,6 +344,11 @@ def contribute():
320344 else :
321345 status = 400
322346 return jsonify ({'message' : output_string }),status
347+ except ValueError as e :
348+ return jsonify ({'message' : str (e )}), 400
349+ except subprocess .CalledProcessError as e :
350+ output_string = e .stderr if hasattr (e , 'stderr' ) and e .stderr else "Command execution failed"
351+ return jsonify ({'message' : output_string }), 501
323352 except Exception as e :
324353 output_string = "Some Error occured.Please try after some time"
325354 status = 501
@@ -365,18 +394,34 @@ def library(dir):
365394 dir_path = os .path .abspath (os .path .join (concore_path , dir_name ))
366395 filename = request .args .get ('filename' )
367396 library_path = request .args .get ('path' )
397+
398+ # Validate user inputs to prevent command injection
399+ try :
400+ validate_input (filename , 'filename' )
401+ validate_input (library_path , 'path' )
402+ except ValueError as e :
403+ resp = jsonify ({'message' : str (e )})
404+ resp .status_code = 400
405+ return resp
406+
368407 proc = 0
369408 if (library_path == None or library_path == '' ):
370409 library_path = r"../tools"
371- if (platform .uname ()[0 ]== 'Windows' ):
372- proc = subprocess .check_output ([r"..\library" , library_path , filename ],shell = True , cwd = dir_path )
373- else :
374- proc = subprocess .check_output ([r"../library" , library_path , filename ], cwd = dir_path )
375- if (proc != 0 ):
376- resp = jsonify ({'message' : proc .decode ("utf-8" )})
410+ try :
411+ if (platform .uname ()[0 ]== 'Windows' ):
412+ result = subprocess .run ([r"..\library" , library_path , filename ], cwd = dir_path , check = True , capture_output = True , text = True )
413+ proc = result .stdout
414+ else :
415+ proc = subprocess .check_output ([r"../library" , library_path , filename ], cwd = dir_path )
416+ proc = proc .decode ("utf-8" )
417+ resp = jsonify ({'message' : proc })
377418 resp .status_code = 201
378419 return resp
379- else :
420+ except subprocess .CalledProcessError as e :
421+ resp = jsonify ({'message' : 'Command execution failed' })
422+ resp .status_code = 500
423+ return resp
424+ except Exception as e :
380425 resp = jsonify ({'message' : 'There is an Error' })
381426 resp .status_code = 500
382427 return resp
0 commit comments