Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-59938

CVE-2026-59938: pypdf Library DOS Vulnerability

CVE-2026-59938 is a denial of service vulnerability in pypdf library where attackers craft PDFs with oversized image declarations causing excessive memory usage. This article covers technical details, affected versions, and mitigation.

Published:

CVE-2026-59938 Overview

CVE-2026-59938 is a memory exhaustion vulnerability in pypdf, a widely used pure-Python PDF library. Versions prior to 6.14.0 fail to validate declared image dimensions against actual image data during PDF parsing. An attacker can craft a PDF that declares oversized image dimensions, causing pypdf to allocate excessive memory when processing the image. The underlying weakness is classified as [CWE-789: Memory Allocation with Excessive Size Value]. Any application or service that parses untrusted PDF documents with pypdf is exposed to remote denial-of-service conditions. The issue is fixed in pypdf version 6.14.0.

Critical Impact

Attackers can trigger uncontrolled memory allocation in pypdf by supplying a malicious PDF, leading to denial of service against document-processing pipelines.

Affected Products

  • pypdf versions prior to 6.14.0
  • Python applications and services that parse untrusted PDF files with pypdf
  • Document-processing pipelines, PDF ingestion APIs, and OCR workflows built on pypdf

Discovery Timeline

  • 2026-07-08 - CVE-2026-59938 published to NVD
  • 2026-07-09 - Last updated in NVD database

Technical Details for CVE-2026-59938

Vulnerability Analysis

The vulnerability resides in pypdf's image parsing path. When pypdf decodes an image XObject embedded in a PDF, it trusts the declared image dimensions (width × height) and the color mode when constructing the pixel buffer. A crafted PDF can declare very large dimensions while providing only a small compressed data stream. During reconstruction, pypdf computes a required buffer size based on the attacker-controlled values and attempts to materialize a Pillow Image object of that size. This produces a large memory allocation that can exhaust available RAM on the host. The flaw is a resource-consumption issue [CWE-789] rather than a memory-corruption bug, and it does not require authentication or user interaction beyond supplying a PDF for processing.

Root Cause

The root cause is missing validation of declared image size before allocation in _image_from_bytes within pypdf/generic/_image_xobject.py. Prior to the patch, the function passed attacker-controlled size and mode values directly to Image.frombytes and, in the fallback path, computed a byte-replication factor k = nb_pix * len(mode) / data_length without bounding the total buffer size. Because no upper limit was enforced on pixel_count * bytes_per_pixel, an adversary could specify arbitrarily large images.

Attack Vector

Exploitation requires an attacker to deliver a crafted PDF to any component that parses it with a vulnerable version of pypdf. Common exposure points include web upload endpoints, email attachment scanners, PDF-to-text services, and automated report ingestion. Because the attack vector is network-reachable and requires no privileges, unattended server-side parsing is the highest-risk scenario. Successful exploitation manifests as memory exhaustion, worker crashes, and degradation or outage of the hosting service.

python
# Patch excerpt from pypdf/generic/_image_xobject.py
# Source: https://github.com/py-pdf/pypdf/commit/c64583be16b8e8763d8777075f8ecbf382014b7a
def _image_from_bytes(
    mode: str, size: tuple[int, int], data: bytes
) -> Image.Image:
    pixel_count = size[0] * size[1]
    bytes_per_pixel = len(mode)
    required_byte_count = pixel_count * bytes_per_pixel

    from pypdf.filters import FLATE_MAX_BUFFER_SIZE  # noqa: PLC0415
    if required_byte_count > FLATE_MAX_BUFFER_SIZE:
        raise LimitReachedError(
            f"Requested image buffer size {required_byte_count} exceeds limit {FLATE_MAX_BUFFER_SIZE}."
        )

    try:
        img = Image.frombytes(mode, size, data)
    except ValueError as exc:
        data_length = len(data)
        if data_length == 0:
            raise EmptyImageDataError(
                "Data is 0 bytes, cannot process an image from empty data."
            ) from exc
        if data_length % pixel_count != 0:
            raise
        k = required_byte_count / data_length
        data = b"".join(bytes((x,) * int(k)) for x in data)
        img = Image.frombytes(mode, size, data)
    return img

The patch enforces FLATE_MAX_BUFFER_SIZE (75,000,000 bytes) as an upper bound on requested image size and raises LimitReachedError before allocation occurs. Source: pypdf commit c64583b.

Detection Methods for CVE-2026-59938

Indicators of Compromise

  • Python worker processes hosting pypdf terminated by the OS out-of-memory killer shortly after PDF ingestion.
  • Unhandled exceptions or tracebacks originating in pypdf/generic/_image_xobject.py or pypdf/filters.py during document processing.
  • Sudden spikes in resident memory usage of PDF-parsing services correlated with specific inbound documents.

Detection Strategies

  • Inventory Python dependencies across build artifacts and container images to identify pypdf versions below 6.14.0.
  • Inspect PDF image XObjects for implausibly large /Width and /Height values relative to the size of the compressed stream.
  • Correlate application error logs referencing MemoryError, Image.frombytes, or LimitReachedError with document upload events.

Monitoring Recommendations

  • Alert on rapid memory growth or OOM terminations in services that parse user-supplied PDFs.
  • Log and rate-limit PDF uploads by source, and record file hashes for post-incident analysis.
  • Track pypdf version drift in software bill of materials (SBOM) reports across your fleet.

How to Mitigate CVE-2026-59938

Immediate Actions Required

  • Upgrade pypdf to version 6.14.0 or later in all applications, containers, and virtual environments.
  • Pin the minimum version in requirements.txt, pyproject.toml, or Poetry lockfiles to prevent regression.
  • Rebuild and redeploy any container images that bundle pypdf as a transitive dependency.

Patch Information

The fix is included in pypdf6.14.0, which introduces a hard limit of 75,000,000 bytes on the requested image buffer size and raises LimitReachedError when a PDF declares a larger allocation. Details are available in the pypdf 6.14.0 release notes, the GitHub Security Advisory GHSA-5qjq-93h5-hrgp, and pull request #3888.

Workarounds

  • Run PDF parsing in isolated worker processes with strict memory cgroups or ulimit caps to contain exhaustion.
  • Reject PDFs exceeding a reasonable maximum file size at the ingress layer before they reach pypdf.
  • Pre-validate PDFs with a lightweight parser to filter documents declaring absurd image dimensions.
bash
# Upgrade pypdf to the patched release
pip install --upgrade "pypdf>=6.14.0"

# Verify the installed version
python -c "import pypdf; print(pypdf.__version__)"

# Example dependency pin
# requirements.txt
# pypdf>=6.14.0

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.