80 lines
2.6 KiB
Plaintext
80 lines
2.6 KiB
Plaintext
=== How to fix it in Jinja
|
|
|
|
The following code is vulnerable to cross-site scripting because auto-escaping of special HTML characters has been disabled.
|
|
The recommended way to fix this code is to move the HTML content to the template and to only inject the dynamic value. Therefore, it is not necessary to disable auto-escaping.
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,python,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
from flask import render_template
|
|
|
|
@app.route('/hello/<name>')
|
|
def hello(name=None):
|
|
hello = f"<h1>Hello { name }</h1>"
|
|
return render_template('hello.html', hello=hello)
|
|
----
|
|
|
|
[source,html,diff-id=2,diff-type=noncompliant]
|
|
----
|
|
<!doctype html>
|
|
{% autoescape false %}
|
|
{{ hello }} <!-- Noncompliant -->
|
|
{% endautoescape %}
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,python,diff-id=1,diff-type=compliant]
|
|
----
|
|
from flask import render_template
|
|
|
|
@app.route('/hello/<name>')
|
|
def hello(name=None):
|
|
return render_template('hello.html', name=name)
|
|
----
|
|
|
|
[source,html,diff-id=2,diff-type=compliant]
|
|
----
|
|
<!doctype html>
|
|
<h1>Hello {{ name }}</h1>
|
|
----
|
|
|
|
=== How does this work?
|
|
|
|
Template engines are used by web applications to build HTML content. Template files contain static HTML as well as template language instructions. These instructions allow, for example, to insert dynamic values (variables) in the document as the template is rendered.
|
|
Template engines can auto escape HTML special characters of variables in order to prevent XSS vulnerabilities.
|
|
|
|
In Flask applications, Jinja's auto-escaping feature is enabled by default. XSS vulnerabilities arise when an untrusted value is injected into the template and auto-escaping is disabled with the `++{% autoescape false %}++` or `++|safe++` filters.
|
|
This is often the case when a piece of dynamic HTML is generated from Python code and used in a template variable.
|
|
|
|
=== Pitfalls
|
|
|
|
==== Variables in script blocks
|
|
|
|
Although auto-escaping drastically decreases the chance of introducing cross-site scripting vulnerabilities, there are still specific cases where vulnerabilities can occur.
|
|
Injecting user-controlled values inside a ``++script++`` is dangerous. In such a case, the best practice is to add the value to an attribute.
|
|
Another option is to use the ``++tojson++`` filter to insert a data structure in the JavaScript code at render time.
|
|
|
|
===== Noncompliant code example
|
|
|
|
[source,html,diff-id=3,diff-type=noncompliant]
|
|
----
|
|
<!doctype html>
|
|
<script> var name = '{{ name }}';</script>
|
|
|
|
----
|
|
|
|
===== Compliant solution
|
|
|
|
[source,html,diff-id=3,diff-type=compliant]
|
|
----
|
|
<!doctype html>
|
|
<script> var name = {{ name | tojson }}</script>
|
|
----
|
|
|
|
=== Going the extra mile
|
|
|
|
include::../../common/extra-mile/csp.adoc[]
|
|
|