10. HTML Escaping

When generating HTML from templates, there’s always a risk that a variable will include characters that affect the resulting HTML. There are two approaches:

  1. manually escaping each variable; or
  2. automatically escaping everything by default.

Jinja supports both. What is used depends on the application configuration. The default configuration is no automatic escaping; for various reasons:

  • Escaping everything except for safe values will also mean that Jinja is escaping variables known to not include HTML (e.g. numbers, booleans) which can be a huge performance hit.
  • The information about the safety of a variable is very fragile. It could happen that by coercing safe and unsafe values, the return value is double-escaped HTML.

10.1. Working with Manual Escaping

If manual escaping is enabled, it’s your responsibility to escape variables if needed. What to escape? If you have a variable that may include any of the following chars (>, <, &, or ") you SHOULD escape it unless the variable contains well-formed and trusted HTML. Escaping works by piping the variable through the |e filter:

{{ user.username|e }}

10.2. Working with Automatic Escaping

When automatic escaping is enabled, everything is escaped by default except for values explicitly marked as safe. Variables and expressions can be marked as safe either in:

  1. the context dictionary by the application with MarkupSafe.Markup, or
  2. the template, with the |safe filter

The main problem with this approach is that Python itself doesn’t have the concept of tainted values; so whether a value is safe or unsafe can get lost.

If a value is not marked safe, auto-escaping will take place; which means that you could end up with double-escaped contents. Double-escaping is easy to avoid, however: just rely on the tools Jinja2 provides and don’t use builtin Python constructs such as str.format or the string modulo operator (%).

Jinja2 functions (macros, super, self.BLOCKNAME) always return template data that is marked as safe.

String literals in templates with automatic escaping are considered unsafe because native Python strings (str, unicode, basestring) are not MarkupSafe.Markup strings with an __html__ attribute.