Simple and safe evaluator

George Sakkis george.sakkis at gmail.com
Thu Jun 12 00:16:08 EDT 2008


On Jun 11, 8:15 pm, bvdp <b... at mellowood.ca> wrote:

> Matimus wrote:
>
> > The solution I posted should work and is safe. It may not seem very
> > readable, but it is using Pythons internal parser to parse the passed
> > in string into an abstract symbol tree (rather than code). Normally
> > Python would just use the ast internally to create code. Instead I've
> > written the code to do that. By avoiding anything but simple operators
> > and literals it is guaranteed safe.
>
> Just wondering ... how safe would:
>
>          eval(s, {"__builtins__":None}, {} )
>
> be? From my testing it seems that it parses out numbers properly (int
> and float) and does simple math like +, -, **, etc. It doesn't do
> functions like int(), sin(), etc ... but that is fine for my puposes.
>
> Just playing a bit, it seems to give the same results as your code using
> ast does. I may be missing something!

Probably you do; within a couple of minutes I came up with this:

>>> s = """
... (t for t in 42 .__class__.__base__.__subclasses__()
...  if t.__name__ == 'file').next()('/etc/passwd')
... """
>>> eval(s, {"__builtins__":None}, {} )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 3, in <module>
IOError: file() constructor not accessible in restricted mode


Not an exploit yet but I wouldn't be surprised if there is one. Unless
you fully trust your users, an ast-based approach is your best bet.

George

George



More information about the Python-list mailing list