[Python-Dev] Add a frozendict builtin type

Victor Stinner victor.stinner at haypocalc.com
Thu Mar 1 00:52:48 CET 2012


> It would (apparently) help Victor to fix issues in his pysandbox
> project. I don't know if a secure Python sandbox is an important
> enough concept to warrant core changes to make it possible.

Ok, let's talk about sandboxing and security.

The main idea of pysandbox is to reuse most of CPython but hide
"dangerous" functions and run untrusted code in a separated namespace.
The problem is to create the sandbox and ensure that it is not
possible to escape from this sandbox. pysandbox is still a
proof-of-concept, even if it works pretty well for short dummy
scripts. But pysandbox is not ready for real world programs.

pysandbox uses various "tricks" and "hacks" to create a sandbox. But
there is a major issue: the __builtins__ dict (or module) is available
and used everywhere (in module globals, in frames, in functions
globals, etc.), and can be modified. A read-only __builtins__ dict is
required to protect the sandbox. If the untrusted can modify
__builtins__, it can replace core functions like isinstance(), len(),
... and so modify code outside the sandbox.

To implement a frozendict in Python, pysandbox uses the blacklist
approach: a class inheriting from dict and override some methods to
raise an error. The whitelist approach cannot be used  for a type
implemented in Python, because the __builtins__ type must inherit from
dict: ceval.c expects a type compatible with PyDict_GetItem and
PyDict_SetItem.

Problem: if you implement a frozendict type inheriting from dict in
Python, it is still possible to call dict methods (e.g.
dict.__setitem__()). To fix this issue, pysandbox removes all dict
methods modifying the dict: __setitem__, __delitem__, pop, etc. This
is a problem because untrusted code cannot use these methods on valid
dict created in the sandbox.

> However,
> if Victor was saying that implementing this PEP was all that is needed
> to implement a secure sandbox, then that would be a very different
> claim, and likely much more compelling (to some, at least - I have no
> personal need for a secure sandbox).

A builtin frozendict type "compatible" with the PyDict C API is very
convinient for pysandbox because using this type for core features
like builtins requires very few modification. For example, use
frozendict for __builtins__ only requires to modify 3 lines in
frameobject.c.

I don't see how to solve the pysandbox issue (read-only __builtins__
issue, need to remove dict.__setitem__ & friends) without modifying
CPython (so without adding a frozendict type).

> As it stands, I don't find the PEP compelling. The hardening use case
> might be significant but Victor needs to spell it out if it's to make
> a difference.

I don't know if hardening Python is a compelling argument to add a new
builtin type.

Victor


More information about the Python-Dev mailing list