a19da0
diff --git a/jinja2/nodes.py b/jinja2/nodes.py
a19da0
index c5697e6..9465943 100644
a19da0
--- a/jinja2/nodes.py
a19da0
+++ b/jinja2/nodes.py
a19da0
@@ -599,7 +599,7 @@ class Call(Expr):
a19da0
 
a19da0
     def as_const(self, eval_ctx=None):
a19da0
         eval_ctx = get_eval_context(self, eval_ctx)
a19da0
-        if eval_ctx.volatile:
a19da0
+        if eval_ctx.volatile or eval_ctx.environment.sandboxed:
a19da0
             raise Impossible()
a19da0
         obj = self.node.as_const(eval_ctx)
a19da0
 
a19da0
diff --git a/jinja2/sandbox.py b/jinja2/sandbox.py
a19da0
index da479c1..7e31a7a 100644
a19da0
--- a/jinja2/sandbox.py
a19da0
+++ b/jinja2/sandbox.py
a19da0
@@ -12,12 +12,19 @@
a19da0
     :copyright: (c) 2010 by the Jinja Team.
a19da0
     :license: BSD.
a19da0
 """
a19da0
+import types
a19da0
 import operator
a19da0
+from collections import Mapping
a19da0
 from jinja2.environment import Environment
a19da0
 from jinja2.exceptions import SecurityError
a19da0
 from jinja2._compat import string_types, function_type, method_type, \
a19da0
-     traceback_type, code_type, frame_type, generator_type, PY2
a19da0
+     traceback_type, code_type, frame_type, generator_type, text_type, PY2
a19da0
+from jinja2.utils import Markup
a19da0
 
a19da0
+has_format = False
a19da0
+if hasattr(text_type, 'format'):
a19da0
+    from string import Formatter
a19da0
+    has_format = True
a19da0
 
a19da0
 #: maximum number of items a range may produce
a19da0
 MAX_RANGE = 100000
a19da0
@@ -32,6 +39,12 @@ UNSAFE_METHOD_ATTRIBUTES = set(['im_class', 'im_func', 'im_self'])
a19da0
 #: unsafe generator attirbutes.
a19da0
 UNSAFE_GENERATOR_ATTRIBUTES = set(['gi_frame', 'gi_code'])
a19da0
 
a19da0
+#: unsafe attributes on coroutines
a19da0
+UNSAFE_COROUTINE_ATTRIBUTES = set(['cr_frame', 'cr_code'])
a19da0
+
a19da0
+#: unsafe attributes on async generators
a19da0
+UNSAFE_ASYNC_GENERATOR_ATTRIBUTES = set(['ag_code', 'ag_frame'])
a19da0
+
a19da0
 # On versions > python 2 the special attributes on functions are gone,
a19da0
 # but they remain on methods and generators for whatever reason.
a19da0
 if not PY2:
a19da0
@@ -92,6 +105,79 @@ _mutable_spec = (
a19da0
     ]))
a19da0
 )
a19da0
 
a19da0
+# Bundled EscapeFormatter class from markupsafe >= 0.21 which is used by
a19da0
+# jinja2 for fixing CVE-2016-10745
a19da0
+# Copyright 2010 Pallets
a19da0
+# BSD 3-Clause License
a19da0
+# https://github.com/pallets/markupsafe/blob/79ee6ce0ed93c6da73512f069d7db866d955df04/LICENSE.rst
a19da0
+if hasattr(text_type, "format"):
a19da0
+
a19da0
+    class EscapeFormatter(Formatter):
a19da0
+        def __init__(self, escape):
a19da0
+            self.escape = escape
a19da0
+
a19da0
+        def format_field(self, value, format_spec):
a19da0
+            if hasattr(value, "__html_format__"):
a19da0
+                rv = value.__html_format__(format_spec)
a19da0
+            elif hasattr(value, "__html__"):
a19da0
+                if format_spec:
a19da0
+                    raise ValueError(
a19da0
+                        "Format specifier {0} given, but {1} does not"
a19da0
+                        " define __html_format__. A class that defines"
a19da0
+                        " __html__ must define __html_format__ to work"
a19da0
+                        " with format specifiers.".format(format_spec, type(value))
a19da0
+                    )
a19da0
+                rv = value.__html__()
a19da0
+            else:
a19da0
+                # We need to make sure the format spec is unicode here as
a19da0
+                # otherwise the wrong callback methods are invoked.  For
a19da0
+                # instance a byte string there would invoke __str__ and
a19da0
+                # not __unicode__.
a19da0
+                rv = Formatter.format_field(self, value, text_type(format_spec))
a19da0
+            return text_type(self.escape(rv))
a19da0
+
a19da0
+class _MagicFormatMapping(Mapping):
a19da0
+    """This class implements a dummy wrapper to fix a bug in the Python
a19da0
+    standard library for string formatting.
a19da0
+
a19da0
+    See http://bugs.python.org/issue13598 for information about why
a19da0
+    this is necessary.
a19da0
+    """
a19da0
+
a19da0
+    def __init__(self, args, kwargs):
a19da0
+        self._args = args
a19da0
+        self._kwargs = kwargs
a19da0
+        self._last_index = 0
a19da0
+
a19da0
+    def __getitem__(self, key):
a19da0
+        if key == '':
a19da0
+            idx = self._last_index
a19da0
+            self._last_index += 1
a19da0
+            try:
a19da0
+                return self._args[idx]
a19da0
+            except LookupError:
a19da0
+                pass
a19da0
+            key = str(idx)
a19da0
+        return self._kwargs[key]
a19da0
+
a19da0
+    def __iter__(self):
a19da0
+        return iter(self._kwargs)
a19da0
+
a19da0
+    def __len__(self):
a19da0
+        return len(self._kwargs)
a19da0
+
a19da0
+
a19da0
+def inspect_format_method(callable):
a19da0
+    if not has_format:
a19da0
+        return None
a19da0
+    if not isinstance(callable, (types.MethodType,
a19da0
+                                 types.BuiltinMethodType)) or \
a19da0
+       callable.__name__ != 'format':
a19da0
+        return None
a19da0
+    obj = callable.__self__
a19da0
+    if isinstance(obj, string_types):
a19da0
+        return obj
a19da0
+
a19da0
 
a19da0
 def safe_range(*args):
a19da0
     """A range that can't generate ranges with a length of more than
a19da0
@@ -146,6 +232,12 @@ def is_internal_attribute(obj, attr):
a19da0
     elif isinstance(obj, generator_type):
a19da0
         if attr in UNSAFE_GENERATOR_ATTRIBUTES:
a19da0
             return True
a19da0
+    elif hasattr(types, 'CoroutineType') and isinstance(obj, types.CoroutineType):
a19da0
+        if attr in UNSAFE_COROUTINE_ATTRIBUTES:
a19da0
+            return True
a19da0
+    elif hasattr(types, 'AsyncGeneratorType') and isinstance(obj, types.AsyncGeneratorType):
a19da0
+        if attri in UNSAFE_ASYNC_GENERATOR_ATTRIBUTES:
a19da0
+            return True
a19da0
     return attr.startswith('__')
a19da0
 
a19da0
 
a19da0
@@ -184,8 +276,8 @@ class SandboxedEnvironment(Environment):
a19da0
     attributes or functions are safe to access.
a19da0
 
a19da0
     If the template tries to access insecure code a :exc:`SecurityError` is
a19da0
-    raised.  However also other exceptions may occour during the rendering so
a19da0
-    the caller has to ensure that all exceptions are catched.
a19da0
+    raised.  However also other exceptions may occur during the rendering so
a19da0
+    the caller has to ensure that all exceptions are caught.
a19da0
     """
a19da0
     sandboxed = True
a19da0
 
a19da0
@@ -347,8 +439,24 @@ class SandboxedEnvironment(Environment):
a19da0
             obj.__class__.__name__
a19da0
         ), name=attribute, obj=obj, exc=SecurityError)
a19da0
 
a19da0
+    def format_string(self, s, args, kwargs):
a19da0
+        """If a format call is detected, then this is routed through this
a19da0
+        method so that our safety sandbox can be used for it.
a19da0
+        """
a19da0
+        if isinstance(s, Markup):
a19da0
+            formatter = SandboxedEscapeFormatter(self, s.escape)
a19da0
+        else:
a19da0
+            formatter = SandboxedFormatter(self)
a19da0
+        kwargs = _MagicFormatMapping(args, kwargs)
a19da0
+        rv = formatter.vformat(s, args, kwargs)
a19da0
+        return type(s)(rv)
a19da0
+
a19da0
     def call(__self, __context, __obj, *args, **kwargs):
a19da0
         """Call an object from sandboxed code."""
a19da0
+        fmt = inspect_format_method(__obj)
a19da0
+        if fmt is not None:
a19da0
+            return __self.format_string(fmt, args, kwargs)
a19da0
+
a19da0
         # the double prefixes are to avoid double keyword argument
a19da0
         # errors when proxying the call.
a19da0
         if not __self.is_safe_callable(__obj):
a19da0
@@ -366,3 +474,37 @@ class ImmutableSandboxedEnvironment(SandboxedEnvironment):
a19da0
         if not SandboxedEnvironment.is_safe_attribute(self, obj, attr, value):
a19da0
             return False
a19da0
         return not modifies_known_mutable(obj, attr)
a19da0
+
a19da0
+
a19da0
+if has_format:
a19da0
+    # This really is not a public API apparenlty.
a19da0
+    try:
a19da0
+        from _string import formatter_field_name_split
a19da0
+    except ImportError:
a19da0
+        def formatter_field_name_split(field_name):
a19da0
+            return field_name._formatter_field_name_split()
a19da0
+
a19da0
+    class SandboxedFormatterMixin(object):
a19da0
+
a19da0
+        def __init__(self, env):
a19da0
+            self._env = env
a19da0
+
a19da0
+        def get_field(self, field_name, args, kwargs):
a19da0
+            first, rest = formatter_field_name_split(field_name)
a19da0
+            obj = self.get_value(first, args, kwargs)
a19da0
+            for is_attr, i in rest:
a19da0
+                if is_attr:
a19da0
+                    obj = self._env.getattr(obj, i)
a19da0
+                else:
a19da0
+                    obj = self._env.getitem(obj, i)
a19da0
+            return obj, first
a19da0
+
a19da0
+    class SandboxedFormatter(SandboxedFormatterMixin, Formatter):
a19da0
+        def __init__(self, env):
a19da0
+            SandboxedFormatterMixin.__init__(self, env)
a19da0
+            Formatter.__init__(self)
a19da0
+
a19da0
+    class SandboxedEscapeFormatter(SandboxedFormatterMixin, EscapeFormatter):
a19da0
+        def __init__(self, env, escape):
a19da0
+            SandboxedFormatterMixin.__init__(self, env)
a19da0
+            EscapeFormatter.__init__(self, escape)