[Django] #33631: Blocktranslate asvar escapes variables, but stores the result as str instance, leading to double escaping

24 views
Skip to first unread message

Django

unread,
Apr 9, 2022, 7:21:38 PM4/9/22
to django-...@googlegroups.com
#33631: Blocktranslate asvar escapes variables, but stores the result as str
instance, leading to double escaping
-------------------------------------+-------------------------------------
Reporter: Richard | Owner: nobody
Ebeling |
Type: Bug | Status: new
Component: | Version: 4.0
Uncategorized | Keywords: blocktranslate
Severity: Normal | asvar escape
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
In the docs, this snippet is given as an example usage of `blocktranslate`
with the `asvar` argument (here:
[https://docs.djangoproject.com/en/4.0/topics/i18n/translation
/#blocktranslate-template-tag]:
{{{
{% blocktranslate asvar the_title %}The title is {{ title }}.{%
endblocktranslate %}
<title>{{ the_title }}</title>
<meta name="description" content="{{ the_title }}">
}}}

However, this template is buggy when `title` is a string, which I'd argue
is a common use case.

`title` will be escaped when formatting the content of the
`blocktranslate` block, but the "was escaped" information is discarded,
and `the_title` will be a `str` instance with escaped content.
When later using the `the_title` variable, it will be conditionally
escaped. Since it is a `str`, it will be escaped, so control characters
are escaped again, breaking their display on the final page.

Minimal example to reproduce (can be put in any view):
{{{
from django.template import Template, Context
template_content = """
{% blocktranslate asvar the_title %}The title is {{ title }}.{%
endblocktranslate %}
<title>{{ the_title }}</title>
<meta name="description" content="{{ the_title }}">
"""
rendered = Template(template_content).render(Context({"title": "<>&
Title"}))
assert "&amp;lt;" not in rendered, "> was escaped two times"
}}}

I'd argue that `blocktranslate` should:
* Either assign a `SafeString` instance to prevent future escaping
* or not escape the variables used within the translation, and store them
marked as unsafe (= as `str` instance)

--
Ticket URL: <https://code.djangoproject.com/ticket/33631>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Apr 13, 2022, 5:35:54 AM4/13/22
to django-...@googlegroups.com
#33631: Blocktranslate asvar escapes variables, but stores the result as str
instance, leading to double escaping
-------------------------------------+-------------------------------------
Reporter: Richard Ebeling | Owner: nobody
Type: Bug | Status: closed
Component: Uncategorized | Version: 4.0
Severity: Normal | Resolution: wontfix
Keywords: blocktranslate | Triage Stage:
asvar escape | Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Carlton Gibson):

* status: new => closed
* resolution: => wontfix


Comment:

Hi Richard, thanks for the report.

So this would be the way forward:

> ... assign a SafeString instance to prevent future escaping

But it's not at all clear how feasible it would be to correctly mark the
returned string as safe. Individual variables are run via
`render_value_in_context()` which escapes them assuming `autoescape` is
enabled, but then the final output is constructed after that, so it's not
clear we can reliably mark it safe.

**Rather** if, in your example, you know `the_title` is safe, declare it
as so: `{{ the_title|safe }}`. The following test case passes:

{{{
diff --git a/tests/template_tests/syntax_tests/i18n/test_blocktranslate.py
b/tests/template_tests/syntax_tests/i18n/test_blocktranslate.py
index 4a162362c6..967a7c1829 100644
--- a/tests/template_tests/syntax_tests/i18n/test_blocktranslate.py
+++ b/tests/template_tests/syntax_tests/i18n/test_blocktranslate.py
@@ -388,6 +388,23 @@ class I18nBlockTransTagTests(SimpleTestCase):
output = self.engine.render_to_string("i18n39")
self.assertEqual(output, ">Seite nicht gefunden<")

+ @setup(
+ {
+ "issue33631": (
+ """
+ {% load i18n %}
+ {% blocktranslate asvar the_title %}The title is


{{title}}.{% endblocktranslate %}

+ < title > {{the_title|safe}} < / title >
+ < meta name="description" content="{{ the_title|safe }}"
>
+ """
+ )
+ }
+ )
+ def test_issue33631(self):
+ with translation.override("en"):
+ output = self.engine.render_to_string("issue33631", {"title":
"<>& Title"})
+ self.assertNotIn("&amp;lt;", output)
+
@setup(
{
}}}

... and it avoids trying to resolve the difficulty above.

As such, I'm going to say `wontfix` here initially, and ask that you
follow-up on the [https://forum.djangoproject.com/c/internals/i18n/14
Internationalization Topics section of the Django Forum] to get a wider
audience if you'd like to discuss it further.

Thanks.

--
Ticket URL: <https://code.djangoproject.com/ticket/33631#comment:1>

Django

unread,
Apr 19, 2022, 10:05:56 AM4/19/22
to django-...@googlegroups.com
#33631: Blocktranslate asvar escapes variables, but stores the result as str
instance, leading to double escaping
-------------------------------------+-------------------------------------
Reporter: Richard Ebeling | Owner: nobody
Type: Bug | Status: new

Component: Uncategorized | Version: 4.0
Severity: Normal | Resolution:
Keywords: blocktranslate | Triage Stage: Accepted
asvar escape |

Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Carlton Gibson):

* status: closed => new
* resolution: wontfix =>
* stage: Unreviewed => Accepted


Comment:

Reopening to assess a patch [https://forum.djangoproject.com/t
/blocktranslate-asvar-escapes-without-marking-safe-re-ticket-33631/13146
based on forum discussion].

--
Ticket URL: <https://code.djangoproject.com/ticket/33631#comment:2>

Django

unread,
May 26, 2022, 1:51:05 AM5/26/22
to django-...@googlegroups.com
#33631: Blocktranslate asvar escapes variables, but stores the result as str
instance, leading to double escaping
-------------------------------------+-------------------------------------
Reporter: Richard Ebeling | Owner: Cheng
| Yuan
Type: Bug | Status: assigned

Component: Uncategorized | Version: 4.0
Severity: Normal | Resolution:
Keywords: blocktranslate | Triage Stage: Accepted
asvar escape |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Cheng Yuan):

* owner: nobody => Cheng Yuan
* status: new => assigned


--
Ticket URL: <https://code.djangoproject.com/ticket/33631#comment:3>

Django

unread,
May 29, 2022, 12:15:22 AM5/29/22
to django-...@googlegroups.com
#33631: Blocktranslate asvar escapes variables, but stores the result as str
instance, leading to double escaping
-------------------------------------+-------------------------------------
Reporter: Richard Ebeling | Owner: Cheng
| Yuan
Type: Bug | Status: assigned
Component: Uncategorized | Version: 4.0
Severity: Normal | Resolution:
Keywords: blocktranslate | Triage Stage: Accepted
asvar escape |
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Cheng Yuan):

* has_patch: 0 => 1


Comment:

PR
https://github.com/django/django/pull/15742

--
Ticket URL: <https://code.djangoproject.com/ticket/33631#comment:4>

Django

unread,
Jul 13, 2022, 2:50:45 AM7/13/22
to django-...@googlegroups.com
#33631: Blocktranslate asvar escapes variables, but stores the result as str
instance, leading to double escaping
-------------------------------------+-------------------------------------
Reporter: Richard Ebeling | Owner: Cheng
| Yuan
Type: Bug | Status: assigned
Component: Uncategorized | Version: 4.0
Severity: Normal | Resolution:
Keywords: blocktranslate | Triage Stage: Accepted
asvar escape |
Has patch: 1 | Needs documentation: 1

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

* needs_docs: 0 => 1


--
Ticket URL: <https://code.djangoproject.com/ticket/33631#comment:5>

Django

unread,
Jul 14, 2022, 5:14:18 AM7/14/22
to django-...@googlegroups.com
#33631: Blocktranslate asvar escapes variables, but stores the result as str
instance, leading to double escaping
-------------------------------------+-------------------------------------
Reporter: Richard Ebeling | Owner: Cheng
| Yuan
Type: Bug | Status: assigned
Component: Uncategorized | Version: 4.0
Severity: Normal | Resolution:
Keywords: blocktranslate | Triage Stage: Ready for
asvar escape | checkin
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

* needs_docs: 1 => 0
* stage: Accepted => Ready for checkin


--
Ticket URL: <https://code.djangoproject.com/ticket/33631#comment:6>

Django

unread,
Jul 14, 2022, 5:53:35 AM7/14/22
to django-...@googlegroups.com
#33631: Blocktranslate asvar escapes variables, but stores the result as str
instance, leading to double escaping
-------------------------------------+-------------------------------------
Reporter: Richard Ebeling | Owner: Cheng
| Yuan
Type: Bug | Status: closed
Component: Uncategorized | Version: 4.0
Severity: Normal | Resolution: fixed

Keywords: blocktranslate | Triage Stage: Ready for
asvar escape | checkin
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak <felisiak.mariusz@…>):

* status: assigned => closed
* resolution: => fixed


Comment:

In [changeset:"d4c5d2b52c897ccc07f04482d3f42f976a79223c" d4c5d2b5]:
{{{
#!CommitTicketReference repository=""
revision="d4c5d2b52c897ccc07f04482d3f42f976a79223c"
Fixed #33631 -- Marked {% blocktranslate asvar %} result as HTML safe.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/33631#comment:7>

Reply all
Reply to author
Forward
0 new messages