Secure Filenames
Never trust a user-provided filename.
Attackers can try things like:
../../etc/passwd- special characters that break file systems
Flask/Werkzeug provides secure_filename().
flowchart TD
A["file.filename from the request"] --> B{"used as-is?"}
B -->|yes| C["os.path.join(UPLOAD_DIR, '../../../etc/passwd')"]
C --> D["the write escapes the upload directory"]
B -->|no| E["secure_filename(name)"]
E --> F["path separators and .. removed"]
F --> G["'etc_passwd' -- a flat, safe name"]
G --> H{"is the result empty?"}
H -->|yes| I["reject the upload -- there is no filename left"]
H -->|no| J["still check the extension and the size"]
J --> K["save under a name YOU control, e.g. a uuid"]
Example
Section titled “Example”import os
from werkzeug.utils import secure_filename
from flask import Flask, request
app = Flask(__name__)
UPLOAD_FOLDER = "uploads"
@app.route("/upload", methods=["POST"])
def upload():
file = request.files.get("photo")
if not file:
return "No file", 400
filename = secure_filename(file.filename)
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
save_path = os.path.join(UPLOAD_FOLDER, filename)
file.save(save_path)
return {"saved_as": filename}, 201Best practices for production
Section titled “Best practices for production”- Rename uploaded files (UUID) instead of using original name
- Store metadata in DB (who uploaded, when, original name)
- Set an upload size limit (
MAX_CONTENT_LENGTH) - Validate extensions and MIME type
- Consider storing files in object storage (S3) rather than the app server
pch.coffeeTagline
pch.coffeeCtapch.feedbackHeading
pch.feedbackSubheading