How can I sandbox Python in pure Python?
How can you sandbox Python using only pure Python, and what techniques allow you to safely execute untrusted code? Understanding Python sandboxing helps prevent security risks when running dynamic or third-party scripts.
Sandboxing Python means running code in a restricted environment where it cannot perform harmful operations, access the file system, or modify sensitive variables. But how can you sandbox Python using only pure Python, without relying on external tools or containers?
1. Using exec() with Restricted Globals
- The exec() function allows dynamic code execution.
- You can control the environment by providing a custom dictionary for globals and locals.
Example:
safe_globals = {"__builtins__": {}}
code = "result = 5 + 7"
exec(code, safe_globals)
print(safe_globals.get("result")) # Output: 12
By restricting __builtins__, you prevent access to dangerous functions like open() or eval().
2. Limiting Built-in Functions
- You can selectively allow only safe built-ins.
Example:
safe_builtins = {"print": print, "len": len}
safe_globals = {"__builtins__": safe_builtins}
exec("print(len([1,2,3]))", safe_globals) # Output: 3
This ensures the executed code cannot perform unauthorized actions.
3. Using ast Module for Pre-checks
- You can parse Python code with the ast module and inspect or filter nodes before execution.
- Example: disallow Import or Attribute nodes to prevent module imports or object access.
Key Points to Remember:
- Pure Python sandboxing is never 100% secure, as determined users may find ways to escape restrictions.
- Always combine with code review or run in additional OS-level restrictions if security is critical.
- Sandboxing is useful for educational tools, plugins, or running untrusted snippets in a controlled environment.
In summary, sandboxing Python in pure Python involves restricting globals, controlling built-ins, and optionally analyzing code with ast. While convenient, it should be used with caution for security-critical applications.