Start learning free

LESSON 12 OF 20 · SECURITY: TOKENS AND SESSIONS

Check What Gets Uploaded

Practice

An upload route keeps a stranger's file on the shop's disk, and the starting POST /avatar trusts everything about it: its size, its kind and its name. So a visitor can send a huge file to fill the disk, upload a page.html holding a <script> that the shop then serves from its own address, or upload a file named ben.png that replaces Ben's avatar.

Three checks: app.config["MAX_CONTENT_LENGTH"] makes Flask refuse a bigger request with 413 by itself. A file's first bytes tell you its kind, whatever its name says: every PNG starts with \x89PNG\r\n\x1a\n and every JPEG with \xff\xd8\xff. And the shop picks the stored name itself with secrets.token_hex(16), so no visitor can choose it. Here is the bytes check on another route, for PDF manuals:

@app.post("/manuals")
def upload_manual():
    data = request.files["manual"].read()
    if not data.startswith(b"%PDF-"):
        return jsonify({"error": "not a PDF"}), 415
    name = secrets.token_hex(16) + ".pdf"

Any other kind of file gets 415 Unsupported Media Type. The requests and answers your code must give (<random> stands for 32 random hex characters):

POST /avatar  mug.png, PNG bytes        →  201  {"avatar": "<random>.png"}
GET /avatars/<random>.png               →  200  the PNG, 23 bytes
POST /avatar  me.jpg, JPEG bytes        →  201  {"avatar": "<random>.jpg"}
GET /avatars/<random>.jpg               →  200  the JPEG, 17 bytes
POST /avatar  page.html, a <script>     →  415  {"error": "page.html is not a PNG or JPEG image"}
GET /avatars/page.html                  →  404
POST /avatar  ben.png, PNG bytes        →  201  {"avatar": "<random>.png"}
GET /avatars/ben.png                    →  200  Ben's own avatar, 24 bytes
POST /avatar  big.png, over 1000 bytes  →  413

Your task: limit every request to 1000 bytes, save PNG and JPEG files under a random name ending in .png or .jpg, and answer any other file with status 415 and the error "<file name> is not a PNG or JPEG image", using the visitor's file name.


Assignment
Follow the Coding Tutorial to add the size limit, then the PNG, JPEG and other-file checks, to upload_avatar.


Hint
Bytes have startswith, just like text, and PNG_START and JPEG_START are already in your code. In the else, name is still the visitor's file name: only the PNG and JPEG branches replace it.


STEP 1 OF 7
    Ctrl + Enter to check