comparison venv/lib/python2.7/site-packages/jinja2/sandbox.py @ 0:d67268158946 draft

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