Jinja2

environmentxml

Jinja is a text-based template engine for Python, written by Armin Ronacher. It looks like the Django template language but allows Python-like expressions, including calling methods with arguments on the objects you pass in. It is Flask’s default template engine, and it templates any text, not just HTML: config files, SQL, source code.

Tags, filters, tests and globals are all customisable on the Environment.

Two defaults worth knowing

Both of these are commonly assumed to be on. They are not.

Autoescaping is off in a bare Environment. Flask turns it on for .html and .xml templates; plain Jinja does not.

from jinja2 import Environment, select_autoescape

Environment().autoescape                      # False
Environment().from_string("{{ x }}").render(x="<b>hi</b>")   # '<b>hi</b>', not escaped

# opt in, either always
Environment(autoescape=True)
# or per file extension, the way Flask does it
Environment(autoescape=select_autoescape(["html", "xml"]))

Templates are not sandboxed by default either. A plain Environment gives a template full attribute access on the objects it receives, which is enough to walk back up to arbitrary Python:

from jinja2 import Environment
from jinja2.sandbox import SandboxedEnvironment

payload = "{{ ''.__class__.__mro__[1].__subclasses__()|length }}"

Environment().from_string(payload).render()           # 303, it runs
SandboxedEnvironment().from_string(payload).render()  # jinja2.exceptions.SecurityError

So: never render a template whose source comes from a user without jinja2.sandbox.SandboxedEnvironment, and even then read its documented limits first. Passing untrusted data into a trusted template is fine, that is the normal case.

Verified on Jinja2 3.1.6.

References

Related