2
\$\begingroup\$

Code is Working Review and Recommend What Are Best Practice

What I am trying to achieve.

  1. API with Flask that runs any python file from the current directory.

  2. Run the file and get output in JSON

Below is the code for the app.py

from flask import Flask,jsonify
from flask_restful import Api,Resource
import os

app = Flask(__name__)
api = Api(app)

class callApi(Resource):
    def get(self,file_name):
        my_dir = os.path.dirname(__file__)
        file_path = os.path.join(my_dir, file_name)
        file = open(file_path)
        getvalues={}
        exec(file.read(),getvalues)
        return jsonify({'data':getvalues['total']})

api.add_resource(callApi,"/callApi/<string:file_name>")

if __name__ == '__main__':
   app.run(debug='true')

Below is the code for the main.py which sends a request to API.with Filename which to run. The filename will be changed as per requirements.

import requests

BASE = 'https://127.0.0.1/callApi/runMe.py'

response = requests.get(BASE)
print(response.encoding)

Below is the File which runs by exec from API API/app.py can access this file because both are in the same dir.

def fun():
    a = 10
    b = 10 
    total = a+b
    print(total)
    return total
 
total = fun()

Is there any better way to write all this code please let me know. here are refs which I used to make this

Eval function

Exec Function

Exec Docs

Running a python script saved in local machine from google sheets on a button press

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

To be honest this code looks pretty dangerous. exec is dangerous in its own right, and using it in conjunction with user-provided input makes an explosive combination.

One flaw is the path traversal vulnerability. For example, providing a file name like "../root/something/script.py" I should be able to invoke files outside your directory. The file has to exist to be executed, but a hacker might find some file lying on your system, that can be exploited in a way you did not foresee.

Your script also does not verify that the resulting path really exists (for this, simply use os.path.exists). Thus, validation of user input is lacking.

And probably this code can be exploited in ways I have not thought about.

But since you are reading files from a specific directory, you could simply run a dir of that location, using for example the os.scandir function, and then you can generate a whitelist of files that are allowed to run. Anything else should be disallowed outright.

Personally I would ditch this approach. It would be better to build a library of functions, and invoke only functions that are known and understood, rather than arbitrary files. The rule of thumb is that user input can never be trusted, so it has to be validated thoroughly.

\$\endgroup\$
1
  • \$\begingroup\$ I am going to create a list of script name which I want to allow to run then I will match the input with that list. \$\endgroup\$ Commented Apr 13, 2021 at 4:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.