Prologue: I know that many people already tried to sandbox Python code within Python and failed, but I haven't seen the approach to additionally preprocess the scripts as text and reject scripts containing keywords like __base__
that could be used to recover hidden __buuiltins__
. I think this approach is new and hasn't been proofed to fail yet - has it?
I plan to write a multiplayer strategy game where players may not normally interact with their units using keyboard/mouse commands, but only through scripts they have to submit to change the units' automatic behaviour. This is based on the idea of http://screeps.com.
I would love to write that in Python 3, but the main problem seems to be the secure execution of untrusted foreign player scripts on the server. I know that I may not trust exec()
or eval()
, even when passing them empty globals
and locals
as environment. I also know that simply erasing __builtins__
also does not work because one can still easily restore them using Python's introspection capabilities as described here: http://nedbatchelder.com/blog/201302/finding_python_3_builtins.html
I already learned that PyPy or Jython might have some kind of sandboxing feature that would probably work for my purpose, but I would somehow prefer to stay with the CPython reference interpreter. Also, I could only find examples where those sandboxing features work for entire programs, but none that consists of a main program running untrusted scripts as child threads and communicating with them efficiently.
But I think I have one more chance: I can preprocess the submitted scripts literally and search for strings like __class__
or __base__
and reject scripts containing those keywords. I would also have to replace eval()
and exec()
in the script with my own, secured functions that also reject to run code containing those keywords.
Would this approach, together with overwriting all potentially dangerous items (which ones would that be?) using a custom globals
argument for exec()
be secure? Which keywords would I have to look for?
If not, why would that fail? Can you suggest a better solution?