17d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)# -*- coding: utf-8 -*-
27d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)"""
37d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    jinja2.sandbox
47d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ~~~~~~~~~~~~~~
57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
67d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    Adds a sandbox layer to Jinja as it was the default behavior in the old
77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    Jinja 1 releases.  This sandbox is slightly different from Jinja 1 as the
87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    default behavior is easier to use.
97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    The behavior can be changed by subclassing the environment.
117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    :copyright: (c) 2010 by the Jinja Team.
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    :license: BSD.
147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)"""
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)import operator
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)from jinja2.environment import Environment
177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)from jinja2.exceptions import SecurityError
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochfrom jinja2._compat import string_types, function_type, method_type, \
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)     traceback_type, code_type, frame_type, generator_type, PY2
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#: maximum number of items a range may produce
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochMAX_RANGE = 100000
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#: attributes of function objects that are considered unsafe.
26eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochUNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict',
27eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                  'func_defaults', 'func_globals'])
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
29eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#: unsafe method attributes.  function attributes are unsafe for methods too
30eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochUNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
31eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#: unsafe generator attirbutes.
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochUNSAFE_GENERATOR_ATTRIBUTES = set(['gi_frame', 'gi_code'])
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch# On versions > python 2 the special attributes on functions are gone,
367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)# but they remain on methods and generators for whatever reason.
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)if not PY2:
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    UNSAFE_FUNCTION_ATTRIBUTES = set()
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochimport warnings
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)# make sure we don't warn in python 2.6 about stuff we don't care about
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)warnings.filterwarnings('ignore', 'the sets module', DeprecationWarning,
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                        module='jinja2.sandbox')
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)from collections import deque
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)_mutable_set_types = (set,)
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)_mutable_mapping_types = (dict,)
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)_mutable_sequence_types = (list,)
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)# on python 2.x we can register the user collection types
547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)try:
557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    from UserDict import UserDict, DictMixin
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    from UserList import UserList
577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    _mutable_mapping_types += (UserDict, DictMixin)
587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    _mutable_set_types += (UserList,)
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)except ImportError:
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    pass
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)# if sets is still available, register the mutable set from there as well
637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)try:
647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    from sets import Set
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    _mutable_set_types += (Set,)
667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)except ImportError:
677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    pass
687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#: register Python 2.6 abstract base classes
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)try:
717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    from collections import MutableSet, MutableMapping, MutableSequence
727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    _mutable_set_types += (MutableSet,)
737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    _mutable_mapping_types += (MutableMapping,)
747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    _mutable_sequence_types += (MutableSequence,)
757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)except ImportError:
767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    pass
777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)_mutable_spec = (
797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    (_mutable_set_types, frozenset([
807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        'add', 'clear', 'difference_update', 'discard', 'pop', 'remove',
817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        'symmetric_difference_update', 'update'
827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ])),
837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    (_mutable_mapping_types, frozenset([
847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        'clear', 'pop', 'popitem', 'setdefault', 'update'
857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ])),
867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    (_mutable_sequence_types, frozenset([
877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        'append', 'reverse', 'insert', 'sort', 'extend', 'remove'
887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ])),
897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    (deque, frozenset([
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        'append', 'appendleft', 'clear', 'extend', 'extendleft', 'pop',
91eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        'popleft', 'remove', 'rotate'
92eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ]))
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch)
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)def safe_range(*args):
977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    """A range that can't generate ranges with a length of more than
987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    MAX_RANGE items.
997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    """
1007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    rng = range(*args)
1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if len(rng) > MAX_RANGE:
1027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        raise OverflowError('range too big, maximum size for range is %d' %
1037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                            MAX_RANGE)
1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return rng
1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)def unsafe(f):
1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    """Marks a function or method as unsafe.
1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ::
1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        @unsafe
1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        def delete(self):
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            pass
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    """
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    f.unsafe_callable = True
1177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return f
1187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)def is_internal_attribute(obj, attr):
1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    """Test if the attribute given is an internal python attribute.  For
1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    example this function returns `True` for the `func_code` attribute of
123    python objects.  This is useful if the environment method
124    :meth:`~SandboxedEnvironment.is_safe_attribute` is overridden.
125
126    >>> from jinja2.sandbox import is_internal_attribute
127    >>> is_internal_attribute(lambda: None, "func_code")
128    True
129    >>> is_internal_attribute((lambda x:x).func_code, 'co_code')
130    True
131    >>> is_internal_attribute(str, "upper")
132    False
133    """
134    if isinstance(obj, function_type):
135        if attr in UNSAFE_FUNCTION_ATTRIBUTES:
136            return True
137    elif isinstance(obj, method_type):
138        if attr in UNSAFE_FUNCTION_ATTRIBUTES or \
139           attr in UNSAFE_METHOD_ATTRIBUTES:
140            return True
141    elif isinstance(obj, type):
142        if attr == 'mro':
143            return True
144    elif isinstance(obj, (code_type, traceback_type, frame_type)):
145        return True
146    elif isinstance(obj, generator_type):
147        if attr in UNSAFE_GENERATOR_ATTRIBUTES:
148            return True
149    return attr.startswith('__')
150
151
152def modifies_known_mutable(obj, attr):
153    """This function checks if an attribute on a builtin mutable object
154    (list, dict, set or deque) would modify it if called.  It also supports
155    the "user"-versions of the objects (`sets.Set`, `UserDict.*` etc.) and
156    with Python 2.6 onwards the abstract base classes `MutableSet`,
157    `MutableMapping`, and `MutableSequence`.
158
159    >>> modifies_known_mutable({}, "clear")
160    True
161    >>> modifies_known_mutable({}, "keys")
162    False
163    >>> modifies_known_mutable([], "append")
164    True
165    >>> modifies_known_mutable([], "index")
166    False
167
168    If called with an unsupported object (such as unicode) `False` is
169    returned.
170
171    >>> modifies_known_mutable("foo", "upper")
172    False
173    """
174    for typespec, unsafe in _mutable_spec:
175        if isinstance(obj, typespec):
176            return attr in unsafe
177    return False
178
179
180class SandboxedEnvironment(Environment):
181    """The sandboxed environment.  It works like the regular environment but
182    tells the compiler to generate sandboxed code.  Additionally subclasses of
183    this environment may override the methods that tell the runtime what
184    attributes or functions are safe to access.
185
186    If the template tries to access insecure code a :exc:`SecurityError` is
187    raised.  However also other exceptions may occour during the rendering so
188    the caller has to ensure that all exceptions are catched.
189    """
190    sandboxed = True
191
192    #: default callback table for the binary operators.  A copy of this is
193    #: available on each instance of a sandboxed environment as
194    #: :attr:`binop_table`
195    default_binop_table = {
196        '+':        operator.add,
197        '-':        operator.sub,
198        '*':        operator.mul,
199        '/':        operator.truediv,
200        '//':       operator.floordiv,
201        '**':       operator.pow,
202        '%':        operator.mod
203    }
204
205    #: default callback table for the unary operators.  A copy of this is
206    #: available on each instance of a sandboxed environment as
207    #: :attr:`unop_table`
208    default_unop_table = {
209        '+':        operator.pos,
210        '-':        operator.neg
211    }
212
213    #: a set of binary operators that should be intercepted.  Each operator
214    #: that is added to this set (empty by default) is delegated to the
215    #: :meth:`call_binop` method that will perform the operator.  The default
216    #: operator callback is specified by :attr:`binop_table`.
217    #:
218    #: The following binary operators are interceptable:
219    #: ``//``, ``%``, ``+``, ``*``, ``-``, ``/``, and ``**``
220    #:
221    #: The default operation form the operator table corresponds to the
222    #: builtin function.  Intercepted calls are always slower than the native
223    #: operator call, so make sure only to intercept the ones you are
224    #: interested in.
225    #:
226    #: .. versionadded:: 2.6
227    intercepted_binops = frozenset()
228
229    #: a set of unary operators that should be intercepted.  Each operator
230    #: that is added to this set (empty by default) is delegated to the
231    #: :meth:`call_unop` method that will perform the operator.  The default
232    #: operator callback is specified by :attr:`unop_table`.
233    #:
234    #: The following unary operators are interceptable: ``+``, ``-``
235    #:
236    #: The default operation form the operator table corresponds to the
237    #: builtin function.  Intercepted calls are always slower than the native
238    #: operator call, so make sure only to intercept the ones you are
239    #: interested in.
240    #:
241    #: .. versionadded:: 2.6
242    intercepted_unops = frozenset()
243
244    def intercept_unop(self, operator):
245        """Called during template compilation with the name of a unary
246        operator to check if it should be intercepted at runtime.  If this
247        method returns `True`, :meth:`call_unop` is excuted for this unary
248        operator.  The default implementation of :meth:`call_unop` will use
249        the :attr:`unop_table` dictionary to perform the operator with the
250        same logic as the builtin one.
251
252        The following unary operators are interceptable: ``+`` and ``-``
253
254        Intercepted calls are always slower than the native operator call,
255        so make sure only to intercept the ones you are interested in.
256
257        .. versionadded:: 2.6
258        """
259        return False
260
261
262    def __init__(self, *args, **kwargs):
263        Environment.__init__(self, *args, **kwargs)
264        self.globals['range'] = safe_range
265        self.binop_table = self.default_binop_table.copy()
266        self.unop_table = self.default_unop_table.copy()
267
268    def is_safe_attribute(self, obj, attr, value):
269        """The sandboxed environment will call this method to check if the
270        attribute of an object is safe to access.  Per default all attributes
271        starting with an underscore are considered private as well as the
272        special attributes of internal python objects as returned by the
273        :func:`is_internal_attribute` function.
274        """
275        return not (attr.startswith('_') or is_internal_attribute(obj, attr))
276
277    def is_safe_callable(self, obj):
278        """Check if an object is safely callable.  Per default a function is
279        considered safe unless the `unsafe_callable` attribute exists and is
280        True.  Override this method to alter the behavior, but this won't
281        affect the `unsafe` decorator from this module.
282        """
283        return not (getattr(obj, 'unsafe_callable', False) or
284                    getattr(obj, 'alters_data', False))
285
286    def call_binop(self, context, operator, left, right):
287        """For intercepted binary operator calls (:meth:`intercepted_binops`)
288        this function is executed instead of the builtin operator.  This can
289        be used to fine tune the behavior of certain operators.
290
291        .. versionadded:: 2.6
292        """
293        return self.binop_table[operator](left, right)
294
295    def call_unop(self, context, operator, arg):
296        """For intercepted unary operator calls (:meth:`intercepted_unops`)
297        this function is executed instead of the builtin operator.  This can
298        be used to fine tune the behavior of certain operators.
299
300        .. versionadded:: 2.6
301        """
302        return self.unop_table[operator](arg)
303
304    def getitem(self, obj, argument):
305        """Subscribe an object from sandboxed code."""
306        try:
307            return obj[argument]
308        except (TypeError, LookupError):
309            if isinstance(argument, string_types):
310                try:
311                    attr = str(argument)
312                except Exception:
313                    pass
314                else:
315                    try:
316                        value = getattr(obj, attr)
317                    except AttributeError:
318                        pass
319                    else:
320                        if self.is_safe_attribute(obj, argument, value):
321                            return value
322                        return self.unsafe_undefined(obj, argument)
323        return self.undefined(obj=obj, name=argument)
324
325    def getattr(self, obj, attribute):
326        """Subscribe an object from sandboxed code and prefer the
327        attribute.  The attribute passed *must* be a bytestring.
328        """
329        try:
330            value = getattr(obj, attribute)
331        except AttributeError:
332            try:
333                return obj[attribute]
334            except (TypeError, LookupError):
335                pass
336        else:
337            if self.is_safe_attribute(obj, attribute, value):
338                return value
339            return self.unsafe_undefined(obj, attribute)
340        return self.undefined(obj=obj, name=attribute)
341
342    def unsafe_undefined(self, obj, attribute):
343        """Return an undefined object for unsafe attributes."""
344        return self.undefined('access to attribute %r of %r '
345                              'object is unsafe.' % (
346            attribute,
347            obj.__class__.__name__
348        ), name=attribute, obj=obj, exc=SecurityError)
349
350    def call(__self, __context, __obj, *args, **kwargs):
351        """Call an object from sandboxed code."""
352        # the double prefixes are to avoid double keyword argument
353        # errors when proxying the call.
354        if not __self.is_safe_callable(__obj):
355            raise SecurityError('%r is not safely callable' % (__obj,))
356        return __context.call(__obj, *args, **kwargs)
357
358
359class ImmutableSandboxedEnvironment(SandboxedEnvironment):
360    """Works exactly like the regular `SandboxedEnvironment` but does not
361    permit modifications on the builtin mutable objects `list`, `set`, and
362    `dict` by using the :func:`modifies_known_mutable` function.
363    """
364
365    def is_safe_attribute(self, obj, attr, value):
366        if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value):
367            return False
368        return not modifies_known_mutable(obj, attr)
369