1645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# -*- coding: utf-8 -*- 2645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez""" 3645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez jinja2.sandbox 4645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ~~~~~~~~~~~~~~ 5645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 6645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Adds a sandbox layer to Jinja as it was the default behavior in the old 7645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Jinja 1 releases. This sandbox is slightly different from Jinja 1 as the 8645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez default behavior is easier to use. 9645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 10645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez The behavior can be changed by subclassing the environment. 11645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 12645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez :copyright: (c) 2010 by the Jinja Team. 13645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez :license: BSD. 14645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez""" 15645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport operator 16645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom jinja2.environment import Environment 17645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom jinja2.exceptions import SecurityError 18645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom jinja2._compat import string_types, function_type, method_type, \ 19645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez traceback_type, code_type, frame_type, generator_type, PY2 20645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 21645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 22645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#: maximum number of items a range may produce 23645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezMAX_RANGE = 100000 24645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 25645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#: attributes of function objects that are considered unsafe. 26645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezUNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict', 27645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'func_defaults', 'func_globals']) 28645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 29645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#: unsafe method attributes. function attributes are unsafe for methods too 30645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezUNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self']) 31645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 32645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#: unsafe generator attirbutes. 33645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector ChavezUNSAFE_GENERATOR_ATTRIBUTES = set(['gi_frame', 'gi_code']) 34645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 35645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# On versions > python 2 the special attributes on functions are gone, 36645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# but they remain on methods and generators for whatever reason. 37645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezif not PY2: 38645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez UNSAFE_FUNCTION_ATTRIBUTES = set() 39645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 40645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezimport warnings 41645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 42645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# make sure we don't warn in python 2.6 about stuff we don't care about 43645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezwarnings.filterwarnings('ignore', 'the sets module', DeprecationWarning, 44645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez module='jinja2.sandbox') 45645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 46645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezfrom collections import deque 47645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 48645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez_mutable_set_types = (set,) 49645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez_mutable_mapping_types = (dict,) 50645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez_mutable_sequence_types = (list,) 51645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 52645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 53645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# on python 2.x we can register the user collection types 54645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveztry: 55645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez from UserDict import UserDict, DictMixin 56645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez from UserList import UserList 57645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez _mutable_mapping_types += (UserDict, DictMixin) 58645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez _mutable_set_types += (UserList,) 59645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezexcept ImportError: 60645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pass 61645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 62645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez# if sets is still available, register the mutable set from there as well 63645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveztry: 64645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez from sets import Set 65645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez _mutable_set_types += (Set,) 66645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezexcept ImportError: 67645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pass 68645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 69645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez#: register Python 2.6 abstract base classes 70645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chaveztry: 71645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez from collections import MutableSet, MutableMapping, MutableSequence 72645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez _mutable_set_types += (MutableSet,) 73645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez _mutable_mapping_types += (MutableMapping,) 74645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez _mutable_sequence_types += (MutableSequence,) 75645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezexcept ImportError: 76645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pass 77645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 78645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez_mutable_spec = ( 79645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (_mutable_set_types, frozenset([ 80645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'add', 'clear', 'difference_update', 'discard', 'pop', 'remove', 81645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'symmetric_difference_update', 'update' 82645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ])), 83645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (_mutable_mapping_types, frozenset([ 84645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'clear', 'pop', 'popitem', 'setdefault', 'update' 85645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ])), 86645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (_mutable_sequence_types, frozenset([ 87645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'append', 'reverse', 'insert', 'sort', 'extend', 'remove' 88645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ])), 89645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (deque, frozenset([ 90645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'append', 'appendleft', 'clear', 'extend', 'extendleft', 'pop', 91645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'popleft', 'remove', 'rotate' 92645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ])) 93645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez) 94645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 95645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 96645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef safe_range(*args): 97645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """A range that can't generate ranges with a length of more than 98645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MAX_RANGE items. 99645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 100645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez rng = range(*args) 101645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if len(rng) > MAX_RANGE: 102645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raise OverflowError('range too big, maximum size for range is %d' % 103645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez MAX_RANGE) 104645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return rng 105645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 106645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 107645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef unsafe(f): 108645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Marks a function or method as unsafe. 109645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 110645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez :: 111645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 112645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez @unsafe 113645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def delete(self): 114645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pass 115645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 116645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez f.unsafe_callable = True 117645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return f 118645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 119645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 120645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef is_internal_attribute(obj, attr): 121645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Test if the attribute given is an internal python attribute. For 122645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez example this function returns `True` for the `func_code` attribute of 123645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez python objects. This is useful if the environment method 124645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez :meth:`~SandboxedEnvironment.is_safe_attribute` is overridden. 125645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 126645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> from jinja2.sandbox import is_internal_attribute 127645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> is_internal_attribute(lambda: None, "func_code") 128645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez True 129645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> is_internal_attribute((lambda x:x).func_code, 'co_code') 130645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez True 131645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> is_internal_attribute(str, "upper") 132645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez False 133645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 134645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if isinstance(obj, function_type): 135645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if attr in UNSAFE_FUNCTION_ATTRIBUTES: 136645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return True 137645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez elif isinstance(obj, method_type): 138645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if attr in UNSAFE_FUNCTION_ATTRIBUTES or \ 139645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez attr in UNSAFE_METHOD_ATTRIBUTES: 140645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return True 141645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez elif isinstance(obj, type): 142645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if attr == 'mro': 143645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return True 144645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez elif isinstance(obj, (code_type, traceback_type, frame_type)): 145645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return True 146645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez elif isinstance(obj, generator_type): 147645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if attr in UNSAFE_GENERATOR_ATTRIBUTES: 148645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return True 149645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return attr.startswith('__') 150645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 151645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 152645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezdef modifies_known_mutable(obj, attr): 153645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """This function checks if an attribute on a builtin mutable object 154645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez (list, dict, set or deque) would modify it if called. It also supports 155645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez the "user"-versions of the objects (`sets.Set`, `UserDict.*` etc.) and 156645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez with Python 2.6 onwards the abstract base classes `MutableSet`, 157645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez `MutableMapping`, and `MutableSequence`. 158645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 159645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> modifies_known_mutable({}, "clear") 160645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez True 161645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> modifies_known_mutable({}, "keys") 162645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez False 163645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> modifies_known_mutable([], "append") 164645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez True 165645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> modifies_known_mutable([], "index") 166645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez False 167645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 168645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez If called with an unsupported object (such as unicode) `False` is 169645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez returned. 170645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 171645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez >>> modifies_known_mutable("foo", "upper") 172645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez False 173645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 174645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez for typespec, unsafe in _mutable_spec: 175645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if isinstance(obj, typespec): 176645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return attr in unsafe 177645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return False 178645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 179645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 180645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass SandboxedEnvironment(Environment): 181645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """The sandboxed environment. It works like the regular environment but 182645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez tells the compiler to generate sandboxed code. Additionally subclasses of 183645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez this environment may override the methods that tell the runtime what 184645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez attributes or functions are safe to access. 185645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 186645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez If the template tries to access insecure code a :exc:`SecurityError` is 187645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raised. However also other exceptions may occour during the rendering so 188645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez the caller has to ensure that all exceptions are catched. 189645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 190645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez sandboxed = True 191645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 192645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: default callback table for the binary operators. A copy of this is 193645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: available on each instance of a sandboxed environment as 194645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: :attr:`binop_table` 195645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez default_binop_table = { 196645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez '+': operator.add, 197645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez '-': operator.sub, 198645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez '*': operator.mul, 199645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez '/': operator.truediv, 200645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez '//': operator.floordiv, 201645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez '**': operator.pow, 202645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez '%': operator.mod 203645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 204645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 205645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: default callback table for the unary operators. A copy of this is 206645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: available on each instance of a sandboxed environment as 207645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: :attr:`unop_table` 208645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez default_unop_table = { 209645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez '+': operator.pos, 210645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez '-': operator.neg 211645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez } 212645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 213645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: a set of binary operators that should be intercepted. Each operator 214645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: that is added to this set (empty by default) is delegated to the 215645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: :meth:`call_binop` method that will perform the operator. The default 216645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: operator callback is specified by :attr:`binop_table`. 217645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: 218645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: The following binary operators are interceptable: 219645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: ``//``, ``%``, ``+``, ``*``, ``-``, ``/``, and ``**`` 220645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: 221645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: The default operation form the operator table corresponds to the 222645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: builtin function. Intercepted calls are always slower than the native 223645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: operator call, so make sure only to intercept the ones you are 224645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: interested in. 225645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: 226645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: .. versionadded:: 2.6 227645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez intercepted_binops = frozenset() 228645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 229645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: a set of unary operators that should be intercepted. Each operator 230645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: that is added to this set (empty by default) is delegated to the 231645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: :meth:`call_unop` method that will perform the operator. The default 232645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: operator callback is specified by :attr:`unop_table`. 233645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: 234645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: The following unary operators are interceptable: ``+``, ``-`` 235645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: 236645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: The default operation form the operator table corresponds to the 237645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: builtin function. Intercepted calls are always slower than the native 238645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: operator call, so make sure only to intercept the ones you are 239645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: interested in. 240645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: 241645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez #: .. versionadded:: 2.6 242645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez intercepted_unops = frozenset() 243645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 244645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def intercept_unop(self, operator): 245645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Called during template compilation with the name of a unary 246645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez operator to check if it should be intercepted at runtime. If this 247645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez method returns `True`, :meth:`call_unop` is excuted for this unary 248645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez operator. The default implementation of :meth:`call_unop` will use 249645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez the :attr:`unop_table` dictionary to perform the operator with the 250645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez same logic as the builtin one. 251645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 252645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez The following unary operators are interceptable: ``+`` and ``-`` 253645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 254645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Intercepted calls are always slower than the native operator call, 255645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez so make sure only to intercept the ones you are interested in. 256645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 257645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez .. versionadded:: 2.6 258645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 259645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return False 260645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 261645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 262645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def __init__(self, *args, **kwargs): 263645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez Environment.__init__(self, *args, **kwargs) 264645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.globals['range'] = safe_range 265645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.binop_table = self.default_binop_table.copy() 266645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez self.unop_table = self.default_unop_table.copy() 267645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 268645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def is_safe_attribute(self, obj, attr, value): 269645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """The sandboxed environment will call this method to check if the 270645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez attribute of an object is safe to access. Per default all attributes 271645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez starting with an underscore are considered private as well as the 272645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez special attributes of internal python objects as returned by the 273645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez :func:`is_internal_attribute` function. 274645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 275645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return not (attr.startswith('_') or is_internal_attribute(obj, attr)) 276645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 277645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def is_safe_callable(self, obj): 278645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Check if an object is safely callable. Per default a function is 279645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez considered safe unless the `unsafe_callable` attribute exists and is 280645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez True. Override this method to alter the behavior, but this won't 281645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez affect the `unsafe` decorator from this module. 282645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 283645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return not (getattr(obj, 'unsafe_callable', False) or 284645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez getattr(obj, 'alters_data', False)) 285645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 286645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def call_binop(self, context, operator, left, right): 287645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """For intercepted binary operator calls (:meth:`intercepted_binops`) 288645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez this function is executed instead of the builtin operator. This can 289645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez be used to fine tune the behavior of certain operators. 290645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 291645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez .. versionadded:: 2.6 292645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 293645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self.binop_table[operator](left, right) 294645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 295645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def call_unop(self, context, operator, arg): 296645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """For intercepted unary operator calls (:meth:`intercepted_unops`) 297645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez this function is executed instead of the builtin operator. This can 298645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez be used to fine tune the behavior of certain operators. 299645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 300645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez .. versionadded:: 2.6 301645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 302645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self.unop_table[operator](arg) 303645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 304645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def getitem(self, obj, argument): 305645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Subscribe an object from sandboxed code.""" 306645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try: 307645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return obj[argument] 308645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez except (TypeError, LookupError): 309645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if isinstance(argument, string_types): 310645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try: 311645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez attr = str(argument) 312645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez except Exception: 313645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pass 314645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez else: 315645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try: 316645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez value = getattr(obj, attr) 317645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez except AttributeError: 318645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pass 319645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez else: 320645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if self.is_safe_attribute(obj, argument, value): 321645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return value 322645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self.unsafe_undefined(obj, argument) 323645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self.undefined(obj=obj, name=argument) 324645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 325645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def getattr(self, obj, attribute): 326645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Subscribe an object from sandboxed code and prefer the 327645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez attribute. The attribute passed *must* be a bytestring. 328645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 329645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try: 330645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez value = getattr(obj, attribute) 331645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez except AttributeError: 332645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez try: 333645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return obj[attribute] 334645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez except (TypeError, LookupError): 335645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez pass 336645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez else: 337645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if self.is_safe_attribute(obj, attribute, value): 338645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return value 339645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self.unsafe_undefined(obj, attribute) 340645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self.undefined(obj=obj, name=attribute) 341645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 342645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def unsafe_undefined(self, obj, attribute): 343645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Return an undefined object for unsafe attributes.""" 344645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return self.undefined('access to attribute %r of %r ' 345645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 'object is unsafe.' % ( 346645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez attribute, 347645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez obj.__class__.__name__ 348645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez ), name=attribute, obj=obj, exc=SecurityError) 349645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 350645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def call(__self, __context, __obj, *args, **kwargs): 351645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Call an object from sandboxed code.""" 352645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # the double prefixes are to avoid double keyword argument 353645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez # errors when proxying the call. 354645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if not __self.is_safe_callable(__obj): 355645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez raise SecurityError('%r is not safely callable' % (__obj,)) 356645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return __context.call(__obj, *args, **kwargs) 357645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 358645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 359645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavezclass ImmutableSandboxedEnvironment(SandboxedEnvironment): 360645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """Works exactly like the regular `SandboxedEnvironment` but does not 361645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez permit modifications on the builtin mutable objects `list`, `set`, and 362645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez `dict` by using the :func:`modifies_known_mutable` function. 363645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez """ 364645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez 365645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez def is_safe_attribute(self, obj, attr, value): 366645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value): 367645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return False 368645501c2ab19a559ce82a1d5a29ced159a4c30fbLuis Hector Chavez return not modifies_known_mutable(obj, attr) 369