CVE-2026-59937 Overview
CVE-2026-59937 is a denial-of-service vulnerability in pypdf, a pure-Python PDF library used by data pipelines, document processing services, and web applications. Versions prior to 6.14.0 mishandle repeated malformed cross-reference streams inside PDF documents. An attacker who supplies a crafted PDF causes pypdf to spend excessive time recovering broken cross-reference table entries. The condition maps to [CWE-400: Uncontrolled Resource Consumption]. Exploitation requires no authentication and no user interaction beyond the target parsing the attacker-supplied file. The pypdf maintainers fixed the issue in version 6.14.0 by introducing a recovery cache that speeds up handling of broken cross-reference tables.
Critical Impact
A single crafted PDF can consume CPU resources on any service that ingests untrusted documents through pypdf, degrading availability of document-processing workloads.
Affected Products
- pypdf versions prior to 6.14.0
- Python applications and services that parse untrusted PDFs using pypdf
- Downstream libraries and frameworks that embed pypdf as a dependency
Discovery Timeline
- 2026-07-08 - CVE-2026-59937 published to NVD
- 2026-07-08 - Last updated in NVD database
Technical Details for CVE-2026-59937
Vulnerability Analysis
The vulnerability lives in pypdf's cross-reference (xref) recovery path. A PDF file uses an xref table to map object numbers to byte offsets inside the document. When pypdf detects a broken xref table, it falls back to a recovery routine that scans the file for object headers to rebuild the mapping. Prior to 6.14.0, this recovery routine repeated expensive scanning work for each malformed xref stream encountered in a single PDF. An attacker can embed many malformed cross-reference streams in one document, forcing the parser to repeat the scan on every recovery attempt. The result is a CPU-bound denial of service on any process parsing the file.
Root Cause
The recovery logic did not cache the results of scanning the raw PDF bytes for object headers. Every malformed xref stream triggered a fresh, full-document scan. This is a classic algorithmic-complexity issue: attacker-controlled input multiplies the work performed by a linear scan into behavior that scales poorly with document size and number of embedded malformed streams.
Attack Vector
Exploitation is remote and unauthenticated wherever pypdf ingests attacker-controlled PDFs. Common attack surfaces include email attachment scanners, SaaS document converters, CI/CD pipelines that parse PDFs, and web upload endpoints. The attacker only needs to deliver a crafted PDF; parsing the file triggers the excessive recovery loop.
# Patch excerpt: pypdf/_reader.py - SEC: Speed up recovery when reading
# broken cross-reference table (pypdf PR #3887, commit b5fc5aa)
break
raise PdfReadError("startxref not found")
def _load_recovery_cache(self, data: bytes) -> dict[int, tuple[int, int]]:
cache = {}
for object_number, generation_number, object_start in self._find_pdf_objects(data):
if object_number in cache:
# Always use the first match.
continue
cache[object_number] = (object_start, generation_number)
return cache
def _read_standard_xref_table(self, stream: StreamType) -> None:
# standard cross-reference table
ref = stream.read(3)
Source: pypdf commit b5fc5aa. The fix introduces _load_recovery_cache, which scans the PDF for object headers once and reuses the mapping across every recovery attempt.
Detection Methods for CVE-2026-59937
Indicators of Compromise
- Python processes importing pypdf that exhibit sustained high CPU usage while parsing a single PDF file.
- Request timeouts or worker restarts in document-processing services shortly after an untrusted PDF is uploaded.
- PDF files that contain multiple malformed or truncated cross-reference streams alongside repeated xref keywords.
Detection Strategies
- Inventory application dependencies to identify installations of pypdf below version 6.14.0, including transitive dependencies pulled in by other libraries.
- Instrument PDF parsing calls with wall-clock timers and alert when parse duration exceeds a workload-appropriate threshold.
- Log and review any PdfReadError or xref recovery messages emitted by pypdf, since recovery paths are the trigger for the slowdown.
Monitoring Recommendations
- Track CPU and memory metrics per worker on services that parse user-supplied PDFs and alert on sustained saturation tied to a single request.
- Retain samples of PDFs that caused parser timeouts for offline analysis of xref structures.
- Correlate upload sources with parse-time anomalies to identify abusive clients submitting crafted documents.
How to Mitigate CVE-2026-59937
Immediate Actions Required
- Upgrade pypdf to version 6.14.0 or later in all applications, container images, and build pipelines.
- Audit transitive dependencies with pip list or a software bill of materials tool to catch pinned older versions of pypdf.
- Enforce parse timeouts and per-request CPU limits on services that accept PDFs from untrusted sources.
Patch Information
The fix ships in pypdf 6.14.0 via pull request #3887 and commit b5fc5aa. See the GitHub Security Advisory GHSA-55h5-xmcq-c37v and the pypdf 6.14.0 release notes for full details.
Workarounds
- Run PDF parsing in an isolated worker process with a hard wall-clock timeout to cap the impact of any single document.
- Reject or pre-filter PDFs that exceed a reasonable size or that fail a fast structural sanity check before invoking pypdf.
- Move PDF parsing behind a queue with concurrency limits so that a burst of malicious uploads cannot exhaust all workers.
# Upgrade pypdf to the fixed release
pip install --upgrade 'pypdf>=6.14.0'
# Verify the installed version
python -c "import pypdf; print(pypdf.__version__)"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

