summaryrefslogtreecommitdiff
path: root/tests/responses
diff options
context:
space:
mode:
authorCarlton Gibson <carlton.gibson@noumenal.es>2022-07-20 12:14:45 +0200
committerCarlton Gibson <carlton.gibson@noumenal.es>2022-08-03 08:46:31 +0200
commitbd062445cffd3f6cc6dcd20d13e2abed818fa173 (patch)
treee3a150ec5176cb0adff541b1a78cb200ef87428e /tests/responses
parent9062c23de80e999009cbe4100d83e90dd0463612 (diff)
downloaddjango-bd062445cffd3f6cc6dcd20d13e2abed818fa173.tar.gz
Fixed CVE-2022-36359 -- Escaped filename in Content-Disposition header.
Thanks to Motoyasu Saburi for the report.
Diffstat (limited to 'tests/responses')
-rw-r--r--tests/responses/test_fileresponse.py35
1 files changed, 35 insertions, 0 deletions
diff --git a/tests/responses/test_fileresponse.py b/tests/responses/test_fileresponse.py
index af90b1170d..952fe4dd7c 100644
--- a/tests/responses/test_fileresponse.py
+++ b/tests/responses/test_fileresponse.py
@@ -143,6 +143,41 @@ class FileResponseTests(SimpleTestCase):
'%s; filename="%s"' % (header_disposition, header_filename),
)
+ def test_content_disposition_escaping(self):
+ # fmt: off
+ tests = [
+ (
+ 'multi-part-one";\" dummy".txt',
+ r"multi-part-one\";\" dummy\".txt"
+ ),
+ ]
+ # fmt: on
+ # Non-escape sequence backslashes are path segments on Windows, and are
+ # eliminated by an os.path.basename() check in FileResponse.
+ if sys.platform != "win32":
+ # fmt: off
+ tests += [
+ (
+ 'multi-part-one\\";\" dummy".txt',
+ r"multi-part-one\\\";\" dummy\".txt"
+ ),
+ (
+ 'multi-part-one\\";\\\" dummy".txt',
+ r"multi-part-one\\\";\\\" dummy\".txt"
+ )
+ ]
+ # fmt: on
+ for filename, escaped in tests:
+ with self.subTest(filename=filename, escaped=escaped):
+ response = FileResponse(
+ io.BytesIO(b"binary content"), filename=filename, as_attachment=True
+ )
+ response.close()
+ self.assertEqual(
+ response.headers["Content-Disposition"],
+ f'attachment; filename="{escaped}"',
+ )
+
def test_content_disposition_buffer(self):
response = FileResponse(io.BytesIO(b"binary content"))
self.assertFalse(response.has_header("Content-Disposition"))