Skip to content

Knowledgebase

Uploading files safely in a Flask application

development

File upload handling must validate content, control storage paths and limit resource use. Saving the submitted filename directly can create a path or overwrite problem.

What you need before you begin

Decide which file types, maximum sizes and access levels the application actually needs. Identify persistent storage and the reverse proxy upload limit.

01 Upload files safely in a Flask application

  1. Validate the incoming request and enforce a deliberate MAX_CONTENT_LENGTH. Coordinate this with the proxy and server limits so the application can return a useful error.

  2. Generate a safe unique storage name. If retaining part of the submitted filename, use the framework-supported filename sanitization and handle empty or duplicate results.

  3. Validate the allowed content and extension according to the feature. Keep executable content out of web-executable directories and do not treat a claimed MIME type as proof of safety.

  4. Store private files outside direct public access and authorise downloads. Preserve uploaded files independently of application release replacement.

  5. Test oversized, disallowed and duplicate uploads with harmless files, then verify normal uploads and cleanup of abandoned temporary data.

02 Example: test upload limits and filename sanitisation separately

In the Flask application factory, set a deliberate total request-size limit. The filename example below demonstrates a separate check; neither size control nor a cleaned filename establishes that the uploaded content is safe to process.

Code or configuration example
from werkzeug.utils import secure_filename

app.config['MAX_CONTENT_LENGTH'] = 5 * 1024 * 1024
safe_name = secure_filename('../../proposal.pdf')
# safe_name is 'proposal.pdf'

Test a harmless 3 MiB PDF and a 6 MiB file. Multipart overhead also counts toward the request limit, so do not promise that a file exactly at the threshold will fit. Validate the permitted content, generate a unique storage name, handle an empty sanitised name, and save private documents outside direct public access.

Expected result: The permitted small document follows the normal authorised workflow and the oversized request receives a controlled rejection. A filename containing directory traversal cannot choose the storage path, and another user cannot download the private document.

Confirm the expected result

Confirm files cannot escape the intended directory, replace unrelated files or be downloaded by another user without permission. Check that rejected uploads do not fill temporary storage.

Troubleshoot unexpected results

A 413 response may be generated by the proxy before Flask handles the request. Check both layers instead of only increasing the Python setting.

A common question

Does secure_filename guarantee the uploaded file is safe?

It helps create a safer filename. It does not validate the file’s content, decide who may download it or prevent every processing vulnerability.

Sources and further reading

Was this answer helpful?

Need a little more help?

Our support team can help you find the next step.

Contact support