Dev.to Security 🔐 Cybersecurity 👁 0 📖 3 min read

CVE-2026-119205: CVE-2026-119205: Denial of Service via Infinite Loop in pypdf DictionaryObject Cloning

CVE-2026-119205: Denial of Service via Infinite Loop in pypdf DictionaryObject Cloning Vulnerability ID: CVE-2026-119205 CVSS Score: 7.1 Published: 2026-10-30 CVE-2026-119205 (GHSA-mfr5-77xh-9j7h) is a Denial of Ser

CVE-2026-119205: Denial of Service via Infinite Loop in pypdf DictionaryObject Cloning

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

CVE-2026-119205 (GHSA-mfr5-77xh-9j7h) is a Denial of Service (DoS) vulnerability in pypdf prior to version 6.21.4. The flaw occurs during the cloning or duplication of nested PDF dictionary structures. Because the cycle-detection algorithm within DictionaryObject._clone() tracked generated destination object references rather than the original source indirect references, cyclic reference graphs in source PDFs evaded detection, resulting in an infinite loop and CPU exhaustion.

TL;DR

Versions of pypdf prior to 6.21.4 contain a logic error in cycle detection during DictionaryObject cloning (CWE-835). Processing a crafted PDF containing cyclic indirect dictionary references triggers an infinite loop, leading to application hangs and CPU exhaustion. Upgrade to pypdf 6.21.4 or later.

⚠️ Exploit Status: POC

Technical Details

  • Vulnerability Type: Infinite Loop / Denial of Service (CWE-835)
  • Affected Component: pypdf/generic/_data_structures.py (DictionaryObject._clone)
  • Attack Vector: Network (Crafted PDF Document)
  • CVSS v4.0 Score: 7.1 High
  • EPSS Score: 0.30% (23.18th Percentile)
  • Impact: Application Hang & 100% CPU Utilization
  • Exploit Status: Proof-of-Concept (Unit Test)
  • Fixed Version: pypdf 6.21.4

Affected Systems

  • py-pdf pypdf (< 6.21.4)
  • pypdf: < 6.21.4 (Fixed in: 6.21.4)

Code Analysis

Commit: f176db1

SEC: Fix loop detection when cloning DictionaryObject (#4288)

diff --git a/pypdf/generic/_data_structures.py b/pypdf/generic/_data_structures.py
index a1b2c3d..e4f5g6h 100644
--- a/pypdf/generic/_data_structures.py
+++ b/pypdf/generic/_data_structures.py
@@ -419,20 +419,21 @@ def _clone(
                         )
                         prev_obj: Optional[DictionaryObject] = self
                         while cur_obj is not None:
+                            source_reference = cur_obj.indirect_reference
                             clon = cast(
                                 "DictionaryObject",
                                 cur_obj._reference_clone(
                                     cur_obj.__class__(), pdf_dest, force_duplicate
                                 ),
                             )
                             # Check to see if we've previously processed our item
-                            if clon.indirect_reference is not None:
-                                idnum = clon.indirect_reference.idnum
-                                generation = clon.indirect_reference.generation
-                                if (idnum, generation) in visited:
+                            if source_reference is not None:
+                                source_idnum = source_reference.idnum
+                                source_generation = source_reference.generation
+                                if (source_idnum, source_generation) in visited:
                                     cur_obj = None
                                     break
-                                visited.add((idnum, generation))
+                                visited.add((source_idnum, source_generation))
                             objs.append((cur_obj, clon))
                             assert prev_obj is not None
                             prev_obj[NameObject(k)] = clon.indirect_reference

Exploit Details

  • GitHub: Official unit test (test_dictionary_object_clone_cycle_detection) demonstrating a minimal PDF with cyclic /N references that reproduces the infinite loop.

Mitigation Strategies

  • Upgrade pypdf to version 6.21.4 or later to ensure cycle detection evaluates source indirect references.
  • Isolate PDF parsing and cloning operations in separate worker processes enforced with strict wall-clock and CPU execution timeouts.
  • Enforce memory and CPU resource quotas at the OS or container level to prevent runaway loops from starving co-located services.

Remediation Steps:

  1. Audit application dependencies (requirements.txt, pyproject.toml, Pipfile.lock, or poetry.lock) to identify installations of pypdf prior to 6.21.4.
  2. Update pypdf by running: pip install --upgrade 'pypdf>=6.21.4'.
  3. Verify the installed version in your deployment environment using: python3 -c 'import pypdf; print(pypdf.version)'.
  4. Configure task queues (such as Celery) or process pools running PDF operations to enforce hard execution timeouts (e.g., 30 seconds per document).

References

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

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.