blob: 4b9ac13832a90035e3d033161c5501b054b0a488 [file] [log] [blame]
Armin Ronacherc63243e2008-04-14 22:53:58 +02001# -*- 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: Copyright 2008 by Armin Ronacher.
13 :license: BSD.
14"""
Armin Ronacherb5f522c2008-05-04 18:25:02 +020015from types import FunctionType, MethodType, TracebackType, CodeType, \
16 FrameType, GeneratorType
Armin Ronacherc63243e2008-04-14 22:53:58 +020017from jinja2.runtime import Undefined
18from jinja2.environment import Environment
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +020019from jinja2.exceptions import SecurityError
Armin Ronacherc63243e2008-04-14 22:53:58 +020020
21
22#: maximum number of items a range may produce
23MAX_RANGE = 100000
24
Armin Ronacher76c280b2008-05-04 12:31:48 +020025#: attributes of function objects that are considered unsafe.
26UNSAFE_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
30UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
31
Armin Ronacherc63243e2008-04-14 22:53:58 +020032
33def safe_range(*args):
34 """A range that can't generate ranges with a length of more than
Armin Ronacher7ceced52008-05-03 10:15:31 +020035 MAX_RANGE items.
36 """
Armin Ronacherc63243e2008-04-14 22:53:58 +020037 rng = xrange(*args)
38 if len(rng) > MAX_RANGE:
Armin Ronacher76c280b2008-05-04 12:31:48 +020039 raise OverflowError('range too big, maximum size for range is %d' %
40 MAX_RANGE)
Armin Ronacherc63243e2008-04-14 22:53:58 +020041 return rng
42
43
44def unsafe(f):
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +020045 """
46 Mark a function or method as unsafe::
47
48 @unsafe
49 def delete(self):
50 pass
51 """
Armin Ronacherc63243e2008-04-14 22:53:58 +020052 f.unsafe_callable = True
53 return f
54
55
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +020056def is_internal_attribute(obj, attr):
57 """Test if the attribute given is an internal python attribute. For
58 example this function returns `True` for the `func_code` attribute of
59 python objects. This is useful if the environment method
60 :meth:`~SandboxedEnvironment.is_safe_attribute` is overriden.
61
62 >>> from jinja2.sandbox import is_internal_attribute
63 >>> is_internal_attribute(lambda: None, "func_code")
64 True
65 >>> is_internal_attribute((lambda x:x).func_code, 'co_code')
66 True
67 >>> is_internal_attribute(str, "upper")
68 False
69 """
70 if isinstance(obj, FunctionType):
71 return attr in UNSAFE_FUNCTION_ATTRIBUTES
72 if isinstance(obj, MethodType):
73 return attr in UNSAFE_FUNCTION_ATTRIBUTES or \
74 attr in UNSAFE_METHOD_ATTRIBUTES
75 if isinstance(obj, type):
76 return attr == 'mro'
77 if isinstance(obj, (CodeType, TracebackType, FrameType)):
78 return True
79 if isinstance(obj, GeneratorType):
80 return attr == 'gi_frame'
81 return attr.startswith('__')
82
83
Armin Ronacherc63243e2008-04-14 22:53:58 +020084class SandboxedEnvironment(Environment):
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +020085 """The sandboxed environment. It works like the regular environment but
86 tells the compiler to generate sandboxed code. Additionally subclasses of
87 this environment may override the methods that tell the runtime what
88 attributes or functions are safe to access.
89
90 If the template tries to access insecure code a :exc:`SecurityError` is
91 raised. However also other exceptions may occour during the rendering so
92 the caller has to ensure that all exceptions are catched.
93 """
Armin Ronacherc63243e2008-04-14 22:53:58 +020094 sandboxed = True
95
96 def __init__(self, *args, **kwargs):
97 Environment.__init__(self, *args, **kwargs)
98 self.globals['range'] = safe_range
99
Armin Ronacher9a822052008-04-17 18:44:07 +0200100 def is_safe_attribute(self, obj, attr, value):
Armin Ronacherc63243e2008-04-14 22:53:58 +0200101 """The sandboxed environment will call this method to check if the
102 attribute of an object is safe to access. Per default all attributes
103 starting with an underscore are considered private as well as the
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +0200104 special attributes of internal python objects as returned by the
105 :func:`is_internal_attribute` function.
Armin Ronacherc63243e2008-04-14 22:53:58 +0200106 """
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +0200107 return not (attr.startswith('_') or is_internal_attribute(obj, attr))
Armin Ronacherc63243e2008-04-14 22:53:58 +0200108
109 def is_safe_callable(self, obj):
110 """Check if an object is safely callable. Per default a function is
111 considered safe unless the `unsafe_callable` attribute exists and is
Armin Ronacher7ceced52008-05-03 10:15:31 +0200112 True. Override this method to alter the behavior, but this won't
Armin Ronacherc63243e2008-04-14 22:53:58 +0200113 affect the `unsafe` decorator from this module.
114 """
Armin Ronacher7ceced52008-05-03 10:15:31 +0200115 return not (getattr(obj, 'unsafe_callable', False) or \
116 getattr(obj, 'alters_data', False))
Armin Ronacherc63243e2008-04-14 22:53:58 +0200117
Armin Ronacher9a822052008-04-17 18:44:07 +0200118 def subscribe(self, obj, argument):
Armin Ronacherc63243e2008-04-14 22:53:58 +0200119 """Subscribe an object from sandboxed code."""
Armin Ronacher9a822052008-04-17 18:44:07 +0200120 is_unsafe = False
Armin Ronacherc63243e2008-04-14 22:53:58 +0200121 try:
Armin Ronacher9a822052008-04-17 18:44:07 +0200122 value = getattr(obj, str(argument))
123 except (AttributeError, UnicodeError):
124 pass
125 else:
126 if self.is_safe_attribute(obj, argument, value):
127 return value
128 is_unsafe = True
129 try:
130 return obj[argument]
Armin Ronacherc63243e2008-04-14 22:53:58 +0200131 except (TypeError, LookupError):
Armin Ronacher9a822052008-04-17 18:44:07 +0200132 if is_unsafe:
133 return self.undefined('access to attribute %r of %r object is'
134 ' unsafe.' % (
135 argument,
136 obj.__class__.__name__
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +0200137 ), name=argument, exc=SecurityError)
Armin Ronacher9a822052008-04-17 18:44:07 +0200138 return self.undefined(obj=obj, name=argument)
Armin Ronacherc63243e2008-04-14 22:53:58 +0200139
140 def call(__self, __obj, *args, **kwargs):
141 """Call an object from sandboxed code."""
142 # the double prefixes are to avoid double keyword argument
143 # errors when proxying the call.
144 if not __self.is_safe_callable(__obj):
Armin Ronacher5cdc1ac2008-05-07 12:17:18 +0200145 raise SecurityError('%r is not safely callable' % (__obj,))
Armin Ronacherc63243e2008-04-14 22:53:58 +0200146 return __obj(*args, **kwargs)