Skip to content

Commit

Permalink
Apply correct HTML escaping to include_block tag output
Browse files Browse the repository at this point in the history
  • Loading branch information
gasman committed Jun 17, 2021
1 parent 904b548 commit e24f10c
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 2 deletions.
10 changes: 8 additions & 2 deletions wagtail/core/templatetags/wagtailcore_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.template.defaulttags import token_kwargs
from django.template.loader import render_to_string
from django.utils.encoding import force_str
from django.utils.html import conditional_escape

from wagtail import VERSION, __version__
from wagtail.core.models import Page, Site
Expand Down Expand Up @@ -130,9 +131,14 @@ def render(self, context):
for var_name, var_value in self.extra_context.items():
new_context[var_name] = var_value.resolve(context)

return value.render_as_block(context=new_context)
output = value.render_as_block(context=new_context)
else:
return force_str(value)
output = value

if context.autoescape:
return conditional_escape(output)
else:
return force_str(output)


@register.tag
Expand Down
48 changes: 48 additions & 0 deletions wagtail/core/tests/test_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3986,6 +3986,54 @@ def test_include_block_tag_with_only_flag(self):
})
self.assertIn('<body><h1 class="important">bonjour</h1></body>', result)

def test_include_block_html_escaping(self):
"""
Output of include_block should be escaped as per Django autoescaping rules
"""
block = blocks.CharBlock()
bound_block = block.bind(block.to_python('some <em>evil</em> HTML'))

result = render_to_string('tests/blocks/include_block_test.html', {
'test_block': bound_block,
})
self.assertIn('<body>some &lt;em&gt;evil&lt;/em&gt; HTML</body>', result)

# {% autoescape off %} should be respected
result = render_to_string('tests/blocks/include_block_autoescape_off_test.html', {
'test_block': bound_block,
})
self.assertIn('<body>some <em>evil</em> HTML</body>', result)

# The same escaping should be applied when passed a plain value rather than a BoundBlock -
# a typical situation where this would occur would be rendering an item of a StructBlock,
# e.g. {% include_block person_block.first_name %} as opposed to
# {% include_block person_block.bound_blocks.first_name %}
result = render_to_string('tests/blocks/include_block_test.html', {
'test_block': 'some <em>evil</em> HTML',
})
self.assertIn('<body>some &lt;em&gt;evil&lt;/em&gt; HTML</body>', result)

result = render_to_string('tests/blocks/include_block_autoescape_off_test.html', {
'test_block': 'some <em>evil</em> HTML',
})
self.assertIn('<body>some <em>evil</em> HTML</body>', result)

# Blocks that explicitly return 'safe HTML'-marked values (such as RawHTMLBlock) should
# continue to produce unescaped output
block = blocks.RawHTMLBlock()
bound_block = block.bind(block.to_python('some <em>evil</em> HTML'))

result = render_to_string('tests/blocks/include_block_test.html', {
'test_block': bound_block,
})
self.assertIn('<body>some <em>evil</em> HTML</body>', result)

# likewise when applied to a plain 'safe HTML' value rather than a BoundBlock
result = render_to_string('tests/blocks/include_block_test.html', {
'test_block': mark_safe('some <em>evil</em> HTML'),
})
self.assertIn('<body>some <em>evil</em> HTML</body>', result)


class BlockUsingGetTemplateMethod(blocks.Block):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% load wagtailcore_tags %}

<body>{% autoescape off %}{% include_block test_block %}{% endautoescape %}</body>

0 comments on commit e24f10c

Please sign in to comment.