Giovanni Bajo wrote:
I use something along these lines:
def safe_eval(expr, symbols={}):
return eval(expr, dict(__builtins__=None, True=True, False=False), symbols)
import math def calc(expr): return safe_eval(expr, vars(math))
That offers only notional security:
>>> calc("acos.__class__.__bases__[0]") <type 'object'>
Yeah, I was concerned about the same thing, but I realized that I can't actually access any of the func_globals attributes:
py> eval('(1).__class__.mro()[-1].__subclasses__()[17]' ... '.substitute.func_globals', dict(__builtins__=None)) Traceback (most recent call last): File "<interactive input>", line 2, in ? File "<string>", line 0, in ? RuntimeError: restricted attribute
AFAIK, you need to get to func_globals to do anything really interesting. (You can get file through object, but you can't get __import__ AFAIK. So you can read and write files which means you can create a DOS attack, but I don't know how to do the eqivalent of, say, 'rm -rf /'.)
Also interesting is that an old exec trick[1] no longer works:
py> exec """\ ... global __builtins__ ... del __builtins__ ... print __builtins__""" in dict(__builtins__=None) Traceback (most recent call last): File "<interactive input>", line 1, in ? File "<string>", line 3, in ? NameError: global name '__builtins__' is not defined
(It used to make __builtins__ available.)
STeVe
[1]http://mail.python.org/pipermail/python-list/2004-August/234838.html -- http://mail.python.org/mailman/listinfo/python-list