Sandboxing eval() (was: Calculator)

Chris Angelico rosuav at gmail.com
Sun Jan 19 14:43:41 EST 2020


On Mon, Jan 20, 2020 at 4:43 AM <musbur at posteo.org> wrote:
>
> Is it actually possible to build a "sandbox" around eval, permitting it
> only to do some arithmetic and use some math functions, but no
> filesystem acces or module imports?
>
> I have an application that loads calculation recipes (a few lines of
> variable assignments and arithmetic) from a database.
>
> exec(string, globals, locals)
>
> with locals containing the input variables, and globals has a
> __builtin__ object with a few math functions. It works, but is it safe?

As such? No. However, there are some elegant hybrid options, where you
can make use of the Python parser to do some of your work, and then
look at the abstract syntax tree. What you'd be doing is something
similar to ast.literal_eval, but with a few more permitted options.
For instance, you might allow Name nodes as long as the name is part
of a whitelist, and allow BinOp, but not allow Attribute lookup. (It
would be easiest if you make all your math functions available as
simple names - "log" not "math.log" - to make this easy.) Once you've
parsed the expression to an abstract syntax tree, then walked the tree
and made sure everything fits your requirements, you can then compile
it the rest of the way and run it.

It's a lot more work than simply calling eval, but it's a lot less
than trying to build your own parser from scratch and try to make it
flexible enough to be useful.

Research the "ast" module for some ideas on what you can do.

ChrisA


More information about the Python-list mailing list