From 47a63e94944592abb81962a3bb660b2c60ce2e66 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 19 Mar 2026 16:52:26 +0000 Subject: [PATCH] Add decompression size limit to FITS gzip decoder gzip.decompress() was called without any size limit, allowing a crafted FITS file with a gzip bomb to cause unbounded memory allocation (OOM/DoS). Add a limit based on the expected image dimensions, similar to MAX_TEXT_CHUNK in the PNG decoder. Security: CWE-409 (Decompression Bomb) --- src/PIL/FitsImagePlugin.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/PIL/FitsImagePlugin.py b/src/PIL/FitsImagePlugin.py index a3fdc0efeec..dd0753986d4 100644 --- a/src/PIL/FitsImagePlugin.py +++ b/src/PIL/FitsImagePlugin.py @@ -128,7 +128,19 @@ class FitsGzipDecoder(ImageFile.PyDecoder): def decode(self, buffer: bytes | Image.SupportsArrayInterface) -> tuple[int, int]: assert self.fd is not None + + # Limit decompressed size to prevent decompression bomb DoS. + # Each pixel uses 4 bytes in the decompressed FITS BINTABLE format. + max_expected = self.state.xsize * self.state.ysize * 4 + max_decompressed = max(max_expected * 2, 1024 * 1024) # at least 1 MB + value = gzip.decompress(self.fd.read()) + if len(value) > max_decompressed: + msg = ( + f"FITS gzip decompressed data too large: " + f"{len(value)} bytes > {max_decompressed} bytes limit" + ) + raise ValueError(msg) rows = [] offset = 0