CVE-2026-119203: Infinite Loop in pypdf Standard Cross-Reference Table Parser
Vulnerability ID: CVE-2026-119203
CVSS Score: 7.1
Published: 2026-10-30
CVE-2026-119203 is a denial-of-service vulnerability affecting the pypdf library in versions prior to 6.21.4. The flaw occurs within the standard cross-reference (xref) table parsing routine when processing truncated or malformed PDF streams that terminate before a valid trailer dictionary is encountered. Because the parser attempts to rewind the stream pointer by a fixed offset whenever the trailer token is absent without verifying forward progress, hitting the end-of-file (EOF) or non-advancing tokens causes the parser to re-read the same byte offset indefinitely. An unauthenticated attacker can exploit this flaw by supplying a crafted PDF document to an application using pypdf, resulting in continuous CPU consumption and thread exhaustion.
TL;DR
Versions of the Python pypdf library prior to 6.21.4 contain an infinite loop vulnerability (CWE-835) in the _read_standard_xref_table method. Processing a malformed PDF with an incomplete cross-reference table that lacks a trailer causes the parser to repeatedly seek backward to the same byte position, hanging the executing thread and causing a denial of service.
⚠️ Exploit Status: POC
Technical Details
- Vulnerability ID: CVE-2026-119203 / GHSA-5849-834g-hvw5
- Weakness Class: CWE-835: Loop with Unreachable Exit Condition ('Infinite Loop')
- 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
- Affected Component: pypdf._reader.PdfReader._read_standard_xref_table (< 6.21.4)
- Patched Version: pypdf 6.21.4
- Primary Impact: Denial of Service via CPU and worker thread exhaustion
- EPSS Score: 0.30% (23.18th Percentile)
- CISA KEV Status: Not Listed
Affected Systems
- pypdf (PyPI package) < 6.21.4
-
pypdf: < 6.21.4 (Fixed in:
6.21.4)
Code Analysis
Commit: 06593f9
SEC: Detect EOF when reading standard xref table trailer (#4289)
File: pypdf/_reader.py
@@ -1072,6 +1072,7 @@ def _read_standard_xref_table(self, stream: StreamType) -> None:
stream.seek(-1, 1)
first_time = True # check if the first time looking at the xref table
recovery_cache: Optional[dict[int, tuple[int, int]]] = None
+ previous_position: Optional[int] = None
while True:
num = cast(int, read_object(stream, self))
if first_time and num != 0:
@@ -1186,12 +1187,20 @@ def _read_standard_xref_table(self, stream: StreamType) -> None:
stream.seek(-1, 1)
stream.seek(-1, 1)
trailer_tag = stream.read(7)
- if trailer_tag != b"trailer":
- # more xrefs!
- stream.seek(-7, 1)
- else:
+ if trailer_tag == b"trailer":
break
+ # More xrefs should move the parser to another section.
+ stream.seek(-7, 1)
+
+ # Detect a repeated read at the same position.
+ rewound_position = stream.tell()
+ if rewound_position == previous_position:
+ raise PdfReadError(
+ f"Xref parsing stuck at position {rewound_position}: {trailer_tag!r}"
+ )
+ previous_position = rewound_position
+
def _read_xref_tables_and_trailers(
self, stream: StreamType, startxref: Optional[int], xref_issue_nr: int
) -> None:
Exploit Details
- GitHub: Official regression test case in the security fix commit demonstrating a 40-byte PDF stream that triggers the infinite loop in pypdf < 6.21.4.
Mitigation Strategies
- Upgrade the pypdf package to version 6.21.4 or later across all environments processing PDF documents.
- Isolate untrusted PDF parsing tasks in dedicated subprocesses or task queues with strict CPU and wall-clock execution timeouts.
- Implement exception handling for pypdf.errors.PdfReadError to gracefully reject malformed or truncated PDF uploads.
Remediation Steps:
- Audit application dependencies (requirements.txt, pyproject.toml, poetry.lock, Pipfile.lock) to identify any installations of pypdf prior to version 6.21.4.
- Run
pip install --upgrade "pypdf>=6.21.4"to install the patched release. - Verify that application error handlers catch
pypdf.errors.PdfReadErrorwhen opening untrusted streams withPdfReader. - Configure process supervisors (e.g., Gunicorn
--timeout, Celery--time-limit, or container health checks) to terminate hung worker processes.
References
- GitHub Security Advisory GHSA-5849-834g-hvw5
- Pull Request #4289: SEC: Detect EOF when reading standard xref table trailer
- Official Security Fix Commit (06593f993789a4b573dd955730c1a7051128bb2a)
- pypdf Release 6.21.4
- CVE.org Record: CVE-2026-119203
- NVD Vulnerability Detail: CVE-2026-119203
- cvelistV5 JSON Entry for CVE-2026-119203
Read the full report for CVE-2026-119203 on our website for more details including interactive diagrams and full exploit analysis.
Top comments (0)