77 lines
2.4 KiB
Plaintext
77 lines
2.4 KiB
Plaintext
=== How to fix it in Flask
|
|
|
|
The following code is vulnerable to cross-site scripting because it returns an HTML response that contains user input.
|
|
|
|
If you do not intend to send HTML code to clients, the vulnerability can be fixed by specifying the type of data returned in the response.
|
|
For example, you can use the `jsonify` class to return JSON messages safely.
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,python,diff-id=1,diff-type=noncompliant]
|
|
----
|
|
from flask import make_response, request
|
|
import json
|
|
|
|
@app.route('/')
|
|
def index():
|
|
json = json.dumps({ "data": request.args.get("input") })
|
|
return make_response(json)
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,python,diff-id=1,diff-type=compliant]
|
|
----
|
|
from flask import jsonify, request
|
|
|
|
@app.route('/')
|
|
def index():
|
|
return jsonify({ "data": request.args.get("input") })
|
|
----
|
|
|
|
It is also possible to set the content-type manually with the `mimetype` parameter when calling the `make_response` function.
|
|
|
|
==== Noncompliant code example
|
|
|
|
[source,python,diff-id=2,diff-type=noncompliant]
|
|
----
|
|
from flask import make_response, request
|
|
|
|
@app.route('/')
|
|
def index():
|
|
return make_response(request.args.get("input"))
|
|
----
|
|
|
|
==== Compliant solution
|
|
|
|
[source,python,diff-id=2,diff-type=compliant]
|
|
----
|
|
from flask import make_response, request
|
|
|
|
@app.route('/')
|
|
def index():
|
|
return make_response(request.args.get("input"), mimetype="text/plain")
|
|
----
|
|
|
|
=== How does this work?
|
|
|
|
If the HTTP response is HTML code, it is highly recommended to use a template engine like https://jinja.palletsprojects.com/[Jinja] to generate it.
|
|
This template engine separates the view from the business logic and automatically encodes the output of variables, drastically reducing the risk of cross-site scripting vulnerabilities.
|
|
|
|
If you do not intend to send HTML code to clients, the vulnerability can be fixed by specifying the type of data returned in the response with the `content-type` HTTP header.
|
|
This HTTP header tells the client browser that the response does not contain HTML code and should not be parsed and interpreted as HTML.
|
|
Thus, the response is not vulnerable to reflected cross-site scripting.
|
|
|
|
For example, setting the content-type header to `text/plain` allows to safely reflect user input because browsers will not try to parse and execute the response.
|
|
|
|
=== Pitfalls
|
|
|
|
include::../../common/pitfalls/content-types.adoc[]
|
|
|
|
include::../../common/pitfalls/validation.adoc[]
|
|
|
|
=== Going the extra mile
|
|
|
|
include::../../common/extra-mile/csp.adoc[]
|
|
|