1

So I have a game, with a modular framework (an api for modders) that can be written in python in the directory of

Game
¬ Info
 ¬ about.txt
¬ Packages
 ¬ mod1
  ¬ main.txt
  ¬ data
   ¬ credits.txt
¬ run.py

With main.py consisting of

import requests #is not allowed

userpassword = "peussweurdo"

open("Game/Info/About.txt", "r") #is allowed
open("Game/Info/About.txt", "w") #is not allowed

open("data/credits.txt") #is allowed
open("C:/Users/<user>/passwords") #is not allowed

The main things im trying to do are:

  • Make sure import, exec and eval cannot be used
  • Allow game to be accessed

I have tried the following

import os

mod_path = "Packages/mod1/main.txt"
mod_data = open(mod_path, "r").read()

def safe_open(path, mode="r"):
    if path.startswith("Game") and mode != "r":
        raise OSError("Accessing game files is read-only")
    else:
        return open("%s/%s" % (mod_path, path), mode)

methods = {
    "open": safe_open
}
newly_defined = {}

exec(mod_data, methods, newly_defined)

But this ends up adding all of the builtins to methods and still allows for imports, execs and evals to be called. How'd I go about preventing this?

Dimsey
  • 43
  • 5
  • 2
    The tl;dr is that sandboxing is *hard*, and I think it's a really interesting project to develop your own, but if your priority is safety, I'd look for an existing library that has had more time to be audited and refined. – Kaia Feb 23 '23 at 21:10
  • 1
    This is very, _very_ hard, if not impossible, to do. There are many creative ways to perform imports or access `eval`/`exec` that a sufficiently motivated attacker could use. As a cute example, here's one way to spell `eval`: `getattr(getattr(lambda:None, "\x5f\x5f\x67\x6c\x6f\x62\x61\x6c\x73\x5f\x5f")["\x5f\x5f\x62\x75\x69\x6c\x74\x69\x6e\x73\x5f\x5f"], "\x65\x76\x61\x6c")` – Brian61354270 Feb 23 '23 at 21:10
  • 1
    it probably isn't possible to make `exec` safe. – juanpa.arrivillaga Feb 23 '23 at 21:13

0 Answers0