python.flask.security.audit.xss.make-response-with-unknown-content.make-response-with-unknown-content
semgrep
Author
1,993
Download Count*
License
Be careful with flask.make_response()
. If this response is rendered onto a webpage, this could create a cross-site scripting (XSS) vulnerability. flask.make_response()
will not autoescape HTML. If you are rendering HTML, write your HTML in a template file and use flask.render_template()
which will take care of escaping. If you are returning data from an API, consider using flask.jsonify()
.
Run Locally
Run in CI
Defintion
rules:
- id: make-response-with-unknown-content
patterns:
- pattern: flask.make_response(...)
- pattern-not-inside: flask.make_response()
- pattern-not-inside: flask.make_response("...", ...)
- pattern-not-inside: 'flask.make_response({"...": "..."}, ...)'
- pattern-not-inside: flask.make_response(flask.redirect(...), ...)
- pattern-not-inside: flask.make_response(flask.render_template(...), ...)
- pattern-not-inside: flask.make_response(flask.jsonify(...), ...)
- pattern-not-inside: flask.make_response(json.dumps(...), ...)
- pattern-not-inside: |
$X = flask.render_template(...)
...
flask.make_response($X, ...)
- pattern-not-inside: |
$X = flask.jsonify(...)
...
flask.make_response($X, ...)
- pattern-not-inside: |
$X = json.dumps(...)
...
flask.make_response($X, ...)
message: Be careful with `flask.make_response()`. If this response is rendered
onto a webpage, this could create a cross-site scripting (XSS)
vulnerability. `flask.make_response()` will not autoescape HTML. If you
are rendering HTML, write your HTML in a template file and use
`flask.render_template()` which will take care of escaping. If you are
returning data from an API, consider using `flask.jsonify()`.
severity: WARNING
metadata:
cwe:
- "CWE-79: Improper Neutralization of Input During Web Page Generation
('Cross-site Scripting')"
references:
- https://github.com/python-security/pyt//blob/093a077bcf12d1f58ddeb2d73ddc096623985fb0/examples/vulnerable_code/XSS_assign_to_other_var.py#L11
- https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.make_response
- https://flask.palletsprojects.com/en/1.1.x/api/#response-objects
category: security
technology:
- flask
owasp:
- A07:2017 - Cross-Site Scripting (XSS)
- A03:2021 - Injection
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- audit
likelihood: LOW
impact: MEDIUM
confidence: LOW
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
vulnerability_class:
- Cross-Site-Scripting (XSS)
languages:
- python
Examples
make-response-with-unknown-content.py
# cf. https://github.com/python-security/pyt//blob/093a077bcf12d1f58ddeb2d73ddc096623985fb0/examples/vulnerable_code/
import json
import flask
from flask import Flask, request, make_response
from somewhere import fxn
app = Flask(__name__)
@app.route('/XSS_param', methods =['GET'])
def XSS1():
param = request.args.get('param', 'not set')
other_var = param
html = open('templates/XSS_param.html').read()
# ruleid: make-response-with-unknown-content
resp = make_response(html.replace('{{ param }}', other_var))
return resp
# cf. https://github.com/alshapton/kb-api/commit/bd649de1da9e4020f9273fff183a74edfadc0b07
def switch(target:str, config: Dict[str, str]):
if does_base_exist(target,config):
switch_base(target,config)
# ruleid: make-response-with-unknown-content
resp = (make_response(({'Switched': "The current knowledge base is now : '" + target + "'"}), 200))
else:
# ruleid: make-response-with-unknown-content
resp = (make_response(({'Error': "The knowledge base '" + target + "' does not exist"}), 404))
resp.mimetype = MIME_TYPE['json']
return resp
# Lots of little unit tests:
# ok: make-response-with-unknown-content
make_response("hello")
# ok: make-response-with-unknown-content
make_response()
# ok: make-response-with-unknown-content
make_response({"hello": "world"}, 200)
# ok: make-response-with-unknown-content
make_response(flask.render_template("index.html"))
# ok: make-response-with-unknown-content
make_response(flask.jsonify({"hello": "world"}))
# ok: make-response-with-unknown-content
make_response(json.dumps({"hello": "world"}))
# ok: make-response-with-unknown-content
make_response(flask.redirect(unk))
t = flask.render_template("index.html")
# ok: make-response-with-unknown-content
make_response(t)
unk = fxn()
# ruleid: make-response-with-unknown-content
make_response(unk)
# ruleid: make-response-with-unknown-content
make_response("<div>" + unk + "</div>")
# ruleid: make-response-with-unknown-content
make_response({"hello": unk})
t = flask.render_template("index.html")
html = t.replace("{{ name }}", unk)
# ruleid: make-response-with-unknown-content
make_response(html)
html = """
<div>
%s
</div>
""" % unk
# ruleid: make-response-with-unknown-content
make_response(html)
if __name__ == '__main__':
app.run(debug=True)
Short Link: https://sg.run/3x3p