CVE-2026-84309 Overview
CVE-2026-84309 is an infinite loop vulnerability [CWE-835] in pypdf, a free and open-source pure-Python PDF library. Versions prior to 6.16.0 fail to detect cycles when traversing PDF tree structures during write operations. An attacker can craft a PDF containing a cyclic tree whose /Next links reference each other, causing TreeObject.insert_child in pypdf/generic/_data_structures.py to loop indefinitely. The condition triggers a denial-of-service against any application that writes children into a tree derived from attacker-controlled input. The maintainers fixed the issue in pypdf version 6.16.0.
Critical Impact
A malicious PDF processed by a write code path in pypdf causes an infinite loop, exhausting CPU and hanging the host application.
Affected Products
- pypdf versions prior to 6.16.0
- Python applications and services that ingest untrusted PDFs and invoke tree-writing operations
- Downstream tools and pipelines bundling vulnerable pypdf releases
Discovery Timeline
- 2026-09-01 - CVE-2026-84309 published to the National Vulnerability Database (NVD)
- 2026-09-02 - Last updated in NVD database
Technical Details for CVE-2026-84309
Vulnerability Analysis
The defect resides in TreeObject.insert_child inside pypdf/generic/_data_structures.py. The function walks a singly linked list of sibling nodes by following /Next references, expecting the chain to terminate at a node without a /Next entry. When the input PDF is crafted so that a /Next link eventually points back to a previously visited node, the traversal never reaches a terminator. The loop continues forever, consuming a CPU core and preventing the host process from completing the write operation or serving other requests.
Root Cause
The pre-patch code assumed acyclic tree structures and did not track visited nodes during traversal. Because PDF documents can supply arbitrary object graphs, this assumption is violated whenever a malicious writer references an ancestor through /Next. The absence of a visited-set check corresponds to CWE-835 (Loop with Unreachable Exit Condition).
Attack Vector
Exploitation requires the target application to open an attacker-supplied PDF and reach a write path that inserts a child into a tree derived from the document. The attack is local in CVSS terms and requires no privileges or user interaction beyond processing the file. Impact is limited to availability; confidentiality and integrity are not affected. Common scenarios include PDF conversion services, batch document processors, and archival pipelines that merge or annotate user-submitted files.
# Patch excerpt: cycle detection added to TreeObject.insert_child
# in pypdf/generic/_data_structures.py
return child_reference
prev = cast("DictionaryObject", self["/Last"])
visited: set[int] = set()
while prev.indirect_reference != before:
prev_id = id(prev)
if prev_id in visited:
raise LimitReachedError("Detected cycle in tree structure.")
visited.add(prev_id)
if "/Next" in prev:
prev = cast("TreeObject", prev["/Next"])
continue
# append at the end
prev[NameObject("/Next")] = cast("TreeObject", child_reference)
child_obj[NameObject("/Prev")] = prev.indirect_reference
child_obj[NameObject("/Parent")] = self.indirect_reference
if "/Next" in child_obj:
del child_obj["/Next"]
self[NameObject("/Last")] = child_reference
inc_parent_counter(self, child_obj.get("/Count", 1))
Source: pypdf commit c9ba557. The fix records the Python id() of each visited node in a visited set and raises LimitReachedError when a repeat is detected.
Detection Methods for CVE-2026-84309
Indicators of Compromise
- Python worker processes pinned at 100% CPU while parsing or writing a PDF with pypdf.
- Long-running or hanging jobs in PDF ingestion pipelines that never emit output or errors.
- PDF files whose outline, structure, or name trees contain /Next references pointing to earlier siblings or ancestors.
Detection Strategies
- Inventory application dependencies to identify installations of pypdf earlier than 6.16.0.
- Add process-level timeouts and CPU quotas around PDF write operations so runaway loops surface as failed jobs.
- Parse suspect PDFs offline with cycle-aware tooling to flag structural anomalies before submission to production processors.
Monitoring Recommendations
- Alert on Python processes exceeding CPU or wall-clock thresholds during document processing.
- Log the file hash, submitter, and size of PDFs that trigger job timeouts to support incident review.
- Track pypdf version telemetry across build artifacts and container images to confirm patched versions in production.
How to Mitigate CVE-2026-84309
Immediate Actions Required
- Upgrade pypdf to version 6.16.0 or later across all applications, containers, and virtual environments.
- Rebuild and redeploy container images that pin an older pypdf release.
- Enforce timeouts on PDF processing workers to bound the impact of any residual denial-of-service condition.
Patch Information
The fix is available in pypdf release 6.16.0 and merged via pull request #3964. Additional context is provided in GitHub Security Advisory GHSA-jp53-mhqp-8xcg.
Workarounds
- Isolate PDF write operations in short-lived worker processes with strict CPU and wall-clock limits.
- Reject or quarantine PDFs from untrusted sources until the library is upgraded.
- Avoid invoking TreeObject.insert_child on structures derived from user-supplied PDFs on unpatched systems.
# Upgrade pypdf to the patched release
pip install --upgrade 'pypdf>=6.16.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.

