File tree Expand file tree Collapse file tree 3 files changed +45
-2
lines changed Expand file tree Collapse file tree 3 files changed +45
-2
lines changed Original file line number Diff line number Diff line change @@ -485,7 +485,9 @@ def set_headers(self, filelike):
485
485
disposition = 'attachment' if self .as_attachment else 'inline'
486
486
try :
487
487
filename .encode ('ascii' )
488
- file_expr = 'filename="{}"' .format (filename )
488
+ file_expr = 'filename="{}"' .format (
489
+ filename .replace ('\\ ' , '\\ \\ ' ).replace ('"' , r'\"' )
490
+ )
489
491
except UnicodeEncodeError :
490
492
file_expr = "filename*=utf-8''{}" .format (quote (filename ))
491
493
self .headers ['Content-Disposition' ] = '{}; {}' .format (disposition , file_expr )
Original file line number Diff line number Diff line change @@ -6,4 +6,10 @@ Django 3.2.15 release notes
6
6
7
7
Django 3.2.15 fixes a security issue with severity "high" in 3.2.14.
8
8
9
- ...
9
+ CVE-2022-36359: Potential reflected file download vulnerability in ``FileResponse``
10
+ ===================================================================================
11
+
12
+ An application may have been vulnerable to a reflected file download (RFD)
13
+ attack that sets the Content-Disposition header of a
14
+ :class:`~django.http.FileResponse` when the ``filename`` was derived from
15
+ user-supplied input. The ``filename`` is now escaped to avoid this possibility.
Original file line number Diff line number Diff line change @@ -89,3 +89,38 @@ def test_unicode_attachment(self):
89
89
response .headers ['Content-Disposition' ],
90
90
"attachment; filename*=utf-8''%E7%A5%9D%E6%82%A8%E5%B9%B3%E5%AE%89.odt"
91
91
)
92
+
93
+ def test_content_disposition_escaping (self ):
94
+ # fmt: off
95
+ tests = [
96
+ (
97
+ 'multi-part-one";\" dummy".txt' ,
98
+ r"multi-part-one\";\" dummy\".txt"
99
+ ),
100
+ ]
101
+ # fmt: on
102
+ # Non-escape sequence backslashes are path segments on Windows, and are
103
+ # eliminated by an os.path.basename() check in FileResponse.
104
+ if sys .platform != "win32" :
105
+ # fmt: off
106
+ tests += [
107
+ (
108
+ 'multi-part-one\\ ";\" dummy".txt' ,
109
+ r"multi-part-one\\\";\" dummy\".txt"
110
+ ),
111
+ (
112
+ 'multi-part-one\\ ";\\ \" dummy".txt' ,
113
+ r"multi-part-one\\\";\\\" dummy\".txt"
114
+ )
115
+ ]
116
+ # fmt: on
117
+ for filename , escaped in tests :
118
+ with self .subTest (filename = filename , escaped = escaped ):
119
+ response = FileResponse (
120
+ io .BytesIO (b"binary content" ), filename = filename , as_attachment = True
121
+ )
122
+ response .close ()
123
+ self .assertEqual (
124
+ response .headers ["Content-Disposition" ],
125
+ f'attachment; filename="{ escaped } "' ,
126
+ )
You can’t perform that action at this time.
0 commit comments