Run `./2to3.py -w jinja2`
[jinja2.git] / jinja2 / sandbox.py
1 # -*- coding: utf-8 -*-
2 """
3     jinja2.sandbox
4     ~~~~~~~~~~~~~~
5
6     Adds a sandbox layer to Jinja as it was the default behavior in the old
7     Jinja 1 releases.  This sandbox is slightly different from Jinja 1 as the
8     default behavior is easier to use.
9
10     The behavior can be changed by subclassing the environment.
11
12     :copyright: (c) 2010 by the Jinja Team.
13     :license: BSD.
14 """
15 import operator
16 from jinja2.environment import Environment
17 from jinja2.exceptions import SecurityError
18 from jinja2.utils import FunctionType, MethodType, TracebackType, CodeType, \
19      FrameType, GeneratorType
20
21
22 #: maximum number of items a range may produce
23 MAX_RANGE = 100000
24
25 #: attributes of function objects that are considered unsafe.
26 UNSAFE_FUNCTION_ATTRIBUTES = set(['func_closure', 'func_code', 'func_dict',
27                                   'func_defaults', 'func_globals'])
28
29 #: unsafe method attributes.  function attributes are unsafe for methods too
30 UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
31
32
33 import warnings
34
35 # make sure we don't warn in python 2.6 about stuff we don't care about
36 warnings.filterwarnings('ignore', 'the sets module', DeprecationWarning,
37                         module='jinja2.sandbox')
38
39 from collections import deque
40
41 _mutable_set_types = (set,)
42 _mutable_mapping_types = (dict,)
43 _mutable_sequence_types = (list,)
44
45
46 # on python 2.x we can register the user collection types
47 try:
48     from UserDict import UserDict, DictMixin
49     from collections import UserList
50     _mutable_mapping_types += (UserDict, DictMixin)
51     _mutable_set_types += (UserList,)
52 except ImportError:
53     pass
54
55 # if sets is still available, register the mutable set from there as well
56 try:
57     from sets import Set
58     _mutable_set_types += (Set,)
59 except ImportError:
60     pass
61
62 #: register Python 2.6 abstract base classes
63 try:
64     from collections import MutableSet, MutableMapping, MutableSequence
65     _mutable_set_types += (MutableSet,)
66     _mutable_mapping_types += (MutableMapping,)
67     _mutable_sequence_types += (MutableSequence,)
68 except ImportError:
69     pass
70
71 _mutable_spec = (
72     (_mutable_set_types, frozenset([
73         'add', 'clear', 'difference_update', 'discard', 'pop', 'remove',
74         'symmetric_difference_update', 'update'
75     ])),
76     (_mutable_mapping_types, frozenset([
77         'clear', 'pop', 'popitem', 'setdefault', 'update'
78     ])),
79     (_mutable_sequence_types, frozenset([
80         'append', 'reverse', 'insert', 'sort', 'extend', 'remove'
81     ])),
82     (deque, frozenset([
83         'append', 'appendleft', 'clear', 'extend', 'extendleft', 'pop',
84         'popleft', 'remove', 'rotate'
85     ]))
86 )
87
88
89 def safe_range(*args):
90     """A range that can't generate ranges with a length of more than
91     MAX_RANGE items.
92     """
93     rng = range(*args)
94     if len(rng) > MAX_RANGE:
95         raise OverflowError('range too big, maximum size for range is %d' %
96                             MAX_RANGE)
97     return rng
98
99
100 def unsafe(f):
101     """Marks a function or method as unsafe.
102
103     ::
104
105         @unsafe
106         def delete(self):
107             pass
108     """
109     f.unsafe_callable = True
110     return f
111
112
113 def is_internal_attribute(obj, attr):
114     """Test if the attribute given is an internal python attribute.  For
115     example this function returns `True` for the `func_code` attribute of
116     python objects.  This is useful if the environment method
117     :meth:`~SandboxedEnvironment.is_safe_attribute` is overriden.
118
119     >>> from jinja2.sandbox import is_internal_attribute
120     >>> is_internal_attribute(lambda: None, "func_code")
121     True
122     >>> is_internal_attribute((lambda x:x).func_code, 'co_code')
123     True
124     >>> is_internal_attribute(str, "upper")
125     False
126     """
127     if isinstance(obj, FunctionType):
128         if attr in UNSAFE_FUNCTION_ATTRIBUTES:
129             return True
130     elif isinstance(obj, MethodType):
131         if attr in UNSAFE_FUNCTION_ATTRIBUTES or \
132            attr in UNSAFE_METHOD_ATTRIBUTES:
133             return True
134     elif isinstance(obj, type):
135         if attr == 'mro':
136             return True
137     elif isinstance(obj, (CodeType, TracebackType, FrameType)):
138         return True
139     elif isinstance(obj, GeneratorType):
140         if attr == 'gi_frame':
141             return True
142     return attr.startswith('__')
143
144
145 def modifies_known_mutable(obj, attr):
146     """This function checks if an attribute on a builtin mutable object
147     (list, dict, set or deque) would modify it if called.  It also supports
148     the "user"-versions of the objects (`sets.Set`, `UserDict.*` etc.) and
149     with Python 2.6 onwards the abstract base classes `MutableSet`,
150     `MutableMapping`, and `MutableSequence`.
151
152     >>> modifies_known_mutable({}, "clear")
153     True
154     >>> modifies_known_mutable({}, "keys")
155     False
156     >>> modifies_known_mutable([], "append")
157     True
158     >>> modifies_known_mutable([], "index")
159     False
160
161     If called with an unsupported object (such as unicode) `False` is
162     returned.
163
164     >>> modifies_known_mutable("foo", "upper")
165     False
166     """
167     for typespec, unsafe in _mutable_spec:
168         if isinstance(obj, typespec):
169             return attr in unsafe
170     return False
171
172
173 class SandboxedEnvironment(Environment):
174     """The sandboxed environment.  It works like the regular environment but
175     tells the compiler to generate sandboxed code.  Additionally subclasses of
176     this environment may override the methods that tell the runtime what
177     attributes or functions are safe to access.
178
179     If the template tries to access insecure code a :exc:`SecurityError` is
180     raised.  However also other exceptions may occour during the rendering so
181     the caller has to ensure that all exceptions are catched.
182     """
183     sandboxed = True
184
185     #: default callback table for the binary operators.  A copy of this is
186     #: available on each instance of a sandboxed environment as
187     #: :attr:`binop_table`
188     default_binop_table = {
189         '+':        operator.add,
190         '-':        operator.sub,
191         '*':        operator.mul,
192         '/':        operator.truediv,
193         '//':       operator.floordiv,
194         '**':       operator.pow,
195         '%':        operator.mod
196     }
197
198     #: default callback table for the unary operators.  A copy of this is
199     #: available on each instance of a sandboxed environment as
200     #: :attr:`unop_table`
201     default_unop_table = {
202         '+':        operator.pos,
203         '-':        operator.neg
204     }
205
206     #: a set of binary operators that should be intercepted.  Each operator
207     #: that is added to this set (empty by default) is delegated to the
208     #: :meth:`call_binop` method that will perform the operator.  The default
209     #: operator callback is specified by :attr:`binop_table`.
210     #:
211     #: The following binary operators are interceptable:
212     #: ``//``, ``%``, ``+``, ``*``, ``-``, ``/``, and ``**``
213     #:
214     #: The default operation form the operator table corresponds to the
215     #: builtin function.  Intercepted calls are always slower than the native
216     #: operator call, so make sure only to intercept the ones you are
217     #: interested in.
218     #:
219     #: .. versionadded:: 2.6
220     intercepted_binops = frozenset()
221
222     #: a set of unary operators that should be intercepted.  Each operator
223     #: that is added to this set (empty by default) is delegated to the
224     #: :meth:`call_unop` method that will perform the operator.  The default
225     #: operator callback is specified by :attr:`unop_table`.
226     #:
227     #: The following unary operators are interceptable: ``+``, ``-``
228     #:
229     #: The default operation form the operator table corresponds to the
230     #: builtin function.  Intercepted calls are always slower than the native
231     #: operator call, so make sure only to intercept the ones you are
232     #: interested in.
233     #:
234     #: .. versionadded:: 2.6
235     intercepted_unops = frozenset()
236
237     def intercept_unop(self, operator):
238         """Called during template compilation with the name of a unary
239         operator to check if it should be intercepted at runtime.  If this
240         method returns `True`, :meth:`call_unop` is excuted for this unary
241         operator.  The default implementation of :meth:`call_unop` will use
242         the :attr:`unop_table` dictionary to perform the operator with the
243         same logic as the builtin one.
244
245         The following unary operators are interceptable: ``+`` and ``-``
246
247         Intercepted calls are always slower than the native operator call,
248         so make sure only to intercept the ones you are interested in.
249
250         .. versionadded:: 2.6
251         """
252         return False
253
254
255     def __init__(self, *args, **kwargs):
256         Environment.__init__(self, *args, **kwargs)
257         self.globals['range'] = safe_range
258         self.binop_table = self.default_binop_table.copy()
259         self.unop_table = self.default_unop_table.copy()
260
261     def is_safe_attribute(self, obj, attr, value):
262         """The sandboxed environment will call this method to check if the
263         attribute of an object is safe to access.  Per default all attributes
264         starting with an underscore are considered private as well as the
265         special attributes of internal python objects as returned by the
266         :func:`is_internal_attribute` function.
267         """
268         return not (attr.startswith('_') or is_internal_attribute(obj, attr))
269
270     def is_safe_callable(self, obj):
271         """Check if an object is safely callable.  Per default a function is
272         considered safe unless the `unsafe_callable` attribute exists and is
273         True.  Override this method to alter the behavior, but this won't
274         affect the `unsafe` decorator from this module.
275         """
276         return not (getattr(obj, 'unsafe_callable', False) or
277                     getattr(obj, 'alters_data', False))
278
279     def call_binop(self, context, operator, left, right):
280         """For intercepted binary operator calls (:meth:`intercepted_binops`)
281         this function is executed instead of the builtin operator.  This can
282         be used to fine tune the behavior of certain operators.
283
284         .. versionadded:: 2.6
285         """
286         return self.binop_table[operator](left, right)
287
288     def call_unop(self, context, operator, arg):
289         """For intercepted unary operator calls (:meth:`intercepted_unops`)
290         this function is executed instead of the builtin operator.  This can
291         be used to fine tune the behavior of certain operators.
292
293         .. versionadded:: 2.6
294         """
295         return self.unop_table[operator](arg)
296
297     def getitem(self, obj, argument):
298         """Subscribe an object from sandboxed code."""
299         try:
300             return obj[argument]
301         except (TypeError, LookupError):
302             if isinstance(argument, str):
303                 try:
304                     attr = str(argument)
305                 except Exception:
306                     pass
307                 else:
308                     try:
309                         value = getattr(obj, attr)
310                     except AttributeError:
311                         pass
312                     else:
313                         if self.is_safe_attribute(obj, argument, value):
314                             return value
315                         return self.unsafe_undefined(obj, argument)
316         return self.undefined(obj=obj, name=argument)
317
318     def getattr(self, obj, attribute):
319         """Subscribe an object from sandboxed code and prefer the
320         attribute.  The attribute passed *must* be a bytestring.
321         """
322         try:
323             value = getattr(obj, attribute)
324         except AttributeError:
325             try:
326                 return obj[attribute]
327             except (TypeError, LookupError):
328                 pass
329         else:
330             if self.is_safe_attribute(obj, attribute, value):
331                 return value
332             return self.unsafe_undefined(obj, attribute)
333         return self.undefined(obj=obj, name=attribute)
334
335     def unsafe_undefined(self, obj, attribute):
336         """Return an undefined object for unsafe attributes."""
337         return self.undefined('access to attribute %r of %r '
338                               'object is unsafe.' % (
339             attribute,
340             obj.__class__.__name__
341         ), name=attribute, obj=obj, exc=SecurityError)
342
343     def call(__self, __context, __obj, *args, **kwargs):
344         """Call an object from sandboxed code."""
345         # the double prefixes are to avoid double keyword argument
346         # errors when proxying the call.
347         if not __self.is_safe_callable(__obj):
348             raise SecurityError('%r is not safely callable' % (__obj,))
349         return __context.call(__obj, *args, **kwargs)
350
351
352 class ImmutableSandboxedEnvironment(SandboxedEnvironment):
353     """Works exactly like the regular `SandboxedEnvironment` but does not
354     permit modifications on the builtin mutable objects `list`, `set`, and
355     `dict` by using the :func:`modifies_known_mutable` function.
356     """
357
358     def is_safe_attribute(self, obj, attr, value):
359         if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value):
360             return False
361         return not modifies_known_mutable(obj, attr)