Skip to content

← Public intelligence

PyPI package

pillow

Open actionable advisories and recorded vendor fixes. This public package view has no inventory attached and cannot establish whether your deployment is affected. A vendor fix never resolves your finding; verify your installed version and the source guidance.

Open advisories

117 actionable advisories, newest first. Withdrawn advisories and news are excluded. Coverage is partial.

  1. Critical, CVSS 9.2PyPIAmendedPublished

    Pillow: Heap buffer overflow in FlashPix (FPX) JPEG decoding leads to code execution

    CVE-2026-112398 · GHSA-5x8w-8jj5-q52h

    Affected
    • PyPI pillow < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    Credits Researcher: Alex Bouffard (mixbo@pebwalker.com) Summary A heap buffer overflow in Pillow's FlashPix (FPX) JPEG-tile decoder lets an attacker achieve arbitrary code execution by getting an application to open a single crafted file with `Image.open()`. The file is recognized by content (the OLE2 magic), not by extension, so any service that opens or thumbnails untrusted uploads with the optional `olefile` dependency installed is reachable with no user interaction. In the PoC below, opening one crafted file executes an attacker-chosen command on stock Pillow 12.2.0 (x86_64 Ubuntu 24.04, glibc 2.39). Details `FpxImagePlugin` decodes FlashPix (FPX) files, which are OLE2/CFBF compound documents. `Image.open()` auto-detects them from the OLE2 magic `D0CF11E0...` whenever the optional `olefile` package is installed (Pillow's documented dependency for FPX/MIC support), regardless of the file's extension. For a JPEG-compressed subimage (`compression == 2`), the plugin…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)osv.dev (4)Source checked Evidence →
  2. Medium, CVSS 6.3PyPIAmendedPublished

    Pillow: Arrow export leaks stale heap memory when PILLOW_ALIGNMENT > 1

    CVE-2026-114501 · GHSA-654x-cwwv-5j9c

    Affected
    • PyPI pillow >= 11.2.1, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    When `PILLOW_ALIGNMENT` is set above 1, exporting an image to Arrow returns uninitialized heap memory mixed in with the pixel data. That memory can include pixels from images the process freed earlier. Details With an alignment above 1, the default allocator pads each row up to `aligned_linesize` and starts the first row at an aligned offset into the block. It then exports `im->blocks[0].ptr` as `xsize * ysize` tightly packed pixels, so exported data includes the padding bytes, and can include a few bytes from before the first row. Tested vulnerable on 11.2.1, 12.3.0, 4c1ed27a5. PoC Whether things leak may depend on allocator configuration. This does show a leak on my Mac. ```python import os os.environ["PILLOW_ALIGNMENT"] = "64" from PIL import Image Image A: 64 px wide, so its rows fill the whole aligned stride a = Image.new("L", (64, 40),…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)osv.dev (4)Source checked Evidence →
  3. High, CVSS 8.1PyPIAmendedPublished

    Pillow: Bundled libopenjp2 2.5.4 in all wheels since 11.1.0 carries OSV-2025-219 heap-buffer-overflow write reachable from Image.open().load()

    GHSA-78g4-xqwv-q3g8

    Affected
    • PyPI pillow >= 11.1.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    Every Pillow wheel from 11.1.0 onward bundles a libopenjp2 containing a heap-buffer-overflow write that is fixed upstream on master but has never appeared in an OpenJPEG release. See https://osv.dev/vulnerability/OSV-2025-219 Because the wheel bundles its own copy, a patched host OS does not help. It is reachable from Image.open(fp); im.load() with default settings. I am reporting it here rather than only upstream because Pillow is where the vulnerable binary actually reaches users. Note the inversion that makes this easy to miss: OpenJPEG 2.5.2 and earlier are safe. The bug was introduced in 954c6e3c (2024-06-25), so keeping the dependency current is what creates the exposure. Details Affected wheels From .github/dependencies.json (openjpeg) at each tag: | Pillow | bundled OpenJPEG | status | |---|---|---| | 10.4.0 | 2.5.2 | safe | | 11.0.0 | 2.5.2 | safe | | 11.1.0, 11.2.1, 11.3.0 | 2.5.3 | affected | | 12.0.0 … 12.3.0 | 2.5.4 | affected | Confirmed on an installed wheel:…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)Source checked Evidence →
  4. High, CVSS 7.7PyPIAmendedPublished

    Pillow: Heap buffer overflow writing JPEG comment after ICC profile fills buffer

    CVE-2026-96778 · GHSA-g7cr-3p24-7wf7

    Affected
    • PyPI pillow >= 9.4.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    ``` ============================================================================ Heap buffer overflow writing JPEG comment after ICC profile fills buffer Location: src/libImaging/JpegEncode.c:330 in ImagingJpegEncode() Commit: a707c6b21c313880d0771e54965d142dd42358b6 ============================================================================ ``` A heap buffer overflow in Pillow's JPEG encoder lets anyone who can supply an image write up to 64 KB of bytes they choose, followed by the rest of the compressed image, past the end of a 64 KB heap buffer. The target is any application that re-saves the image as JPEG while keeping its colour profile. The reliable result is that the Python process is killed outright rather than raising an exception. Because the overwritten memory sits directly in front of function pointers that the encoder calls next, this could allow code execution, though the attached reproducer demonstrates only the crash. The bug is in `ImagingJpegEncode()` in…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)Source checked Evidence →
  5. High, CVSS 7.1PyPIAmendedPublished

    Pillow: Heap over-read in WMF/EMF rendering via 16-bit dimension truncation (Windows builds)

    CVE-2026-96644 · GHSA-9v9v-9qvf-h2hj

    Affected
    • PyPI pillow < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    On Windows builds, Pillow stores EMF and WMF image dimensions without a range check and passes them to the native `drawwmf` handler. That code sizes its allocation from dimensions truncated into 16-bit header fields but copies the result using the full 32-bit dimensions. A crafted metafile that is wide and short passes the decompression-bomb pixel check yet causes a heap over-read. Details The EMF branch computes the size straight from signed 32-bit header fields and stores it with no positivity or range check: - `src/PIL/WmfImagePlugin.py:121-129` reads the bounding box; `:148` stores it; the size reaches the native handler through `src/PIL/WmfImagePlugin.py:56`. In the native handler the DIB header fields `bcWidth` and `bcHeight` are 16-bit and truncate the allocation, while the copy length uses the untruncated ints: - `src/display.c:793-794` assign the 16-bit fields - `src/display.c:800` sizes the allocation from them - `src/display.c:827` copies `height * ((width…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)osv.dev (4)Source checked Evidence →
  6. High, CVSS 7.1PyPIAmendedPublished

    Pillow: PNG eXIf chunk makes EXIF parsing run in quadratic time

    CVE-2026-96643 · GHSA-g4qv-2jxx-769h

    Affected
    • PyPI pillow >= 11.0.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    A PNG file with a large eXIf chunk full of repeated 6-byte markers makes Pillow's EXIF parser take seconds of CPU instead of milliseconds. The cost grows with the square of the chunk size, so a normal small-photo-sized file is enough to cause real delay. Details `Exif.load()` in `src/PIL/Image.py` strips a marker from the start of the EXIF data like this: ```python while data and data.startswith(b"Exif\x00\x00"): data = data[6:] ``` Each pass makes a new copy of the remaining data. A real camera writes this marker once, so this is not normally a problem. `chunk_eXIf()` in `src/PIL/PngImagePlugin.py` puts the raw PNG eXIf chunk straight into `info["exif"]` with no size limit and no check of its content. PNG text chunks (tEXt, zTXt, iTXt) are capped with `MAX_TEXT_CHUNK` and `MAX_TEXT_MEMORY`. The eXIf chunk has no such cap. If the eXIf chunk is filled with repeated `Exif\x00\x00` markers instead of real EXIF data, the strip loop runs once per marker, copying a large…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)osv.dev (4)Source checked Evidence →
  7. High, CVSS 7.1PyPIAmendedPublished

    Pillow: TarIO negative size field causes infinite CPU-spin loop

    CVE-2026-96642 · GHSA-3j72-p6qg-6xp7

    Affected
    • PyPI pillow < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    `TarIO.init` does not check that a tar header's size field is positive. A crafted header with a negative size makes it seek backward onto itself. This causes an infinite loop that uses 100% CPU and never returns. Details `TarIO.init` reads 512-byte tar headers one at a time, looking for a member with a given name. For each header it reads the size field and skips ahead to the next header: ```python size = int(s[124:135], 8) ... self.fh.seek((size + 511) & (~511), io.SEEK_CUR) ``` There is no check that size is zero or more. A tar header can set this field to a negative octal value. For size = -512, the seek offset comes out to exactly -512, which cancels the 512 bytes the loop had just read. The file position goes right back to where this loop step started. The loop only stops on end of file or when a header name starts with a null byte. Neither happens, since the same header keeps showing up again. The loop never ends on its own. Steps to reproduce This…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)osv.dev (4)Source checked Evidence →
  8. Medium, CVSS 6.5PyPIAmendedPublished

    Pillow: Reachable undefined behavior in native integer operations, potentially leading to denial of service or logic integrity compromise

    CVE-2026-96641 · GHSA-4rm8-3hmm-39fg

    Affected
    • PyPI pillow < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    Affected Object and Source Package: Pillow 12.3.0 Source: PyPI sdist pillow-12.3.0.tar.gz SHA-256: 3b8182a766685eaa002637e28b4ec8d6b18819a0c71f579bf0dbaa5830297cce Sink: src/_imaging.c:2809:15, xsize += dx Details The code in Pillow 12.3.0 is: ```c for (xsize = 0; *text; text++) { int dx = self->glyphs[*text].dx; if (dx > 0 && xsize > INT_MAX - dx) { PyErr_SetString(PyExc_OverflowError, "Width too large"); return -1; } xsize += dx; } ``` The PILfont glyph advance is parsed from a signed 16-bit field, so the valid range for `dx` is `[-32768, 32767]`. The existing check only proves: `dx > 0 => xsize xsize >= INT_MIN - dx` Taking `dx = -32768` and repeating it 65,537 times, the mathematical sum is `-2,147,516,416`, which is less than `INT_MIN = -2,147,483,648`. On the 65,537th addition, the operation `-2147483648 + -32768` is performed, resulting in C signed overflow undefined behavior. PoC ```python """Minimal public-API reproducer for the Pillow 12.3.0…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)osv.dev (4)Source checked Evidence →
  9. High, CVSS 8.2PyPIAmendedPublished

    Pillow PDF append accepts malformed shared page-tree DAG causing resource exhaustion

    CVE-2026-96640 · GHSA-mrfp-p49p-3hf2

    Affected
    • PyPI pillow >= 5.1.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    Pillow's documented PDF append path can spend disproportionate CPU time on a compact malformed PDF page tree. An attacker who can supply an existing PDF to an application that appends an image with `Image.save(..., format="PDF", append=True)` can provide a malformed `/Pages` tree where each level repeats the same child `/Pages` reference in `/Kids`. Pillow treats the graph as a tree and expands each repeated reference in `PdfParser.linearize_page_tree()` without tracking visited or duplicate indirect references. In the bounded proof below, a `1410`-byte PDF expands to `8192` page references from one distinct page object and takes about `9.6` seconds through the append path. A comparable linear control with the same depth stays at one page reference and completes in about `0.02` seconds. This is in scope for Pillow's security policy because it is reproducible in `main`, affects the latest public release tested (`12.3.0`), and is not just an unexpected Python exception. The…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)Source checked Evidence →
  10. Critical, CVSS 9.8PyPIAmendedPublished

    Pillow multi-frame loaders can reuse stale native image storage after mode transitions

    CVE-2026-96639 · GHSA-v9pv-5gc8-w2m6

    Affected
    • PyPI pillow >= 11.0.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    Pillow multi-frame image loaders can retain native `ImagingCore` storage allocated for one frame while changing the Python-side image `mode` and decoder tiles for a later frame. If frame 0 allocates storage for a narrow mode such as `L`, and a later frame of the same dimensions switches to a wider mode such as `RGB` or `CMYK`, Pillow may decode wider pixels into the stale narrow native buffer. This causes native out-of-bounds writes and process crashes. In the MPO/JPEG path, I also demonstrated command execution in matching Python/Pillow runtime profiles through Pillow's documented `ImageSequence.Iterator` + `frame.load()` path. Details The root cause appears to be that `ImageFile.load_prepare()` only reallocates native storage when `_im is None`. It does not verify that the retained native `ImagingCore` storage still matches `self.mode` and `self.size`. Several multi-frame `seek()` / `_open()` paths can update `self._mode` and decoder tiles for a later frame without…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)osv.dev (4)Source checked Evidence →
  11. Medium, CVSS 6.5PyPIAmendedPublished

    Pillow: BMP RLE decoder memory-amplification DoS via unbounded delta escape / absolute mode

    CVE-2026-96638 · GHSA-24rc-8hj2-v98c

    Affected
    • PyPI pillow >= 9.1.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    BmpRleDecoder can be forced to allocate gigabytes of memory from a kilobyte-sized crafted BMP file via unbounded growth in the delta escape and absolute mode branches. Affected versions All versions up to and including current HEAD (v13.0.0.dev0, commit e7a7ea84) Root cause BmpRleDecoder.decode() (BmpImagePlugin.py:327-395) builds a Python bytearray `data` with dest_length = xsize*ysize, looping `while len(data) up to ~255*xsize bytes in ONE iteration. - absolute mode (line 385): data += bytes_read (up to 255). Because a single delta can push len(data) to ~256 * (row size), a tiny RLE stream combined with a large-but-legal xsize (xsize*ysize just under MAX_IMAGE_PIXELS, ~89M) yields a multi-GB `data` bytearray (then copied again by bytes(data) and set_as_raw). No heap OOB (bytearray/set_as_raw are bounds-safe), but a severe memory-amplification DoS: the attacker file stays tiny. Reproduction Python 3.13, Pillow HEAD e7a7ea84 Attached: pillow_poc_bmp_rle_dos.py A…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)Source checked Evidence →
  12. High, CVSS 7.1PyPIAmendedPublished

    Pillow: Decompression bomb check bypass in SpiderImagePlugin.seek() leads to unbounded allocation DoS

    CVE-2026-96637 · GHSA-g842-9rc4-69pw

    Affected
    • PyPI pillow < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    SpiderImagePlugin's seek() bypasses the decompression bomb check, allowing a tiny ( DecompressionBombWarning fires correctly. - BYPASS: Image.open(stack, frame0=1x1) passes; im.seek(1) sets size (100,100) with NO DecompressionBombWarning/Error -> the check is bypassed. Real-world impact: a large frame-1 nsam/nrow (e.g. 40000x40000) causes im.load() to allocate ~6.4 GB (mode F) with the bomb check fully bypassed, from a file under 1 KB. Suggested fix Call Image._decompression_bomb_check(self.size) at the end of SpiderImageFile._open() (or in seek() after _open()), mirroring GifImagePlugin / TiffImagePlugin. Optionally validate nsam/nrow are positive and sane in _open(). Credit: Yazan Balawneh - CyStack Security Team pillow_poc_spider_bomb.py

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)osv.dev (4)Source checked Evidence →
  13. Medium, CVSS 6.5PyPIAmendedPublished

    Pillow: Decompression-bomb protection bypass via multi-frame seek() in MPO and DCX (MpoImageFile.seek / DcxImageFile.seek)

    CVE-2026-96636 · GHSA-p8hx-v2p6-rp84

    Affected
    • PyPI pillow < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    Pillow's decompression-bomb protection (`Image._decompression_bomb_check`, gated by `Image.MAX_IMAGE_PIXELS`) is enforced only on the first frame, inside `Image.open()`. For multi-frame formats, `seek()` re-parses the target frame's header and resets `self._size`. `GifImagePlugin` and `TiffImagePlugin` re-run the bomb check on `seek()`, but `MpoImageFile.seek()` and `DcxImageFile.seek()` do not. A crafted MPO or DCX whose first frame is tiny (passing the check) but whose later frame declares enormous dimensions therefore bypasses the protection: loading that frame decodes an over-limit image and commits large amounts of memory — a denial of service (memory exhaustion / OOM). Same class as the recently assigned CVE-2026-55379 (BdfFontFile), CVE-2026-55380 (GdImageFile) and CVE-2026-40192 (FITS GZIP). Details `Image.open()` → `_open_core()` runs `_decompression_bomb_check(im.size)` once, on the frame present at open time. Both vulnerable `seek()` methods…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)osv.dev (4)Source checked Evidence →
  14. High, CVSS 8.8PyPIAmendedPublished

    Pillow: Memory disclosure and segfault in libtiff encoder via crafted TIFF tags

    CVE-2026-112902 · GHSA-xvh5-g6gv-559v

    Affected
    • PyPI pillow <= 12.3.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    A crafted TIFF file of a few hundred bytes makes Pillow copy an attacker-chosen amount of its own process memory into the TIFF it writes back out, or crash the process outright. The trigger is an ordinary Image.open() followed by a bare im.save(fp, "TIFF"). The only precondition is that the application re-saves images as TIFF. When the uploaded file is compressed, Pillow routes that save through libtiff automatically, with no options from the application. The attached reproducer does this with a 356-byte LZW TIFF: one crafted tag comes back holding 65536 bytes taken from imaging.so's read-only data, and a second crafted tag makes the worker die with SIGSEGV on every run. The bug is in PyImagingLibTiffEncoderNew (src/encode.c). It decides what arguments to pass to the variadic TIFFSetField() from the shape of the Python value (scalar, tuple or bytes). It assumes its ImagingLibTiffMergeFieldInfo() call defined how libtiff will read them. But TIFFMergeFieldInfo() never overrides…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)Source checked Evidence →
  15. Critical, CVSS 9.2PyPIAmendedPublished

    Pillow: Heap buffer overflow in _tiffWriteProc when saving TIFF to BytesIO

    CVE-2026-112393 · GHSA-332p-7hrc-92wf

    Affected
    • PyPI pillow >= 2.0.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    ``` ============================================================================ Heap buffer overflow in _tiffWriteProc when saving TIFF to BytesIO Location: src/libImaging/TiffDecode.c:94 in _tiffWriteProc() Commit: a707c6b21c313880d0771e54965d142dd42358b6 ============================================================================ ``` Pillow can write attacker-chosen data past the end of a heap buffer when it saves a TIFF image to an in-memory destination such as `io.BytesIO` rather than to a file. The same code also copies leftover heap memory from the process into the saved file. Anyone who can supply an image to a service that opens it and re-saves it as TIFF this way can trigger this with default settings. The attached reproducer crashes the process, and the overflow could potentially be developed further, but code execution is not demonstrated here. The bug is in `_tiffWriteProc` in `src/libImaging/TiffDecode.c`. This is the write callback for the in-memory sink that Pillow…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)Source checked Evidence →
  16. Medium, CVSS 5.9PyPIAmendedPublished

    Pillow: Heap use-after-free when encoding TIFF to an in-memory buffer

    CVE-2026-112396 · GHSA-4rr5-89j8-mwwm

    Affected
    • PyPI pillow >= 11.3.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    Saving an image as TIFF to an in-memory buffer can trigger a heap use-after-free if libtiff rejects a tag at encode time. When `TIFFWriteScanline` fails, the encoder frees its output buffer but leaves the libtiff handle open. Later, when the encoder object is torn down, `TIFFClose` flushes buffered bytes through the write callback and writes into the freed buffer. An application that re-encodes attacker-influenced images to TIFF in memory can be crashed and is a candidate for remote code execution. Details The failure path in `ImagingLibTiffEncode` frees `clientstate->data` for the in-memory case but does not close the TIFF or null `clientstate->tiff` (the file-descriptor branch just above it does set `tiff = NULL`): - `src/libImaging/TiffDecode.c:1041-1046` Teardown then calls `ImagingLibTiffEncodeCleanup`, which runs `TIFFClose(tiff)` because `tiff` is still set: - `src/encode.c:99-101` - `src/libImaging/TiffDecode.c:955` `TIFFClose` flushes through…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)osv.dev (4)Source checked Evidence →
  17. High, CVSS 8.7PyPIAmendedPublished

    Pillow: Infinite loop in PdfParser.rewrite_pages on page tree Parent cycle

    CVE-2026-112406 · GHSA-f2g6-542v-9j58

    Affected
    • PyPI pillow >= 5.1.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    ``` ============================================================================ Infinite loop in PdfParser.rewrite_pages on page tree Parent cycle Location: src/PIL/PdfParser.py:505 in PdfParser.rewrite_pages() Commit: a707c6b21c313880d0771e54965d142dd42358b6 ============================================================================ ``` A PDF file of a few hundred bytes makes Pillow hang forever, holding one processor core at 100%, when an application tries to append an image to it. Anyone who can supply the existing PDF to an application that calls `im.save(fp, "PDF", append=True)` (or `save_all=True, append=True`) can tie up that worker indefinitely. Memory use stays flat, so only an external timeout stops it. The bug is in `PdfParser.rewrite_pages()` in `src/PIL/PdfParser.py` (the `while pages_tree_node_ref:` loop at line 505). For each original page, it walks the `/Parent` chain upward and stops only when it reaches a node with no `/Parent`. It keeps no record of nodes it has…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)Source checked Evidence →
  18. High, CVSS 8.7PyPIAmendedPublished

    Pillow: APNG background disposal allocates full canvas before decompression bomb check

    CVE-2026-112399 · GHSA-5xm2-6676-qcp9

    Affected
    • PyPI pillow >= 8.1.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    ``` ============================================================================ APNG background disposal allocates full canvas before decompression bomb check Location: src/PIL/PngImagePlugin.py:1000 in PngImageFile._seek() Commit: a707c6b21c313880d0771e54965d142dd42358b6 ============================================================================ ``` A 126-byte animated PNG file makes Pillow's `Image.open()` allocate and fill memory sized by the image dimensions the file claims, before Pillow's built-in check for oversized images runs. A file claiming 22000×22000 pixels costs about 1.9 GB. Anyone who can get an application to open an image they supply, with default settings and no further calls such as `load()`, can cause a multi-gigabyte memory spike per file. If the claimed size exceeds the machine's free memory, the operating system kills the process outright. The bug is in `PngImageFile._seek()` in `src/PIL/PngImagePlugin.py` (around line 1000). For any APNG, `_open()` calls…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)Source checked Evidence →
  19. High, CVSS 8.7PyPIAmendedPublished

    Pillow: MSP RLE decoder expands a tiny file into unbounded memory

    CVE-2026-112892 · GHSA-gg2r-wvfm-q9rx

    Affected
    • PyPI pillow >= 4.1.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    The MSP RLE decoder expands run-length data into an in-memory buffer with no cap tied to the declared image size. A small file that passes the pixel-count check can force hundreds of megabytes or more of allocation when the application loads pixels. Details The MSP decoder writes each run into an unbounded `io.BytesIO` and can expand roughly 85x per run: - `src/PIL/MspImagePlugin.py:144-146` Impact Memory-exhaustion denial of service from a tiny crafted image in any application that loads pixels. The expansion is decoupled from the declared pixel count, so `MAX_IMAGE_PIXELS` does not bound it.

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)Source checked Evidence →
  20. High, CVSS 8.7PyPIAmendedPublished

    Pillow: Quadratic-time DoS in PDF save_all (PdfParser.next_object_id)

    CVE-2026-112894 · GHSA-jg86-v3jv-hrpm

    Affected
    • PyPI pillow >= 5.1.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    ``` ============================================================================ Quadratic-time DoS in PDF save_all (PdfParser.next_object_id) Location: src/PIL/PdfParser.py:629 in next_object_id() Commit: a707c6b21c313880d0771e54965d142dd42358b6 ============================================================================ ``` Pillow's PDF writer takes time proportional to the square of the number of frames when it saves a multi-frame image as a multi-page PDF. Anyone who can get an application to convert their uploaded image this way can tie up a worker at full CPU for minutes with a small file. A 240 KB animated image takes about 70 seconds, a 720 KB one an estimated 10 minutes, and a 125-byte animated PNG that merely *declares* a large frame count triggers the same slowdown with no upper bound short of 2³¹ frames. Memory stays under 100 MB and the decompression-bomb limit never applies. The cause is `PdfParser.next_object_id()` in `src/PIL/PdfParser.py`, which finds the next free…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)Source checked Evidence →
  21. Medium, CVSS 6.3PyPIAmendedPublished

    Pillow: PdfParser can recurse without limit in get_value() and linearize_page_tree()

    CVE-2026-112391 · GHSA-254f-3936-288h

    Affected
    • PyPI pillow >= 5.1.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    `PdfParser`'s `get_value()` can recurse without any limit and crash with an uncaught `RecursionError`. It is reachable through `Image.save(im, fp= , format="PDF", append=True)` when the existing PDF file is attacker-controlled. This is the same class of bug as https://github.com/advisories/GHSA-r73j-pqj5-w3x7 (the /Prev trailer chain loop, fixed earlier this year), in the same file, but in two different functions that fix did not touch. Details `get_value()` in `src/PIL/PdfParser.py` This is a classmethod that takes `max_nesting: int = -1` and has a guard: ```python if max_nesting == 0: return None, None ``` Every recursive call (nested arrays, dictionaries, indirect object definitions) passes `max_nesting=max_nesting - 1`. Since the default and every call site start at -1, this only ever counts down further negative: -1, -2, -3, and so on. It never equals exactly 0, so the guard never runs. A PDF object with a value nested a few thousand levels deep is enough to…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)Source checked Evidence →
  22. Medium, CVSS 6.9PyPIAmendedPublished

    Pillow: ReDoS in XbmImagePlugin: 512-byte file stalls Image.open() for minutes

    CVE-2026-112901 · GHSA-xgh8-jp6q-p5x8

    Affected
    • PyPI pillow < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    ``` ============================================================================ ReDoS in XbmImagePlugin: 512-byte file stalls Image.open() for minutes Location: src/PIL/XbmImagePlugin.py:58 in XbmImageFile._open() Commit: a707c6b21c313880d0771e54965d142dd42358b6 ============================================================================ ``` A crafted 512-byte file makes Pillow's `Image.open()` spend about six minutes of processor time on one core before it gives up with `UnidentifiedImageError`. Anyone who can hand bytes to an application that opens images with Pillow's default settings can trigger this, for example through an upload form, a thumbnailer, or a service that checks whether a blob is an image. A few such files sent at once can tie up a typical pool of worker processes. The cause is the `xbm_head` regular expression in `src/PIL/XbmImagePlugin.py:32-40`, which `XbmImageFile._open()` (line 58) runs over the first 512 bytes of any stream whose prefix starts with `#define`.…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)osv.dev (4)Source checked Evidence →
  23. Medium, CVSS 6.9PyPIAmendedPublished

    Pillow: Image.quantize() with empty palette leaks uninitialized stack memory

    CVE-2026-112898 · GHSA-rfgq-q3w2-pmv2

    Affected
    • PyPI pillow >= 9.1.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    ``` ============================================================================ Image.quantize() with empty palette leaks uninitialized stack memory Location: src/libImaging/Palette.c:216 in ImagingPaletteCacheUpdate() Commit: a707c6b21c313880d0771e54965d142dd42358b6 ============================================================================ ``` When an application lets a user supply the palette image for Pillow's `Image.quantize(palette=...)`, the user can get back 512 bytes of the server process's stack memory in the pixels of the returned image. An 80-byte PNG with an empty palette is enough, and the leaked bytes survive saving to PNG or GIF. In the runs examined, those bytes included memory addresses inside the stack, heap, libc, libpython and Pillow's own C module, along with the stack-protector canary. The bug is in `ImagingPaletteCacheUpdate()` in `src/libImaging/Palette.c`. It fills a local `UINT8 c[512]` only inside loops bounded by `palette->size`. When the palette has…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)Source checked Evidence →
  24. Medium, CVSS 6.9PyPIAmendedPublished

    Pillow: Quadratic GIF comment concatenation allows DoS in Image.open()

    CVE-2026-112401 · GHSA-74r2-7ff9-mjj2

    Affected
    • PyPI pillow >= 5.4.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    ``` ============================================================================ Quadratic GIF comment concatenation allows DoS in Image.open() Location: src/PIL/GifImagePlugin.py:266 in GifImageFile._seek() Commit: a707c6b21c313880d0771e54965d142dd42358b6 ============================================================================ ``` Opening a crafted GIF file with `Image.open()` takes time that grows with the square of the file's size, so anyone who can submit an image to a service that uses Pillow can keep one worker busy at full processor load for a long time with a small file. A 2 MB file takes about 5 seconds to open, a 4 MB file about 35 seconds, and an 8 MB file about 3 minutes. An ordinary GIF of the same size opens in well under a second. The cost is paid inside `Image.open()` itself, with default settings, before the application has seen the image's size or format. The bug is in `GifImageFile._seek()` in `src/PIL/GifImagePlugin.py`, which builds `info["comment"]` by…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)Source checked Evidence →
  25. High, CVSS 8.2PyPIAmendedPublished

    Pillow: Infinite loop in MIC n_frames when the embedded TIFF

    CVE-2026-112390 · GHSA-22hg-r758-rrw9

    Affected
    • PyPI pillow >= 7.2.0, < 13.0.0
    Fixed in
    13.0.0· Vendor fix available
    Issue
    ``` ============================================================================ Infinite loop in MIC n_frames when the embedded TIFF has 3+ IFDs Location: src/PIL/MicImagePlugin.py:86 in MicImageFile.tell() Commit: a707c6b21c313880d0771e54965d142dd42358b6 ============================================================================ ``` A crafted 5.6 KB image file makes Pillow loop forever at 100% CPU when an application asks how many frames the image has. This only affects installations that have the optional `olefile` package. Any application that opens an untrusted image and then reads `im.n_frames` can have one worker tied up indefinitely. That includes the common "is this image animated?" check and re-saving with `save_all=True` to TIFF, PDF or WebP. The call never returns, raises no exception, and does not grow memory, so only an external watchdog stops it. The file is a Microsoft Image Composer (MIC) container, which Pillow recognises by its magic bytes with no extension…

    Recommended action: Upgrade to 13.0.0 or later, then redeploy and verify.A vendor fix does not resolve your finding until you verify it in your own systems.

    Sources:github.com (1)osv.dev (2)osv.dev (3)Source checked Evidence →