CVE-2026-119206: Algorithmic Complexity Denial of Service in pypdf Page Label Resolution

Vulnerability ID: CVE-2026-119206
CVSS Score: 7.1
Published: 2026-10-30

CVE-2026-119206 is an algorithmic complexity vulnerability in pypdf prior to version 6.21.3 that causes uncontrolled CPU resource consumption when evaluating the page_labels property. Due to repeated linear scans of the PDF catalog's /PageLabels number tree from index zero for each individual page, processing a document with a large number of pages and label ranges scales quadratically. An unauthenticated attacker can supply a crafted PDF document to an application that reads page labels, resulting in prolonged execution times and denial of service.

TL;DR

pypdf versions prior to 6.21.3 resolve PDF page labels in quadratic O(pages * ranges) time by restarting the /Nums array scan from index 0 for every page. Supplying a crafted PDF with thousands of pages and page label ranges triggers excessive CPU consumption and application hangs when the .page_labels property is accessed.

⚠️ Exploit Status: POC

Technical Details

  • Vulnerability Type: Algorithmic Complexity Denial of Service (CWE-400)
  • Affected Component: pypdf (pypdf._doc_common.page_labels / pypdf._page_labels)
  • Attack Vector: Network (Crafted PDF document)
  • CVSS v4.0 Score: 7.1 High (CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N)
  • EPSS Score: 0.30% (23.18th Percentile)
  • Impact: High Availability Loss (Quadratic O(P * M) CPU Exhaustion)
  • Patched Version: pypdf 6.21.3
  • CISA KEV Status: Not Listed

Affected Systems

  • pypdf
  • pypdf: < 6.21.3 (Fixed in: 6.21.3)

Code Analysis

Commit: b891fef

Implement single-pass index2labels traversal for flat /Nums arrays in /PageLabels (PR #4251)

--- a/pypdf/_doc_common.py +++ b/pypdf/_doc_common.py @@ -44,7 +44,7 @@ from ._configuration import get_configuration from ._encryption import Encryption from ._page import PageObject, _VirtualList -from ._page_labels import index2label as page_index2page_label +from ._page_labels import index2labels  from ._utils import ( _TraversalState, deprecate_no_replacement, @@ -1295,7 +1295,7 @@ def page_labels(self) -> list[str]: This property is read-only. The labels are in the order that the pages appear in the document. """ - return [page_index2page_label(self, i) for i in range(len(self.pages))] + return index2labels(self, len(self.pages)) 

Mitigation Strategies

  • Upgrade pypdf to version 6.21.3 or higher to enable single-pass O(P + M) traversal for flat /Nums arrays.
  • Enforce execution timeouts and process isolation when parsing metadata from untrusted PDF documents.
  • Validate and bound the number of pages and /PageLabels /Nums entries before accessing the reader.page_labels property.
  • Avoid materializing the full reader.page_labels list if only a subset of page labels is needed by the application.

Remediation Steps:

  1. Audit project dependencies (requirements.txt, pyproject.toml, Pipfile.lock, or poetry.lock) to identify pypdf versions below 6.21.3.
  2. Run pip install --upgrade "pypdf>=6.21.3" across affected environments and rebuild deployment artifacts.
  3. If using untrusted PDF inputs in web workers, implement a pre-check on reader.root_object.get('/PageLabels') to reject documents with excessive /Nums lengths or indirect value references.
  4. Configure WSGI/ASGI worker timeouts (e.g., Gunicorn --timeout) to terminate hung worker processes if anomalous CPU consumption occurs.

References

Read the full report for CVE-2026-119206 on our website for more details including interactive diagrams and full exploit analysis.