Skip to content
This repository has been archived by the owner on Aug 30, 2019. It is now read-only.

Commit

Permalink
Deny access to dict.__init__() to protect __builtins__
Browse files Browse the repository at this point in the history
And set version to 1.0.3
  • Loading branch information
Victor Stinner committed Sep 16, 2010
1 parent 1903cba commit 5fbe725
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 31 deletions.
4 changes: 4 additions & 0 deletions ChangeLog
@@ -1,3 +1,7 @@
Version 1.0.3 (2010-09-16)

* SECURITY FIX: Deny access to dict.__init__() to protect __builtins__.

Version 1.0.2 (2010-09-15)

* SECURITY FIX: Deny access to all dict methods able to modify a dict, not
Expand Down
2 changes: 1 addition & 1 deletion sandbox/attributes.py
Expand Up @@ -30,7 +30,7 @@ def enable(self, sandbox):
# Blacklist all dict methods able to modify a dict, to protect
# ReadOnlyBuiltins
for name in (
'clear', '__delitem__', 'pop', 'popitem',
'__init__', 'clear', '__delitem__', 'pop', 'popitem',
'setdefault', '__setitem__', 'update'):
del self.dict_dict[name]
if version_info < (3, 0):
Expand Down
49 changes: 28 additions & 21 deletions sandbox/blacklist_proxy.py
Expand Up @@ -8,34 +8,41 @@

from .proxy import proxy, readOnlyError

# If you update this class, update also HideAttributes.enable()
class ReadOnlyBuiltins(dict):
"""
Type used for a read only version of the __builtins__ dictionary.
def createReadOnlyBuiltins(builtins):
# If you update this class, update also HideAttributes.enable()
class ReadOnlyBuiltins(dict):
"""
Type used for a read only version of the __builtins__ dictionary.
Don't proxy __getattr__ because we suppose that __builtins__ only contains
safe functions (not mutable objects).
"""
__slots__ = tuple()
Don't proxy __getattr__ because we suppose that __builtins__ only contains
safe functions (not mutable objects).
"""
__slots__ = tuple()

def clear(self):
readOnlyError()
def clear(self):
readOnlyError()

def __delitem__(self, key):
readOnlyError()
def __delitem__(self, key):
readOnlyError()

def pop(self, key, default=None):
readOnlyError()
def pop(self, key, default=None):
readOnlyError()

def popitem(self):
readOnlyError()
def popitem(self):
readOnlyError()

def setdefault(self, key, value):
readOnlyError()
def setdefault(self, key, value):
readOnlyError()

def __setitem__(self, key, value):
readOnlyError()
def __setitem__(self, key, value):
readOnlyError()

def update(self, dict, **kw):
readOnlyError()

def update(self, dict, **kw):
safe = ReadOnlyBuiltins(builtins)
def __init__(*args, **kw):
readOnlyError()
ReadOnlyBuiltins.__init__ = __init__
return safe

4 changes: 2 additions & 2 deletions sandbox/builtins.py
Expand Up @@ -9,7 +9,7 @@
from .safe_import import _safe_import
from .restorable_dict import RestorableDict
from .proxy import createReadOnlyObject
from .blacklist_proxy import ReadOnlyBuiltins
from .blacklist_proxy import createReadOnlyBuiltins
if USE_CSANDBOX:
from _sandbox import set_frame_builtins, set_interp_builtins

Expand Down Expand Up @@ -74,7 +74,7 @@ def safe_exit(code=0):
del self.builtin_dict['help']

# Make builtins read only (enable restricted mode)
safe_builtins = ReadOnlyBuiltins(self.builtin_dict.dict)
safe_builtins = createReadOnlyBuiltins(self.builtin_dict.dict)
if USE_CSANDBOX:
set_frame_builtins(self.frame, safe_builtins)
if not config.cpython_restricted:
Expand Down
2 changes: 1 addition & 1 deletion sandbox/version.py
@@ -1,4 +1,4 @@
PACKAGE = "pysandbox"
VERSION = "1.0.2"
VERSION = "1.0.3"
LICENSE = "BSD"
URL = "http://github.com/haypo/pysandbox/"
10 changes: 4 additions & 6 deletions tests.py
Expand Up @@ -55,13 +55,11 @@ def access_denied():
read_first_line(open)

def test_exec_builtins():
from sandbox.builtins import ReadOnlyBuiltins

def check_builtins_type():
result = []
exec "result.append(type(__builtins__))" in {'result': result}
builtin_type = result[0]
assert builtin_type == ReadOnlyBuiltins
assert builtin_type != dict
createSandbox().call(check_builtins_type)
else:
print "USE_CSANDBOX=False: disable test_open_whitelist(), test_exec_builtins()"
Expand Down Expand Up @@ -605,7 +603,7 @@ def test(*lines, **kw):
globals=namespace)
assert set(namespace.keys()) == set(('a', 'x', '__builtins__'))
assert namespace['a'] == 10
assert namespace['x'] == 42
assert namespace['x'] == 42

namespace = {'b': 2}
test(
Expand All @@ -626,12 +624,12 @@ def test(*lines, **kw):
"x=42",
"a=10",
"b=20",
globals=my_globals,
globals=my_globals,
locals=namespace)
assert set(my_globals.keys()) == set(('a', '__builtins__'))
assert my_globals['a'] == 1
assert namespace == {'a': 10, 'b': 20, 'x': 42}

namespace = {}
test('a=1', locals=namespace)
assert namespace == {'a': 1}, namespace
Expand Down

0 comments on commit 5fbe725

Please sign in to comment.