Opened 8 years ago
Last modified 6 days ago
#29602 assigned Bug
Jinja2's forceescape filter doesn't work on Django's safe strings
| Reported by: | no | Owned by: | Malachi Moody |
|---|---|---|---|
| Component: | Utilities | Version: | 2.0 |
| Severity: | Normal | Keywords: | |
| Cc: | Claude Paroz, Adam Zapletal | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | yes |
| Easy pickings: | no | UI/UX: | no |
Description
Not sure if this is a Django bug, jinja bug, or something I need to change for upgrading to Django 2.0, but since it was a Django commit causes it, I'm reporting here first.
I recently upgraded to Django 2.0, and shortly after had a complaint from one of our users about a page not displaying correctly. I tracked down the issue to a usage of Jinja's forceescape filter.
My usage is that we're displaying a preview of an email that will be sent out, and we do this by using the srcdoc attribute of iframe, so our code looks like:
<iframe srcdoc="{{ rendered_email | forceescape }}"></iframe>
The rendered_email variable is from a call to get_template(template_name).render(ctx), which returns a SafeString object. Which makes sense since a rendered template should be html. And since I want to display the email inside of html again, it needs to be re-escape, logically with the forceescape filter.
However, a change from this ticket/this commit causes the forceescape filter to fail on the jinja side. forcescape calls str() on it's argument to remove the "safety", then re-escapes it, however, the aforementioned commit allow SafeString to bypass the assumption that jinja makes when calling str().
Change History (6)
comment:1 by , 8 years ago
| Cc: | added |
|---|---|
| Summary: | Django 2.0 breaks interop with Jinja2 forceescape filter → Jinja2's forceescape filter doesn't work on Django's safe strings |
comment:2 by , 8 years ago
I agree, it is a bit late in the 2.0 life cycle to revert it; a note in the 2.0 change log would be very helpful for anyone else that's doing a late upgrade like I was (while upgrading I was checking everything in the release notes against our code base). I also assume it's too late in the 2.1 release cycle to fix in some way?
As a work around, I should either be able to use django's force_escape, or manually wrap the variable in Jinja's MarkUp() function so that it works with Jinja's forceescape.
comment:3 by , 8 years ago
| Component: | Template system → Utilities |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
Generally we don't document bugs in the release notes. :-)
It will be interesting to hear Claude's opinion on this issue.
comment:5 by , 6 weeks ago
| Cc: | added |
|---|
comment:6 by , 6 days ago
| Patch needs improvement: | set |
|---|
There is a little bit of admin to be done on the PR in order for it to be added to the review queue. The checklist is required, if you add it back the ticket can be reopened by one of the team.
jinja.filters.do_forceescape() uses markupsafe.escape(). Since
str(SafeText)now returns theSafeText, thehasattr(s, '__html__')check inescape()returns True and no escaping happens.I think it's a legitimate issue as the behavior is certainly unexpected (
SafeTextwith the Django template language'sforce_escapefilter works as you would expect), however, I'm not sure what the best way forward is as it's a bit late in the Django 2.0 lifecycle to revert the original change.