From: Armin Ronacher Date: Tue, 27 Mar 2007 20:00:21 +0000 (+0200) Subject: [svn] improved jinja sandbox X-Git-Tag: 2.0rc1~391 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=c2fde02415d22381205de3ee91179c51f4d5fcb9;p=jinja2.git [svn] improved jinja sandbox --HG-- branch : trunk --- diff --git a/jinja/environment.py b/jinja/environment.py index aaec799..f807576 100644 --- a/jinja/environment.py +++ b/jinja/environment.py @@ -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): diff --git a/jinja/exceptions.py b/jinja/exceptions.py index e8e6c47..1994467 100644 --- a/jinja/exceptions.py +++ b/jinja/exceptions.py @@ -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. """ diff --git a/jinja/translators/python.py b/jinja/translators/python.py index 407960b..9608210 100644 --- a/jinja/translators/python.py +++ b/jinja/translators/python.py @@ -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 diff --git a/jinja/utils.py b/jinja/utils.py index 34a0e84..e689320 100644 --- a/jinja/utils.py +++ b/jinja/utils.py @@ -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.