From c2517faff335f683e1cbe55d9844910b3fb40670 Mon Sep 17 00:00:00 2001 From: Vishy Date: Mon, 6 Jul 2026 09:27:02 -0400 Subject: [PATCH] Fixed #37198 -- Fixed content_disposition_header() quoting of filenames ending with newlines. --- django/utils/http.py | 2 +- tests/utils_tests/test_http.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/django/utils/http.py b/django/utils/http.py index 3d5b7b6be6aa..a892221f0190 100644 --- a/django/utils/http.py +++ b/django/utils/http.py @@ -420,7 +420,7 @@ def content_disposition_header(as_attachment, filename): # characters from 0x21 to 0x7e, except 0x22 (`"`) and 0x5C (`\`) which # can still be expressed but must be escaped with their own `\`. # https://datatracker.ietf.org/doc/html/rfc9110#name-quoted-strings - quotable_characters = r"^[\t \x21-\x7e]*$" + quotable_characters = r"^[\t \x21-\x7e]*\Z" if is_ascii and re.match(quotable_characters, filename): file_expr = 'filename="{}"'.format( filename.replace("\\", "\\\\").replace('"', r"\"") diff --git a/tests/utils_tests/test_http.py b/tests/utils_tests/test_http.py index f7525885c2d2..82ce14721334 100644 --- a/tests/utils_tests/test_http.py +++ b/tests/utils_tests/test_http.py @@ -644,6 +644,8 @@ def test_basic(self): "attachment; filename*=utf-8''%22esp%C3%A9cimen%22%20filename", ), ((True, "some\nfile"), "attachment; filename*=utf-8''some%0Afile"), + ((True, "\n"), "attachment; filename*=utf-8''%0A"), + ((True, "example\n"), "attachment; filename*=utf-8''example%0A"), ) for (is_attachment, filename), expected in tests: