[Python-Dev] Sandboxing Python

Victor Stinner victor.stinner at gmail.com
Thu Mar 1 19:23:47 CET 2012


Hi,

The frozendict discussion switched somewhere to sandboxing, and so I
prefer to start a new thread.

There are various ways to implement a sandbox, but I would like to
expose here how I implemented pysandbox to have your opinion.
pysandbox is written to execute quickly a short untrusted function in
a sandbox and then continue the normal execution of the program. It is
possible to "enable" the sandbox, but also later to "disable" it. It
is written for Python using only one thread and one process.

To create a sandbox, pysandbox uses various protections. The main idea
is to create an empty namespace and ensure that it is not possible to
use objects added into the namespace for escaping from the sandbox.
pysandbox only uses one thread and one process and so it doesn't
replace the existing trusted namespace, but create a new one. The
security of pysandbox depends on the sandbox namespace sealing.

I don't want to integrate pysandbox in CPython because I am not yet
conviced that the approach is secure by design. I am trying to patch
Python to help the implementation of Python security modules and of
read-only proxies.

You can find below the list of protections implemented in pysandbox.
Some of them are implemented in C.

I challenge anymore to break pysandbox! I would be happy if anyone
breaks it because it would make it more stronger.

https://github.com/haypo/pysandbox/
http://pypi.python.org/pypi/pysandbox

Namespace
=========

 * Make builtins read only
 * Remove function attribute:

   * frame.f_locals
   * function.func_closure/__closure__
   * function.func_defaults/__defaults__
   * function.func_globals/__globals__
   * type.__subclasses__
   * builtin_function.__self__

 * Workaround the lack of frozendict, remove dict attributes:

   *__init__
   * clear
   * __delitem__
   * pop
   * popitem
   * setdefault
   * __setitem__
   * update

 * Create a proxy for objects injected to the sandbox namespace and for
   the result of functions (the result of callable objects is also proxified)


Generic
=======

Remove all builtin symbols not in the whitelist.


Features
========

import
------

 * Replace __import__ function to use an import whitelist

Filesystem
----------

 * Replace open and file functions to deny access to the filesystem

Exit
----

 * Replace exit function
 * Remove SystemExit builtin exception

Standard input/output
---------------------

 * Replace sys.stdin, sys.stdout and sys.stderr


Bytecode
========

Execute arbitrary bytecode may crash Python, or lead to execution of arbitrary
(machine) code.

 * Patch code.__new__()
 * Remove attributes:

   * function.func_code/__code__
   * frame.f_code
   * generator.gi_code

Victor


More information about the Python-Dev mailing list