== How to fix it in Flask

=== Code examples

:code_impact: read

include::../../common/fix/code-rationale.adoc[]

==== Noncompliant code example

[source,python,diff-id=1,diff-type=noncompliant]
----
from flask import Flask, request, send_from_directory

app = Flask('example')

@app.route('/example')
def example():
    my_file = request.args['my_file']
    return send_file("static/%s" % my_file, as_attachment=True) # Noncompliant
----

==== Compliant solution

[source,python,diff-id=1,diff-type=compliant]
----
from flask import Flask, request, send_from_directory

app = Flask('example')

@app.route('/example')
def example():
    my_file = request.args['my_file']
    return send_from_directory('static', my_file)
----

=== How does this work?

:auto_canonicalization_function: send_from_directory

The universal method to prevent path injection is to validate paths created
from untrusted data. This can be done either manually or automatically,
depending on whether the library includes a data sanitization feature and the
required function.

Here, {auto_canonicalization_function} can be considered a secure-by-design API.

include::../../common/fix/function-based-validation.adoc[]

=== Pitfalls

:joining_docs: https://docs.python.org/3/library/os.path.html#os.path.join
:joining_func: os.path.join

include::../../common/pitfalls/path-joining.adoc[]

If you want to learn more about this pitfall, read https://blog.sonarsource.com/10-unknown-security-pitfalls-for-python/[our blog post about it].
