From e19cb50fb529bbe75cc4f1b68eeb0a3f631ad0d0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 8 Aug 2024 11:19:28 -0500 Subject: [PATCH] Do not follow symlinks for compressed file variants (#8652) CVE: CVE-2024-42367 Upstream-Status: Backport [https://github.com/aio-libs/aiohttp/commit/ce2e9758814527589b10759a20783fb03b98339f] Co-authored-by: Steve Repsher Signed-off-by: Jiaying Song --- CHANGES/8652.bugfix.rst | 1 + aiohttp/web_fileresponse.py | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 CHANGES/8652.bugfix.rst diff --git a/CHANGES/8652.bugfix.rst b/CHANGES/8652.bugfix.rst new file mode 100644 index 000000000..3a1003e50 --- /dev/null +++ b/CHANGES/8652.bugfix.rst @@ -0,0 +1 @@ +Fixed incorrectly following symlinks for compressed file variants -- by :user:`steverep`. diff --git a/aiohttp/web_fileresponse.py b/aiohttp/web_fileresponse.py index f41ed3fd0..35dbd41e1 100644 --- a/aiohttp/web_fileresponse.py +++ b/aiohttp/web_fileresponse.py @@ -127,6 +127,32 @@ class FileResponse(StreamResponse): self.content_length = 0 return await super().prepare(request) + def _get_file_path_stat_encoding( + self, accept_encoding: str + ) -> Tuple[pathlib.Path, os.stat_result, Optional[str]]: + """Return the file path, stat result, and encoding. + + If an uncompressed file is returned, the encoding is set to + :py:data:`None`. + + This method should be called from a thread executor + since it calls os.stat which may block. + """ + file_path = self._path + for file_extension, file_encoding in ENCODING_EXTENSIONS.items(): + if file_encoding not in accept_encoding: + continue + + compressed_path = file_path.with_suffix(file_path.suffix + file_extension) + with suppress(OSError): + # Do not follow symlinks and ignore any non-regular files. + st = compressed_path.lstat() + if S_ISREG(st.st_mode): + return compressed_path, st, file_encoding + + # Fallback to the uncompressed file + return file_path, file_path.stat(), None + async def prepare(self, request: "BaseRequest") -> Optional[AbstractStreamWriter]: filepath = self._path -- 2.34.1