CVE-2026-59935 Overview
CVE-2026-59935 is a denial-of-service vulnerability in pypdf, a widely used pure-Python PDF library. Versions prior to 6.14.2 fail to handle unterminated inline images that use the ASCII85 or ASCIIHex filters. An attacker who supplies a crafted PDF triggers an infinite loop during page content parsing, such as when the application calls text extraction routines. The condition falls under [CWE-835] (Loop with Unreachable Exit Condition) and is fixed in pypdf version 6.14.2.
Critical Impact
Any service that parses attacker-supplied PDFs with pypdf can be hung indefinitely, exhausting CPU and worker capacity and producing a reliable denial-of-service condition without authentication.
Affected Products
- pypdf versions prior to 6.14.2
- Python applications and services that invoke pypdf on untrusted PDF input
- Downstream pipelines performing text extraction, indexing, or content analysis on user-supplied PDFs
Discovery Timeline
- 2026-07-08 - CVE-2026-59935 published to NVD
- 2026-07-08 - Last updated in NVD database
- pypdf 6.14.2 - Fixed release published on GitHub
Technical Details for CVE-2026-59935
Vulnerability Analysis
The defect resides in pypdf's inline-image parser inside pypdf/generic/_image_inline.py and the related content-stream reader in pypdf/generic/_data_structures.py. When the parser encounters an inline image using the ASCII85 (/A85) or ASCIIHex (/AHx) filter, it loops while searching for the terminating > byte followed by the EI operator. If the stream ends before either delimiter appears, the loop's exit condition is never reached because the code did not detect that stream.read() returned zero bytes at end of file. Parsing therefore spins on the same stream position indefinitely, consuming one CPU core per request.
Root Cause
The original loop only tested if not data_buffered, but read_non_whitespace could still return residual whitespace bytes even when stream.read(BUFFER_SIZE) produced no new data. That combination kept data_buffered truthy while forward progress halted, satisfying the definition of [CWE-835]. The patch adds an explicit check that new bytes were actually read from the stream on each iteration.
Attack Vector
Exploitation requires only that the target application parse an attacker-controlled PDF. Common exposure points include web upload endpoints, email attachment scanners, document conversion services, and machine learning ingestion pipelines. No authentication, user interaction, or memory corruption primitives are required — a single malformed PDF is sufficient to stall a worker process.
# Fix in pypdf/generic/_image_inline.py
data_out = bytearray()
# Read data until delimiter > and EI as backup.
while True:
data_buffered = read_non_whitespace(stream) + (read_bytes := stream.read(BUFFER_SIZE))
if not data_buffered or not read_bytes:
raise PdfReadError("Unexpected end of stream.")
pos_tok = data_buffered.find(b">")
if pos_tok >= 0: # found >
data_out += data_buffered[: pos_tok + 1]
# Source: https://github.com/py-pdf/pypdf/commit/5a33a46416aa1ae6c025ff90a3cca57631fdafd2
The added read_bytes walrus assignment guarantees the loop terminates with a PdfReadError whenever the underlying stream is exhausted, eliminating the unreachable exit condition.
Detection Methods for CVE-2026-59935
Indicators of Compromise
- Python worker processes consuming 100% CPU on a single core while stuck inside pypdf call frames such as _image_inline or read_inline_image.
- Request timeouts, queue backlogs, or OOM kills correlated with recent PDF uploads.
- PDFs containing inline image markers (BI / ID) with ASCII85 (/A85, /ASCII85Decode) or ASCIIHex (/AHx, /ASCIIHexDecode) filters and no matching EI terminator.
Detection Strategies
- Add per-request wall-clock and CPU-time limits around pypdf calls and alert when timeouts fire on PDF parsing paths.
- Sample py-spy or faulthandler stack traces from long-running workers and flag frames inside pypdf/generic/_image_inline.py.
- Inventory Python dependencies with pip list or SBOM tooling and mark hosts running pypdf < 6.14.2 as vulnerable.
Monitoring Recommendations
- Instrument document-processing services with metrics for parse duration, CPU seconds per file, and error rates from PdfReadError.
- Forward application logs into a centralized analytics platform such as Singularity Data Lake to correlate slow PDF parses with the uploading identity and source IP.
- Alert on repeated submissions of PDFs that trigger parser timeouts from the same client, which indicates active abuse.
How to Mitigate CVE-2026-59935
Immediate Actions Required
- Upgrade pypdf to version 6.14.2 or later in every application and container image that processes PDFs.
- Enforce a hard timeout on any code path that calls pypdf functions such as extract_text() or PdfReader.
- Rate-limit unauthenticated PDF uploads and reject files larger than the documented maximum for your workflow.
Patch Information
The fix is delivered in the pypdf 6.14.2 release via pull request #3892 and commit 5a33a464. Full details are in the GHSA-g867-7843-wf8q advisory. Upgrade with pip install --upgrade 'pypdf>=6.14.2'.
Workarounds
- Wrap pypdf invocations in a subprocess or worker with a strict CPU and wall-clock budget, terminating any job that exceeds it.
- Pre-validate uploaded PDFs and reject files that contain inline image operators without a matching EI terminator when full patching is delayed.
- Isolate PDF parsing in a sandboxed, resource-capped container so an infinite loop cannot exhaust host resources.
# Patch pypdf across your environment
pip install --upgrade 'pypdf>=6.14.2'
# Verify the installed version
python -c "import pypdf; print(pypdf.__version__)"
# Optional: pin the fixed version in requirements.txt
echo 'pypdf>=6.14.2' >> requirements.txt
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

