0

I have a snippet of python that does an exec on user-provided python:

import sys
import traceback

def foo():
    print("jailbreak!")

c_globals = {}
c_locals = {}

try:
    exec(compile(open("core.py", "rb").read(), "core.py", 'exec'), c_globals, c_locals)
    c_locals["update"]()
except Exception:
    print(traceback.format_exc(2))

Is it possible for the user-provided python to trivially "jailbreak" or crash the calling code? I'm aware that the user code can call exit, but other than that, what are some ways the user could misbehave?

I perused this question but the answers seem somewhat old.

To be clear: I'm not looking for a bulletproof sandbox. I'm looking for ways users might shoot themselves in the foot so I can prevent them from doing so. This is for a "run at your own risk" computer game I'm making.

See: https://repl.it/repls/MistyConventionalControlflowgraph

Gillespie
  • 5,780
  • 3
  • 32
  • 54

1 Answers1

3

The user-provided code is run inside the same process which means it has all the same access and privilege as your code.

Since Python allows circular imports we can complete your example:

def update():
  print("This should be impossible:")
  from main import foo
  foo()

The user could also run shell commands with the same privilege as given to your own code:

def update():
  print("This should be impossible:")
  import subprocess
  subprocess.run(["ls", "-l"])

The user could also simply exhaust resources. The following will max out the CPU usage on a single core:

def update():
  while True:
    x*x

exec executes code in the same context from which it was called and so by default doesn't really provide any 'sandboxing' at all.

jontypreston
  • 398
  • 2
  • 7
  • This is for a "run at your own risk" computer game, and so generally I'm not really concerned what users do to their own computer with `subprocess.run` but I do want to make it *slightly* more difficult for the average user to mess with/lock up/crash the actual game engine. This answer gives me plenty to research/think about. – Gillespie Sep 06 '19 at 17:31
  • 1
    Ah I see, small recommendation then: if you use a 'bare' except statement (eg: `except:` without providing any Exception class then it'll catch everything. This includes the `SystemExit` exception which is how calling the built-in `exit` actually quits a Python program. – jontypreston Sep 06 '19 at 20:09