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-113789

CVE-2026-113789: Algorithmic Complexity and Resource Exhaustion in pypdf Interactive Form Parsing

Alon Barad
Alon Barad
Software Engineer

Oct 23, 2026·5 min read·3 visits

Executive Summary (TL;DR)

pypdf prior to version 6.21.0 suffers from quadratic O(N^2) complexity in form field cycle detection and lacks traversal depth limits, enabling denial-of-service via malformed PDFs.

An uncontrolled resource consumption and inefficient algorithmic complexity vulnerability in pypdf prior to version 6.21.0 allows remote attackers to trigger application-level denial-of-service (DoS) via crafted PDF form field hierarchies.

Vulnerability Overview

The Python library pypdf (formerly PyPDF2) is an open-source tool widely utilized for extracting text, merging pages, and parsing document structures from PDF files. Within its interactive form field processing module, pypdf provides methods such as get_fields(), _build_field(), and _check_kids() to traverse hierarchical field structures and extract form field metadata.

When processing untrusted PDF documents containing complex or synthetic interactive form fields (/AcroForm and /Fields trees), versions of pypdf prior to 6.21.0 exhibit critical efficiency bottlenecks. Specifically, cycle detection during recursive tree traversal was implemented using sequential array lookups over a growing list of traversed nodes, leading to quadratic time complexity ($O(N^2)$).

In addition to the time complexity flaw, the parser lacked upper boundaries for recursion depth and total processed form field entries. Consequently, an unauthenticated attacker capable of submitting a tailored PDF file to a service using pypdf can cause severe CPU starvation and memory exhaustion, resulting in thread blockages or process failure.

Root Cause Analysis

The root cause of CVE-2026-113789 consists of two interrelated defects located in pypdf/_doc_common.py: linear cycle detection lookup (CWE-407) and missing input structural boundaries (CWE-400).

During recursive traversal of field hierarchies, child objects referenced in /Kids arrays are checked for cyclical references to prevent infinite recursive loops. In affected versions, this check relied on a Python list passed via the stack parameter:

if tree in stack:
    return
stack.append(tree)

In Python, evaluating tree in stack on a list object forces a linear scan ($O(N)$) through every previously visited node. As the total number of field nodes $N$ increases (for instance, in PDFs containing 20,000 or more widget annotations), each node lookup takes time proportional to $N$. The cumulative complexity of traversing the tree scales quadratically ($O(N^2)$), consuming CPU time exponentially relative to element count.

Furthermore, the parser contained no guardrails regarding maximum traversal depth or total total node counts. Because PDF object dictionaries can contain deeply nested child references, an attacker can construct a tree structure that consumes hundreds of megabytes of memory and holds CPU execution in tight loop iterations for tens of seconds per document.

Code Analysis & Patch Inspection

The vulnerability was remediated in commit 5ef728f0e16d225c853e89f861ba0a67402fe3f2 (PR #4219) and released in pypdf version 6.21.0.

The fix introduces two major modifications: converting the identity tracking structure to an $O(1)$ hash set and establishing runtime execution limits in Configuration (pypdf/_configuration.py).

# File: pypdf/_configuration.py
@@ -106,6 +106,11 @@ class Configuration:
     page_tree_maximum_depth: int = 100
     """The maximum allowed depth of the page tree."""
 
+    form_fields_maximum_entries: int = 100_000
+    """The maximum allowed number of form fields."""
+    form_fields_maximum_depth: int = 100
+    """The maximum allowed depth for form fields."""
+
     xform_maximum_invocations_per_extraction: int = 5_000

In pypdf/_doc_common.py, the cycle detection algorithm was rewritten to use Python object memory identifiers (id(tree)) stored within a hash set visited: set[int]:

# File: pypdf/_doc_common.py
@@ -789,17 +828,26 @@ def _check_kids(
         visited: set[int],
         depth: int,
         traversal_state: _TraversalState,
     ) -> None:
-        if tree in stack:
+        tree_id = id(tree)
+        if tree_id in visited:
             logger_warning(
                 "%(field_name)s already parsed",
                 source=__name__,
                 field_name=self._get_qualified_field_name(parent=tree),
             )
             return
-        stack.append(tree)
+        visited.add(tree_id)

By replacing tree in stack (list membership, $O(N)$) with tree_id in visited (set hash lookup, $O(1)$), average iteration complexity drops from $O(N^2)$ to linear $O(N)$. Furthermore, traversal functions now evaluate _depth and _traversal_state.entry_count against configurable limits, throwing LimitReachedError when boundaries are breached.

Exploitation Mechanics

Exploitation of CVE-2026-113789 relies on delivery of a specially crafted PDF document to any application endpoint that automatically calls reader.get_fields() or writer.get_fields() on uploaded or ingested files.

The attack vector requires no authentication or user privilege on the target platform. The payload structure consists of a standard PDF document header containing a valid interactive form dictionary (/AcroForm) with an extensive /Fields array or deeply chained child dictionaries (/Kids).

When get_fields() processes a synthetic PDF file containing 30,000 dummy form fields, an unpatched system spends seconds in loop operations performing identity comparisons. Multiple concurrent uploads of such files will rapidly deplete worker process pools in web applications (such as Gunicorn or Uvicorn workers), causing full HTTP service unresponsiveness.

Impact Assessment & Security Risk

The primary impact of CVE-2026-113789 is high availability impairment (Denial of Service). The vulnerability has no impact on system confidentiality or data integrity.

According to CVSS v4.0 metrics, the issue receives a base score of 6.0 (CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N). The requirement metric AT:P reflects the necessity of triggering form field extraction methods specifically within downstream application logic.

Systems most exposed to this vulnerability include centralized document processing platforms, automated invoice parser services, cloud storage indexing agents, and compliance screening gateways that automatically analyze incoming PDF uploads. Because processing occurs synchronously on service worker threads, triggering the bug can easily result in complete service outage across multi-tenant environments.

Remediation & Mitigation Guidance

To fully remediate CVE-2026-113789, organizations must update pypdf to version 6.21.0 or later.

pip install --upgrade "pypdf>=6.21.0"

In environments handling high-risk untrusted documents where immediate package upgrades are delayed, applications can enforce strict runtime limits using the newly exposed apply_configuration context manager:

from pypdf import PdfReader, apply_configuration
from pypdf.errors import LimitReachedError
 
reader = PdfReader("untrusted_input.pdf")
 
try:
    with apply_configuration(form_fields_maximum_entries=5000, form_fields_maximum_depth=20):
        fields = reader.get_fields()
except LimitReachedError as err:
    # Gracefully reject malicious or over-complex PDF files
    logger.warning(f"Rejected complex PDF form structure: {err}")

Additionally, applications parsing user-provided PDF files should wrap PDF extraction tasks in isolated worker subprocesses with strict timeout mechanisms and memory ceilings using system-level tools (e.g., cgroups or systemd resource limits).

Official Patches

pypdf (GitHub)Pull Request #4219: Fix performance and recursion boundaries in form field parsing
pypdf (GitHub Release)Release tag for pypdf version 6.21.0

Technical Appendix

CVSS Score
6.0/ 10
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:P/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
EPSS Probability
0.32%
Top 77% most exploited

Affected Systems

pypdf prior to 6.21.0Python applications calling get_fields() on untrusted PDF filesAutomated PDF document processing pipelines
AttributeDetail
CWE IDCWE-400 / CWE-407
Attack VectorNetwork (Unauthenticated PDF Submission)
CVSS v4.0 Score6.0 (Medium)
EPSS Score0.00317 (23.44th percentile)
ImpactDenial of Service (CPU & Memory Exhaustion)
Exploit StatusNo public weaponized exploit detected
CISA KEV StatusNot listed
CWE-400
Uncontrolled Resource Consumption

Vulnerability Timeline

Fix commit merged in py-pdf/pypdf repository via PR #4219
2026-10-16
GitHub Advisory GHSA-6vvc-x485-93v7 published and CVE-2026-113789 assigned
2026-10-21
pypdf version 6.21.0 published on PyPI containing security patch
2026-10-21

References & Sources

  • [1]GitHub Security Advisory GHSA-6vvc-x485-93v7
  • [2]Fix Commit 5ef728f0e16d225c853e89f861ba0a67402fe3f2
  • [3]NVD Vulnerability Details CVE-2026-113789
Related Vulnerabilities
CVE-2023-36464

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 1 hour ago•CVE-2026-114131
6.5

CVE-2026-114131: Nuxt Route Rules appMiddleware Bypass via Percent-Encoded Route Segments

Nuxt versions 3.11.0 through 3.21.3 and 4.0.0 through 4.4.3 contain an interpretation conflict between the route rules matching engine and the core page routing mechanism. By submitting percent-encoded request path segments, unauthenticated attackers can bypass route rules, including appMiddleware authorization guards, and access rendered server-side page payloads.

Amit Schendel
Amit Schendel
3 views•5 min read
•about 2 hours ago•CVE-2026-114130
2.3

CVE-2026-114130: Cross-Site Scripting via ASCII Control Characters in Nuxt Fallback Router

A Cross-Site Scripting (XSS) vulnerability exists in Nuxt when configured with pages disabled (pages: false). ASCII C0 control characters prefixing javascript: URIs bypass internal protocol classification in the fallback router, allowing unauthenticated attackers to execute arbitrary script in the victim's origin context upon user interaction.

Alon Barad
Alon Barad
4 views•5 min read
•about 3 hours ago•CVE-2026-114133
5.4

CVE-2026-114133: Stored Cross-Site Scripting via useHeadSafe in Nuxt Server Islands

A Stored Cross-Site Scripting (XSS) vulnerability exists in Nuxt Server Island rendering logic when utilizing the useHeadSafe composable. Raw head attributes bypass sanitization during island serialization.

Amit Schendel
Amit Schendel
2 views•4 min read
•about 4 hours ago•CVE-2026-114132
6.3

CVE-2026-114132: Case-Sensitivity Route Rule Bypass in Nuxt Framework

Nuxt versions prior to 4.6.2 suffer from a route rule bypass vulnerability caused by an architectural mismatch in case-sensitivity handling between the Nitro server runtime and the Vue page router. An unauthenticated remote attacker can bypass server-enforced route directives—such as redirects, security headers, and SSR controls—by altering character casing in HTTP request paths.

Amit Schendel
Amit Schendel
4 views•6 min read
•about 5 hours ago•GHSA-78G4-XQWV-Q3G8
7.5

GHSA-78G4-XQWV-Q3G8: Heap-Based Buffer Overflow in Pillow (libopenjp2)

A heap-based buffer overflow vulnerability in Pillow PyPI binary wheels (versions 11.1.0 to 12.x) allows remote code execution or application crash via crafted JPEG 2000 files processed by the bundled libopenjp2 library.

Alon Barad
Alon Barad
17 views•4 min read
•about 6 hours ago•CVE-2026-109618
9.8

CVE-2026-109618: Remote Code Execution in PHP Core via Out-of-Memory longjmp() Uninitialized Memory Access

CVE-2026-109618 (dubbed PHP2Shell) is a critical vulnerability in the PHP engine core resulting from improper out-of-memory exception handling via longjmp(). When request allocation fails mid-processing, non-local control flow bypasses cleanup procedures, leaving memory structures uninitialized or in a use-after-free state during request shutdown.

Amit Schendel
Amit Schendel
11 views•5 min read