CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-59936

CVE-2026-59936: Infinite Loop in pypdf Inline Image Parser Leads to Denial of Service

Alon Barad
Alon Barad
Software Engineer

Jul 23, 2026·6 min read·4 visits

Executive Summary (TL;DR)

A flaw in the inline image parsing logic of pypdf versions prior to 6.14.1 allows an unauthenticated remote attacker to cause a complete Denial of Service (100% CPU thread utilization) by submitting a malformed PDF with a truncated inline image block.

An infinite loop vulnerability exists in the pure-python PDF library pypdf prior to version 6.14.1. This vulnerability occurs during the processing of malformed or truncated page content streams containing inline images. Specifically, the parser fails to validate the End-of-Stream condition during inline image dictionary parsing. This results in continuous backward stream-seeking and an infinite loop that consumes 100% CPU on the processing thread.

Vulnerability Overview

The vulnerability exists within the core content stream lexing engine of pypdf, specifically during the parsing of inline images in page content streams. In the PDF specification, inline images are embedded directly within content streams utilizing structural markers rather than being stored in external resource dictionaries. This parsing is executed by the internal content stream engine when functions like text extraction or rendering preparation are invoked.

Because PDF parsers are frequently deployed in automated pipeline environments (such as document ingestion systems, search indexing, and automated email processing), they present a significant unauthenticated attack surface. If an application utilizes a vulnerable version of pypdf to parse untrusted files, an attacker can exploit this surface to exhaust system resource limits.

This flaw is classified under CWE-400 (Uncontrolled Resource Consumption). It is caused by a failure to safely terminate a parsing loop when encountering an unexpected End-of-Stream (EOF) condition inside the inline image metadata blocks, leading directly to a Denial of Service (DoS).

Root Cause Analysis

To understand the root cause of CVE-2026-59936, we must analyze how PDF inline images are structured and how pypdf processes them. An inline image is bounded by three specific markers: BI (Begin Image), ID (Image Data), and EI (End Image). Between BI and ID, the PDF stream contains dictionary key-value settings defining properties such as width, height, and color space.

The parsing of these properties is performed by the _read_inline_image function in pypdf/generic/_data_structures.py. This function uses a while True loop to continuously fetch keys and values from the input stream using the helper function read_non_whitespace(stream). The parser reads the next token and then backs up the stream pointer by one byte using stream.seek(-1, 1) to evaluate the token's initial character.

If the stream ends prematurely—due to decompression errors, document truncation, or malicious formatting—read_non_whitespace(stream) returns an empty byte string (b""). Because the pre-patch code did not check whether the retrieved token was empty, the parser proceeded to execute the relative backward seek operation stream.seek(-1, 1). On the next loop iteration, the parser read from the same position, retrieved the empty token, backed up again, and repeated this sequence infinitely, locking the execution thread at maximum CPU utilization.

Code Analysis

The vulnerability resides in pypdf/generic/_data_structures.py within the _read_inline_image method. Below is the vulnerable code block:

def _read_inline_image(self, stream: StreamType) -> dict[str, Any]:
    settings = DictionaryObject()
    while True:
        tok = read_non_whitespace(stream)
        # BUG: Missing verification of token presence. 
        # If tok is empty (EOF), seek moves the stream pointer backward.
        stream.seek(-1, 1)
        if tok == b"I":
            # "ID" - begin of image data
            ...

When read_non_whitespace(stream) encounters the end of the stream, it returns b"". The stream's current position pointer is at the very end of the file or stream block. The subsequent call to stream.seek(-1, 1) moves the stream pointer back by 1 byte. Consequently, subsequent read operations do not hit the natural EOF condition, preventing the stream object from reporting that it is exhausted. This establishes a self-sustaining loop that cannot terminate naturally.

The fix implemented in version 6.14.1 resolves this issue by inserting an explicit check for the empty token condition immediately after retrieving it from the helper function:

def _read_inline_image(self, stream: StreamType) -> dict[str, Any]:
    settings = DictionaryObject()
    while True:
        tok = read_non_whitespace(stream)
        # FIX: Validate that a token was successfully read.
        # If empty, raise an explicit exception to exit the parsing cycle.
        if not tok:
            raise PdfStreamError("Unexpected end of stream.")
        stream.seek(-1, 1)
        if tok == b"I":
            # "ID" - begin of image data
            ...

By raising PdfStreamError, the parser aborts execution gracefully, preventing the infinite loop and allowing parent exception handlers to clean up resources.

Exploitation Methodology

Exploitation of CVE-2026-59936 is straightforward and does not require complex memory corruption payloads or bypasses for security mitigations like ASLR or DEP. An attacker only needs to generate a PDF document containing a malformed inline image sequence where the key-value settings block is truncated and lacks the matching ID and EI operators.

The minimal trigger payload consists of the start marker of an inline image block immediately followed by a key setting, with the stream abruptly ending. A representative sample is shown below:

BI
/IM true
/W001

When a vulnerable application parses this content stream (for example, while invoking reader.pages[0].extract_text()), the parser enters the metadata parsing loop. It processes /IM true and /W001, and then encounters the end of the stream. Rather than terminating, the thread enters the infinite loop and utilizes 100% of its assigned CPU core. If the application handles file uploads asynchronously or sequentially in a single-threaded queue, a single malicious file can halt all subsequent document processing jobs.

Impact Assessment & Risk Analysis

The threat profile of this vulnerability is characterized as High. The authoritative CVSS v4.0 score is 8.7, reflecting a Network (N) attack vector with low complexity and zero required privileges or user interaction. The secondary CVSS v3.1 rating is 7.5, reflecting a High Availability impact.

In microservice architectures or cloud-native applications, worker processes are often shared across tenants. Exhausting CPU resources on a worker node can cause cascading failures, API timeouts, and increased operational costs due to automatic scaling engines attempting to provision additional nodes to handle the false load.

While there is currently no evidence of active exploitation in the wild (as reflected by its status in the CISA KEV and its low EPSS score of 0.00345), the simplicity of creating a functional proof-of-concept file elevates the risk of automated scanning or targeted denial-of-service attacks against public-facing document processing portals.

Remediation and Defensive Strategy

The primary remediation for this vulnerability is upgrading the pypdf dependency to version 6.14.1 or higher. This release contains the patch that correctly terminates execution by throwing a PdfStreamError when the end of stream is reached.

For environments where immediate upgrading is not possible, system administrators and developers should implement process-level isolation and timeout mechanisms. For instance, wrapping PDF parsing logic in worker tasks configured with hard execution limits (e.g., Celery task time limits or Python signal timers) ensures that hanging parser threads are forcibly terminated before exhausting system resources.

Additionally, applications should not perform PDF processing within the context of the main web server thread. Offloading these tasks to dedicated, sandboxed worker containers with restricted CPU allocations limits the blast radius of any successful exploit attempt.

Official Patches

py-pdfGitHub Security Advisory GHSA-5xf7-4p34-54qr
py-pdfOfficial Fix Pull Request

Fix Analysis (1)

Technical Appendix

CVSS Score
8.7/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
EPSS Probability
0.34%
Top 73% most exploited

Affected Systems

Applications utilizing the Python library pypdf to extract text, images, or metadata from untrusted PDF files.

Affected Versions Detail

Product
Affected Versions
Fixed Version
pypdf
py-pdf
< 6.14.16.14.1
AttributeDetail
CWE IDCWE-400
Attack VectorNetwork
CVSS v4.0 Score8.7
EPSS Score0.00345
ImpactDenial of Service (DoS)
Exploit Statuspoc
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-400
Uncontrolled Resource Consumption

The software does not properly control the allocation and maintenance of a limited resource, enabling an attacker to influence the amount of resources consumed and eventually leading to a resource exhaustion state.

Known Exploits & Detection

GitHub Test SuiteThe official PR includes an integration test demonstrating how feeding a malformed, truncated content stream to _read_inline_image leads to an infinite loop in vulnerable versions.

Vulnerability Timeline

Pull Request #3891 opened and merged to resolve the infinite loop flaw.
2026-06-23
pypdf version 6.14.1 officially released containing the security fix.
2026-06-23
GitHub Security Advisory (GHSA-5xf7-4p34-54qr) published and CVE-2026-59936 assigned.
2026-07-08
National Vulnerability Database (NVD) parses and catalogs the vulnerability details.
2026-07-09

References & Sources

  • [1]NVD CVE-2026-59936 Detail
  • [2]CVE.org Record
  • [3]pypdf 6.14.1 Release Tag

More Reports

•12 minutes ago•CVE-2026-59938
5.3

CVE-2026-59938: Uncontrolled Memory Allocation (DoS) in pypdf Image Parsing

An uncontrolled memory allocation vulnerability (CWE-789) exists in pypdf prior to version 6.14.0. The library blindly trusted user-controlled image dimensions (/Width and /Height) from PDF metadata, allowing attackers to trigger physical memory exhaustion and an Out-of-Memory crash via tiny, malformed files.

Amit Schendel
Amit Schendel
0 views•8 min read
•about 2 hours ago•CVE-2026-59935
8.7

CVE-2026-59935: Infinite Loop Denial of Service in pypdf via Malformed Inline Images

An infinite loop vulnerability exists in the pypdf library prior to version 6.14.2 when processing malformed PDF inline images that utilize ASCII85 or ASCIIHex decoders. Attackers can exploit this vulnerability by submitting crafted PDF files containing incomplete streams, causing the parsing thread to consume 100% CPU resource indefinitely and leading to Denial of Service.

Amit Schendel
Amit Schendel
4 views•7 min read
•about 3 hours ago•CVE-2026-59937
7.5

CVE-2026-59937: CPU Exhaustion via Quadratic-Time Cross-Reference Recovery Loop in pypdf

A critical CPU exhaustion vulnerability exists in the pypdf library before version 6.14.0. When parsing PDF files with malformed or corrupt standard cross-reference (xref) table entries, the library falls back to sequentially scanning the entire file buffer via regular expression search. An attacker can exploit this algorithmic bottleneck by supplying a crafted PDF with numerous malformed xref entries, leading to denial of service.

Alon Barad
Alon Barad
4 views•4 min read
•about 4 hours ago•GHSA-8FPG-XM3F-6CX3
7.4

GHSA-8FPG-XM3F-6CX3: Authentication Fail-Open via Unvalidated Server Responses in Auth.js

In Auth.js (specifically next-auth version 5), server-side configuration errors or backend exceptions can cause existence-based authentication and authorization checks to fail open. When the underlying core engine (@auth/core) encounters a configuration error or runtime exception, it returns an HTTP 500 Internal Server Error response containing a JSON-formatted error description payload. Prior to the fix, the next-auth wrappers read this response body using response.json() without validating the HTTP status code. Because any parsed JavaScript object evaluates to truthy, common existence-based checks incorrectly evaluated to true, letting unauthenticated requests pass.

Alon Barad
Alon Barad
4 views•7 min read
•about 6 hours ago•CVE-2026-6790
5.3

CVE-2026-6790: Host/Authority Header Desynchronization in Eclipse Jetty

A host/authority desynchronization vulnerability exists in Eclipse Jetty's handling of HTTP/2 and HTTP/3 requests. When both an ':authority' pseudo-header and a standard 'Host' header are present in a request, Jetty fails to validate that they represent the same target host. This desynchronization creates a host-confusion or 'split-brain' state, enabling attackers to bypass access control lists, escape virtual host isolation, poison web caches, or manipulate redirect targets in backend applications.

Amit Schendel
Amit Schendel
5 views•5 min read
•about 7 hours ago•CVE-2026-8384
5.3

CVE-2026-8384: URI Path Parameter Parser State-Desynchronization Path Traversal in Eclipse Jetty

A path traversal vulnerability exists in Eclipse Jetty due to a state-desynchronization defect in the URI parsing state machine inside URIUtil.java. This defect allows unauthenticated remote attackers to bypass path-based security constraints enforced by downstream filters, application gateways, or authorization modules by crafting URIs with path parameter delimiters and parent directory traversal sequences.

Amit Schendel
Amit Schendel
6 views•7 min read