[svn] improved jinja sandbox
authorArmin Ronacher <armin.ronacher@active-4.com>
Tue, 27 Mar 2007 20:00:21 +0000 (22:00 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Tue, 27 Mar 2007 20:00:21 +0000 (22:00 +0200)
--HG--
branch : trunk

jinja/environment.py
jinja/exceptions.py
jinja/translators/python.py
jinja/utils.py

index aaec7991c9c4497dd2dc490f92b3328d8e7b346f..f807576af7d2f40c897103093f2087010d8b7e34 100644 (file)
@@ -13,8 +13,8 @@ from jinja.lexer import Lexer
 from jinja.parser import Parser
 from jinja.loaders import LoaderWrapper
 from jinja.datastructure import Undefined, Markup, Context, FakeTranslator
-from jinja.utils import escape, collect_translations
-from jinja.exceptions import FilterNotFound, TestNotFound
+from jinja.utils import escape, collect_translations, get_attribute
+from jinja.exceptions import FilterNotFound, TestNotFound, SecurityException
 from jinja.defaults import DEFAULT_FILTERS, DEFAULT_TESTS, DEFAULT_NAMESPACE
 
 
@@ -164,14 +164,10 @@ class Environment(object):
         try:
             return obj[name]
         except (TypeError, KeyError, IndexError):
-            if name[:2] == name[-2:] == '__':
-                return Undefined
-            if not hasattr(obj, name):
-                return Undefined
-            r = getattr(obj, 'jinja_allowed_attributes', None)
-            if r is not None and name not in r:
-                return Undefined
-            return getattr(obj, name)
+            try:
+                return get_attribute(obj, name)
+            except (AttributeError, SecurityException):
+                pass
         return Undefined
 
     def call_function(self, f, context, args, kwargs, dyn_args, dyn_kwargs):
index e8e6c47a3a93fb61e135e3824cdaa62cf3719b15..1994467bf46bca6808db4ddd0c695185b03705e3 100644 (file)
@@ -17,8 +17,6 @@ class TemplateError(RuntimeError):
 class SecurityException(TemplateError):
     """
     Raise if the template designer tried to do something dangerous.
-
-    Not used any more. exists for backwards compatibility.
     """
 
 
index 407960b7e23e6fd812c41cabd54ac61a87b7e56a..96082100a4deb540694fdf1756e9f75d57a4be4d 100644 (file)
@@ -240,9 +240,7 @@ class PythonTranslator(Translator):
 
     def translate(self):
         self.reset()
-        rv = self.handle_node(self.node)
-        print rv
-        return rv
+        return self.handle_node(self.node)
 
     # -- jinja nodes
 
index 34a0e8409013e9780141b3295f6daa65ed1fdaa7..e68932001de5a2226f2ea8231b0c15375957100e 100644 (file)
@@ -19,6 +19,7 @@ from types import MethodType, FunctionType
 from compiler.ast import CallFunc, Name, Const
 from jinja.nodes import Trans
 from jinja.datastructure import Context, TemplateData
+from jinja.exceptions import SecurityException
 
 try:
     from collections import deque
@@ -105,6 +106,24 @@ def from_string(source):
     return _from_string_env.from_string(source)
 
 
+def get_attribute(obj, name):
+    """
+    Return the attribute from name. Raise either `AttributeError`
+    or `SecurityException` if something goes wrong.
+    """
+    if not isinstance(name, basestring):
+        raise AttributeError(name)
+    if name[:2] == name[-2:] == '__' or name[:2] == '::':
+        raise SecurityException('not allowed to access internal attributes')
+    if (obj.__class__ is FunctionType and name.startswith('func_') or
+        obj.__class__ is MethodType and name.startswith('im_')):
+        raise SecurityException('not allowed to access function attributes')
+    r = getattr(obj, 'jinja_allowed_attributes', None)
+    if r is not None and name not in r:
+        raise SecurityException('not allowed attribute accessed')
+    return getattr(obj, name)
+
+
 def debug_context(env, context):
     """
     Use this function in templates to get a printed context.