Skip to content

Commit

Permalink
Several checks for __builtins__ and builtins. (#134)
Browse files Browse the repository at this point in the history
* Several checks for __builtins__ and builtins.

builtins is a dangerous element in RestrictedPython, as it contains the whole Programming Environment with all modules and control access to them.
Should be forbidden to access.

Fixes #115
  • Loading branch information
loechel committed Oct 2, 2018
1 parent ebe4c64 commit 42b4be0
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/RestrictedPython/transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
FORBIDDEN_FUNC_NAMES = frozenset([
'print',
'printed',
'builtins',
])


Expand Down
27 changes: 27 additions & 0 deletions tests/test_Guards.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
from RestrictedPython._compat import IS_PY2
from RestrictedPython._compat import IS_PY3
from RestrictedPython.Guards import guarded_unpack_sequence
from RestrictedPython.Guards import safe_builtins
from RestrictedPython.Guards import safer_getattr
from tests import c_exec
from tests import e_eval
from tests import e_exec

Expand Down Expand Up @@ -214,3 +216,28 @@ def test_Guards__safer_getattr__3(e_exec):
)
e_exec(SAFER_GETATTR_ALLOWED, restricted_globals)
assert restricted_globals['result'] == 2


@pytest.mark.skipif(
IS_PY2,
reason="__builtins__ has been renamed in Python3 to builtins, "
"and need only to be tested there."
)
@pytest.mark.parametrize(*c_exec)
def test_call_py3_builtins(c_exec):
"""It should not be allowed to access global builtins in Python3."""
result = c_exec('builtins["getattr"]')
assert result.code is None
assert result.errors == ('Line 1: "builtins" is a reserved name.',)


@pytest.mark.skipif(
IS_PY3,
reason="__builtins__ has been renamed in Python3 to builtins."
)
@pytest.mark.parametrize(*c_exec)
def test_call_py2_builtins(c_exec):
"""It should not be allowed to access global __builtins__ in Python2."""
result = c_exec('__builtins__["getattr"]')
assert result.code is None
assert result.errors == ('Line 1: "__builtins__" is an invalid variable name because it starts with "_"',) # NOQA: E501
92 changes: 92 additions & 0 deletions tests/test_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"""

from RestrictedPython import safe_builtins
from RestrictedPython._compat import IS_PY2
from RestrictedPython._compat import IS_PY3
from tests import c_exec
from tests import e_exec

import pytest
Expand All @@ -29,3 +32,92 @@ def test_os_import(e_exec):
with pytest.raises(ImportError) as err:
e_exec(OS_IMPORT_EXAMPLE, glb)
assert '__import__ not found' == str(err.value)


__BUILTINS_EXAMPLE = """
import __builtins__
mygetattr = __builtins__['getattr']
"""


@pytest.mark.skipif(
IS_PY3,
reason="__builtins__ has been renamed in Python3 to builtins, "
"so no __builtins__ in Python3."
)
@pytest.mark.parametrize(*c_exec)
def test_import_py2_builtins(c_exec):
"""It should not be allowed to access global __builtins__ in Python2."""
result = c_exec(__BUILTINS_EXAMPLE)
assert result.code is None
assert result.errors == (
'Line 2: "__builtins__" is an invalid variable name because it starts with "_"', # NOQA: E501
'Line 4: "__builtins__" is an invalid variable name because it starts with "_"' # NOQA: E501
)


__BUILTINS_AS_EXAMPLE = """
import __builtins__ as builtins
mygetattr = builtins['getattr']
"""


@pytest.mark.skipif(
IS_PY3,
reason="__builtins__ has been renamed in Python3 to builtins, "
"so no __builtins__ in Python3."
)
@pytest.mark.parametrize(*c_exec)
def test_import_py2_as_builtins(c_exec):
"""It should not be allowed to access global __builtins__ in Python2."""
result = c_exec(__BUILTINS_EXAMPLE)
assert result.code is None
assert result.errors == (
'Line 2: "__builtins__" is an invalid variable name because it starts with "_"', # NOQA: E501
'Line 4: "__builtins__" is an invalid variable name because it starts with "_"' # NOQA: E501
)


BUILTINS_EXAMPLE = """
import builtins
mygetattr = builtins['getattr']
"""


@pytest.mark.skipif(
IS_PY2,
reason="__builtins__ has been renamed in Python3 to builtins, "
"and need only to be tested there."
)
@pytest.mark.parametrize(*c_exec)
def test_import_py3_builtins(c_exec):
"""It should not be allowed to access global builtins in Python3."""
result = c_exec(BUILTINS_EXAMPLE)
assert result.code is None
assert result.errors == (
'Line 2: "builtins" is a reserved name.',
'Line 4: "builtins" is a reserved name.'
)


BUILTINS_AS_EXAMPLE = """
import builtins as glb
mygetattr = glb['getattr']
"""


@pytest.mark.skipif(
IS_PY2,
reason="__builtins__ has been renamed in Python3 to builtins, "
"and need only to be tested there."
)
@pytest.mark.parametrize(*c_exec)
def test_import_py3_as_builtins(c_exec):
"""It should not be allowed to access global builtins in Python3."""
result = c_exec(BUILTINS_AS_EXAMPLE)
assert result.code is None
assert result.errors == ('Line 2: "builtins" is a reserved name.',)

0 comments on commit 42b4be0

Please sign in to comment.