werkzeug icon indicating copy to clipboard operation
werkzeug copied to clipboard

send_file not inserting quote around filename

Open Timmy93 opened this issue 1 year ago • 2 comments

Overview

The function send_file does not insert quotes around the filename in the Content-Disposition header when the sent file does not have spaces. (See here for MDN docs) This causes browser (tested on Windows 11 - last version to date of Firefox and Chrome) to download the file with a blank name (respectively as undefined and undefined.txt)

To recap:

  • when test.pdf is sent with send_file the following Content-Disposition header is set to: attachment; filename=test.pdf -> Correct file is sent but with wrong filename
  • when test 1.pdf is sent with send_file the following Content-Disposition header is set to: attachment; filename="test 1.pdf" -> Works perfectly

Bug replication

Send a file without spaces in name:

from flask import Flask, send_file
app = Flask(__name__)

filepath = "test.pdf"
  if filepath:
    response = send_file(filepath, as_attachment=True)

Expected behavior:

  • when test.pdf is sent with send_file the following Content-Disposition header is set to: attachment; filename="test.pdf"
  • when test 1.pdf is sent with send_file the following Content-Disposition header is set to: attachment; filename="test 1.pdf"

Environment:

  • Python version: 3.11
  • Flask version: 3.0.0
  • Waitress: 2.1.2

Timmy93 avatar Jan 03 '24 23:01 Timmy93

The problem comes from these lines in quote_header_value: https://github.com/pallets/werkzeug/blob/d3dd65a27388fbd39d146caacf2563639ba622f0/src/werkzeug/http.py#L165-L169 This is used called from dump_options_header.

Do you know if this is true for all headers? If yes, it may be safer to default to allow_token = False. If not dump_options_header, _options_header_vkw and Headers.set should accept allow_token and pass it on.

Sympatron avatar Jan 25 '24 15:01 Sympatron

Honestly I don't know, manually adding the quotes using a regex fixed the problem, but I imagine it is not the correct solution, it's just a workaround.

Timmy93 avatar Jan 25 '24 16:01 Timmy93

I can't reproduce this issue. Sending a filename without spaces is downloaded with the correct filename by Firefox, Vivaldi (Chrome), and Safari. The Content-Disposition filename parameter can be either unquoted token chars, or a quoted string if needed, https://httpwg.org/specs/rfc6266.html#header.field.definition, both are valid.

davidism avatar May 05 '24 14:05 davidism

The problem can be reproduced if you set your language to italian and you try firefox to download any file like "test.pdf"

Timmy93 avatar May 08 '24 12:05 Timmy93