Untrusted code execution

Chris Angelico rosuav at gmail.com
Thu Apr 7 08:46:21 EDT 2016


On Thu, Apr 7, 2016 at 10:13 PM, Jon Ribbens
<jon+usenet at unequivocal.co.uk> wrote:
> It's true that I was using eval(), but I don't think that actually
> fundamentally changes the game. Almost exactly the same sanitisation
> method can be used to make exec() code safe. ("import" for example
> does not work because there is no "__import__" in the provided
> builtins, but even if it did work it could be trivially disallowed by
> searching for ast.Import and ast.ImportFrom nodes. "with" must be
> disallowed because otherwise __exit__ can be used to get a frame
> object.)

Once statements are incorporated, you have three options regarding
exception handling:

1) Disallow try/except, flying in the face of modern language design
2) Allow only a bare except clause, flying in the face of modern Python advice
3) Allow access to all the built-in exception types.

Options 1 and 2 are nastily restricted. Option 3 is likely broken, as
exception objects carry tracebacks and such. And don't forget, you can
trigger exceptions very easily:

* TypeError by adding two literals of incompatible types, eg []+{}
* ValueError by casting inappropriate strings eg int("")
* ZeroDivisionError by, yaknow, dividing by zero
* NameError and UnboundLocalError with random names
* RecursionError by infinitely recursing
* Unicode{En,De}codeError with str/bytes methods
* KeyError/IndexError by subscripting
* OverflowError with float exponentiation, eg 2.0**10000
* etc, etc, etc

Are you prepared to guarantee that there's no way to leak information
out of *any* exception? If not, you can't offer exceptions, which
means you can't offer try/except other than with a bare except.

ChrisA



More information about the Python-list mailing list