Is it possible to restrict access to globals for a block of code in python?
Question: I would like users of my program to be able to define custom scripts in python
without breaking the program. I am looking at something like this:

    
    
    def call(script):
      code = "access modification code" + script
      exec(code)
    

Where "access modification code" defines a scope such that script can only
access variables it instantiates itself. Is it possible to do this or
something with similar functionality, such as creating a new python
environment with its own scope and then receiving output from it?

Thank you for your time :)

_Clarification Edit_ "I want to prevent both active attacks and accidental
interaction with the program variables outside the users script (hence hiding
all globals). The user scripts are intended to be small and inputted as text.
The return of the user script needs to be immediate, as though it were native
to the program."


Answer: There's two separate problems you want to prevent in this scenario:

  * Prevent an outside attacker from running arbitrary code in the context of the OS user executing your program. This means preventing [arbitrary code execution](https://en.wikipedia.org/wiki/Arbitrary_code_execution) and [privilege escalation](https://en.wikipedia.org/wiki/Privilege_escalation). 
  * Preventing a legitimate user of your program from changing the program behavior in unintended ways.

* * *

For the first problem, **you need to make sure that the source of the python
code you execute is the user**. You shouldn't accept input from a socket, or
from a file that other users can write to. You need to make sure, somehow,
that it was the user who is running the program that provided the input.
Actual solutions will depend on your OS, but you may want to consider setting
up restrictive file permissions, if you're storing the code in a file.

**Don't ignore or downplay this problem, or your users will fall victim to
virus/malware/hackers thanks to your program.**

* * *

The way you solve the second problem depends on what exactly constitutes
_intended behaviour_ in your program. If you're happy with outputting simple
data structures, you can **run your user-inputted code in a separate process**
, and pass the result over a pipe in a serialization format such as JSON or
YAML.

Here's a very simple example:

    
    
    #remember to set restrictive file permissions on this file. This is OS-dependent
    USER_CODE_FILE="/home/user/user_code_file.py"
    
    #absolute path to python binary (executable)
    PYTHON_PATH="/usr/bin/python"
    
    import subprocess
    import json
    
    user_code= '''
    import json
    my_data= {"a":[1,2,3]}
    print json.dumps(my_data)
    '''
    
    with open(USER_CODE_FILE,"wb") as f:
        f.write(user_code)
    
    user_result_str= subprocess.check_output([PYTHON_PATH, USER_CODE_FILE])
    user_result= json.loads( user_result_str )
    print user_result
    

This is a fairly simple solution, and it has significant overhead. Don't use
this if you need to run the user code many times in a short period of time.

Ultimately, this solution is only effective against unsophisticated attackers
(users). Generally speaking, there's no way to protect any user process from
the user itself - nor would it make much sense.

If you really want more assurance, and want to mitigate the first problem too,
you should **run the process as a separate ("guest") user**. This, again, is
OS-dependent.

* * *

Finally a warning: avoid `exec` and `eval` to the best of your abilities. They
don't protect either your program or the user against the inputted code.
There's a lot of information about this on the web, just search for "python
secure eval"

