mrclary mrclary - 1 month ago 14
Python Question

How to properly limit __builtins__ in eval in Python 3.5?

In python 2.7 I could limit the

__builtins__
namespace used by eval by defining global as
{'__builtins__': None}
. This does not seem to work in Python 3.5.

Python 2.7 correctly gives the NameError:

In [1]: eval('round', {'__builtins__': None})
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-14-dc1cae9c6b26> in <module>()
----> 1 eval('round', {'__builtins__': None})

<string> in <module>()

NameError: name 'round' is not defined


Python 3.5 gives the following:

In [1]: eval('round', {'__builtins__': None})
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-9-83a8846287f1> in <module>()
----> 1 eval('round', {'__builtins__': None})

<string> in <module>()

TypeError: 'NoneType' object is not subscriptable


Both give the correct output for the following:

In [1]: eval('round')
Out[1]: <function round>


How do I properly limit
__builtins__
or work around this?

Answer

You can set it to an empty dictionary:

eval('round', {'__builtins__': {}})

This will reproduce the NameError you got in Python 2.x. However, sandboxing Python, whether 2 or 3, is an inherently hard problem. If possible, you should use something less powerful like ast.literal_eval() instead of eval().

Comments