From 68bd8f8f63a6b9d12998fa89b057372c2a1e90ae Mon Sep 17 00:00:00 2001 From: shamoon <4887959+shamoon@users.noreply.github.com> Date: Mon, 3 Aug 2026 07:31:04 -0700 Subject: [PATCH] Fix: Content-Disposition filename normalization (#13514) --- src/documents/tests/test_api_documents.py | 25 +++++++++++++++++++++++ src/documents/views.py | 2 ++ 2 files changed, 27 insertions(+) diff --git a/src/documents/tests/test_api_documents.py b/src/documents/tests/test_api_documents.py index edd9f3df3..1009ad311 100644 --- a/src/documents/tests/test_api_documents.py +++ b/src/documents/tests/test_api_documents.py @@ -472,6 +472,31 @@ class TestDocumentApi(DirectoriesMixin, ConsumeTaskMixin, APITestCase): self.assertIn("my_document.pdf", response["Content-Disposition"]) response.close() + @override_settings(FILENAME_FORMAT="") + def test_download_filename_normalization_does_not_inject_parameters( + self, + ) -> None: + doc = Document.objects.create( + title="file.doc\uff02; x=\uff02\uff3c", + created=date(2020, 1, 2), + filename="source.pdf", + mime_type="application/pdf", + ) + Path(doc.source_path).write_bytes(b"This is a test") + + response = self.client.get( + f"/api/documents/{doc.pk}/download/?original=true", + ) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual( + response["Content-Disposition"], + "attachment; " + 'filename="2020-01-02 file.doc_; x=__.pdf"; ' + "filename*=utf-8''2020-01-02%20file.doc%EF%BC%82%3B%20x%3D%EF%BC%82%EF%BC%BC.pdf", + ) + response.close() + def test_document_actions_not_existing_file(self) -> None: doc = Document.objects.create( title="none", diff --git a/src/documents/views.py b/src/documents/views.py index 3d6018d43..405913f95 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -4708,6 +4708,8 @@ def serve_file( "ignore", ) .decode("ascii") + .replace("\\", "_") + .replace('"', "_") ) filename_encoded = quote(filename) content_disposition = (