Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

turn on autoescape for flask.templating.render_template_string #1515

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ Version 1.0
- Don't leak exception info of already catched exceptions to context teardown
handlers (pull request ``#1393``).
- Allow custom Jinja environment subclasses (pull request ``#1422``).
- Turn on autoescape for ``flask.templating.render_template_string`` by default
(pull request ``#1515``).

Version 0.10.2
--------------
Expand Down
5 changes: 4 additions & 1 deletion docs/templating.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ Jinja Setup
Unless customized, Jinja2 is configured by Flask as follows:

- autoescaping is enabled for all templates ending in ``.html``,
``.htm``, ``.xml`` as well as ``.xhtml``
``.htm``, ``.xml`` as well as ``.xhtml`` when using
:func:`~flask.templating.render_template`.
- autoescaping is enabled for all strings when using
:func:`~flask.templating.render_template_string`.
- a template has the ability to opt in/out autoescaping with the
``{% autoescape %}`` tag.
- Flask inserts a couple of global functions and helpers into the
Expand Down
4 changes: 4 additions & 0 deletions docs/upgrading.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ Now the inheritance hierarchy takes precedence and handlers for more
specific exception classes are executed instead of more general ones.
See :ref:`error-handlers` for specifics.

The :func:`~flask.templating.render_template_string` function has changed to
autoescape template variables by default. This better matches the behavior
of :func:`~flask.templating.render_template`.

.. note::

There used to be a logic error allowing you to register handlers
Expand Down
20 changes: 10 additions & 10 deletions flask/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,12 +724,12 @@ def init_jinja_globals(self):

def select_jinja_autoescape(self, filename):
"""Returns ``True`` if autoescaping should be active for the given
template name.
template name. If no template name is given, returns `True`.

.. versionadded:: 0.5
"""
if filename is None:
return False
return True
return filename.endswith(('.html', '.htm', '.xml', '.xhtml'))

def update_template_context(self, context):
Expand Down Expand Up @@ -1090,14 +1090,14 @@ def _get_exc_class_and_code(exc_class_or_code):
exc_class = default_exceptions[exc_class_or_code]
else:
exc_class = exc_class_or_code

assert issubclass(exc_class, Exception)

if issubclass(exc_class, HTTPException):
return exc_class, exc_class.code
else:
return exc_class, None

@setupmethod
def errorhandler(self, code_or_exception):
"""A decorator that is used to register a function give a given
Expand Down Expand Up @@ -1166,9 +1166,9 @@ def _register_error_handler(self, key, code_or_exception, f):
'Tried to register a handler for an exception instance {0!r}. '
'Handlers can only be registered for exception classes or HTTP error codes.'
.format(code_or_exception))

exc_class, code = self._get_exc_class_and_code(code_or_exception)

handlers = self.error_handler_spec.setdefault(key, {}).setdefault(code, {})
handlers[exc_class] = f

Expand Down Expand Up @@ -1460,7 +1460,7 @@ def handle_http_exception(self, e):
# those unchanged as errors
if e.code is None:
return e

This comment was marked as off-topic.

This comment was marked as off-topic.

This comment was marked as off-topic.

handler = self._find_error_handler(e)
if handler is None:
return e
Expand Down Expand Up @@ -1503,12 +1503,12 @@ def handle_user_exception(self, e):
# wants the traceback preserved in handle_http_exception. Of course
# we cannot prevent users from trashing it themselves in a custom
# trap_http_exception method so that's their fault then.

if isinstance(e, HTTPException) and not self.trap_http_exception(e):
return self.handle_http_exception(e)

handler = self._find_error_handler(e)

if handler is None:
reraise(exc_type, exc_value, tb)
return handler(e)
Expand Down
2 changes: 1 addition & 1 deletion flask/templating.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ def render_template(template_name_or_list, **context):

def render_template_string(source, **context):
"""Renders a template from the given template source string
with the given context.
with the given context. Template variables will be autoescaped.

:param source: the source code of the template to be
rendered
Expand Down
8 changes: 8 additions & 0 deletions tests/templates/non_escaping_template.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{{ text }}
{{ html }}
{% autoescape false %}{{ text }}
{{ html }}{% endautoescape %}
{% autoescape true %}{{ text }}
{{ html }}{% endautoescape %}
{{ text }}
{{ html }}
21 changes: 20 additions & 1 deletion tests/test_templating.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,29 @@ def index():
]

def test_no_escaping():
text = '<p>Hello World!'
app = flask.Flask(__name__)
@app.route('/')
def index():
return flask.render_template('non_escaping_template.txt', text=text,
html=flask.Markup(text))
lines = app.test_client().get('/').data.splitlines()
assert lines == [
b'<p>Hello World!',
b'<p>Hello World!',
b'<p>Hello World!',
b'<p>Hello World!',
b'&lt;p&gt;Hello World!',
b'<p>Hello World!',
b'<p>Hello World!',
b'<p>Hello World!'
]

def test_escaping_without_template_filename():
app = flask.Flask(__name__)
with app.test_request_context():
assert flask.render_template_string(
'{{ foo }}', foo='<test>') == '<test>'
'{{ foo }}', foo='<test>') == '&lt;test&gt;'
assert flask.render_template('mail.txt', foo='<test>') == \
'<test> Mail'

Expand Down