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

CVE-2026-84311: pypdf Library DOS Vulnerability

CVE-2026-84311 is a denial of service vulnerability in pypdf library that enables attackers to cause excessive memory consumption and long runtimes through crafted PDFs. This article covers technical details, affected versions, impact assessment, and mitigation strategies.

Published:

CVE-2026-84311 Overview

CVE-2026-84311 is a denial-of-service vulnerability in pypdf, a pure-Python PDF library used by document processing pipelines, data extraction tools, and PDF-handling web services. Versions prior to 6.16.1 allow an attacker to craft a PDF that forces PageObject._extract_text and PageObject.extract_xform_text in pypdf/_page.py to traverse a directed acyclic graph of reused form XObjects. Because each form invokes its children multiple times, traversal paths grow exponentially. The result is long CPU runtimes and large memory consumption when parsing a single malicious document. The issue falls under [CWE-834: Excessive Iteration] and is fixed in pypdf 6.16.1.

Critical Impact

A single crafted PDF processed by a vulnerable pypdf version can exhaust CPU and memory on the host running text extraction, disrupting document processing workflows.

Affected Products

  • pypdf versions prior to 6.16.1
  • Applications and services invoking PageObject._extract_text
  • Applications and services invoking PageObject.extract_xform_text

Discovery Timeline

  • 2026-09-01 - CVE-2026-84311 published to NVD
  • 2026-09-02 - Last updated in NVD database

Technical Details for CVE-2026-84311

Vulnerability Analysis

The flaw resides in the text-extraction path of pypdf/_page.py. When a page references form XObjects, the extractor recursively walks each referenced form to collect text content. PDF form XObjects can be shared and reused across a document, forming a directed acyclic graph (DAG) rather than a tree. The extractor does not deduplicate visits or cap iterations. When a parent form invokes the same child form multiple times, and that child itself invokes its children multiple times, the number of traversal paths grows as the product of fan-out at each level. A shallow DAG can therefore encode billions of traversal paths that the parser will attempt to walk.

Root Cause

The extraction routines lacked shared-state tracking to bound recursion across reused XObjects. The upstream fix introduces a _TraversalState dataclass in pypdf/_utils.py that carries a mutable counter (entry_count) and a has_logged flag through the traversal. This state is threaded into outline retrieval and XForm text extraction so the code can enforce an iteration cap and log a warning once the limit is reached, converting exponential work into bounded work.

Attack Vector

Exploitation requires a user or automated pipeline to open or process a malicious PDF using a vulnerable pypdf release. The attack does not require authentication or network access to the parser itself; the vector is the document. Batch document-ingestion services, OCR preprocessing steps, and search indexers that call extract_text on untrusted PDFs are the most exposed. Successful exploitation ties up worker processes and can exhaust memory, degrading or halting the service.

python
# Source: https://github.com/py-pdf/pypdf/commit/d91ab705fd81ed1a9cec175c6958600dea1a4942
# Patch in pypdf/_utils.py introducing the traversal counter used to bound iterations
@dataclass
class _TraversalState:
    """Sometimes we need mutable objects which just count something."""
    entry_count: int = 0
    has_logged: bool = False
python
# Source: https://github.com/py-pdf/pypdf/commit/d91ab705fd81ed1a9cec175c6958600dea1a4942
# Patch in pypdf/_doc_common.py wiring _TraversalState into the extraction paths
from ._page import PageObject, _VirtualList
from ._page_labels import index2label as page_index2page_label
from ._utils import (
    _TraversalState,
    deprecation_with_replacement,
    logger_warning,
    parse_iso8824_date,
)

Detection Methods for CVE-2026-84311

Indicators of Compromise

  • Python worker processes running pypdf extraction consuming sustained high CPU on a single PDF for minutes or longer.
  • Rapid resident memory growth in processes invoking PageObject._extract_text or PageObject.extract_xform_text.
  • Repeated OOM-killer events or container restarts tied to document-processing services after ingesting untrusted PDFs.

Detection Strategies

  • Inventory Python environments for pypdf and flag any version below 6.16.1 using pip list or SBOM tooling.
  • Instrument extraction workers with per-file timeouts and log any PDF that exceeds a wall-clock or memory threshold.
  • Retain samples of PDFs that trigger timeouts for offline analysis of nested form XObject references.

Monitoring Recommendations

  • Alert on process-level CPU saturation and RSS growth in services that call pypdf on user-supplied documents.
  • Track queue depth and job duration percentiles for PDF processing pipelines; sudden tail-latency shifts can indicate abuse.
  • Correlate upload metadata (source IP, account, referrer) with jobs that hit resource limits to identify the submitter.

How to Mitigate CVE-2026-84311

Immediate Actions Required

  • Upgrade pypdf to version 6.16.1 or later in all environments that parse untrusted PDFs.
  • Enforce per-request CPU time and memory limits on workers that call extract_text or extract_xform_text.
  • Quarantine PDFs sourced from untrusted uploaders until the library is patched.

Patch Information

The fix is available in pypdf 6.16.1. Review the GitHub Security Advisory GHSA-763m-79hh-57f2, the pull request implementing the iteration limit, the patch commit, and the 6.16.1 release notes for full details.

Workarounds

  • Wrap extraction calls in a subprocess with hard RLIMIT_CPU and RLIMIT_AS limits so a runaway job cannot exhaust the host.
  • Reject PDFs that exceed a maximum file size or a maximum count of form XObject references before extraction.
  • Run PDF processing in isolated, ephemeral containers with strict cgroup CPU and memory caps.
bash
# Upgrade pypdf to the fixed release
pip install --upgrade 'pypdf>=6.16.1'

# 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.

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.