Hello {{ name }}!
{% endmacro %}' '{{ say_hello("") }}') escaped_out = 'Hello <blink>foo</blink>!
' assert t.render() == escaped_out assert text_type(t.module) == escaped_out assert escape(t.module) == escaped_out assert t.module.say_hello('') == escaped_out assert escape(t.module.say_hello('')) == escaped_out def test_attr_filter(self): env = SandboxedEnvironment() tmpl = env.from_string('{{ cls|attr("__subclasses__")() }}') self.assert_raises(SecurityError, tmpl.render, cls=int) def test_binary_operator_intercepting(self): def disable_op(left, right): raise TemplateRuntimeError('that operator so does not work') for expr, ctx, rv in ('1 + 2', {}, '3'), ('a + 2', {'a': 2}, '4'): env = SandboxedEnvironment() env.binop_table['+'] = disable_op t = env.from_string('{{ %s }}' % expr) assert t.render(ctx) == rv env.intercepted_binops = frozenset(['+']) t = env.from_string('{{ %s }}' % expr) try: t.render(ctx) except TemplateRuntimeError as e: pass else: self.fail('expected runtime error') def test_unary_operator_intercepting(self): def disable_op(arg): raise TemplateRuntimeError('that operator so does not work') for expr, ctx, rv in ('-1', {}, '-1'), ('-a', {'a': 2}, '-2'): env = SandboxedEnvironment() env.unop_table['-'] = disable_op t = env.from_string('{{ %s }}' % expr) assert t.render(ctx) == rv env.intercepted_unops = frozenset(['-']) t = env.from_string('{{ %s }}' % expr) try: t.render(ctx) except TemplateRuntimeError as e: pass else: self.fail('expected runtime error') def test_indirect_call(self): def run(value, arg): return value.run(arg) env = SandboxedEnvironment() env.filters["run"] = run # Use a simple approach: create an object with the format method # stored in 'run' attribute to test indirect access to str.format class Namespace(object): def __init__(self, **kwargs): for k, v in kwargs.items(): setattr(self, k, v) # The format string tries to access unsafe attributes (__class__) on the argument # Without the fix, this would bypass sandbox checks when format is called indirectly # With the fix, wrap_str_format intercepts the format method at access time # and the SandboxedFormatter blocks access to unsafe attributes env.globals['namespace'] = Namespace t = env.from_string( """{% set ns = namespace(run="{0.__class__.__subclasses__}".format) %} {{ ns | run(not_here) }} """ ) try: t.render() except SecurityError: pass else: self.fail('expected SecurityError') def suite(): suite = unittest.TestSuite() suite.addTest(unittest.makeSuite(SandboxTestCase)) return suite