Bump pypdf from 6.11.0 to 6.21.2
Updates pypdf from 6.11.0 to 6.21.2.
Fixes GHSA-6c7f-9265-g8fw and CVE-2026-115572 — a small PDF holds an API worker for over a minute: a 1,180,298-byte upload to the unauthenticated /general/v0/general route costs 69.9 s in the page-tree walk while the same bytes cost 0.025 s on the fixed release, and the route sets no request timeout and no upload size cap, so a few concurrent uploads deny service.
What this changes:
uv.lock—pypdfmoves from 6.11.0 to 6.21.2, with the sdist and wheel entries that release publishes; no other package or line changes
How to verify:
uv lock --check
uv sync --locked --no-dev --no-install-project && .venv/bin/python -c "import pypdf; print(pypdf.__version__)"
python3 -c "import pypdf; pypdf.PdfReader('poc_20k_1m.pdf').pages" # 69.92 s on 6.11.0, 0.025 s on 6.21.2
Why the API route is exposed
POST /general/v0/general (prepline_general/api/general.py:646-647) -> general_partition -> _check_pdf(file) at general.py:308 -> PdfReader(file) at general.py:494 -> list(pdf.pages) at general.py:503; the route needs no credentials and sets no request timeout.
Dockerfile:63-64 copies uv.lock and runs uv sync --no-dev --no-install-project --locked, so the API image runs exactly the pypdf version the lock pins, which is 6.11.0.
In 6.11.0 a missing object is cached as None but the cache lookup returns early only for a non-None hit (pypdf/_reader.py:447-451), so each of the 20,000 references re-copies and re-scans the whole stream (:558-570). 6.21.2 adds the resolved-objects membership test (_reader.py:552-557, PR #4240) and stops after the first miss.
Measured on one 1.2 MB PDF, same bytes both sides
| run | pypdf 6.11.0 | pypdf 6.21.2 |
|---|---|---|
PdfReader(...).pages, median of 3 | 69.92 s | 0.025 s |
POST /general/v0/general on loopback | 171.32 s (HTTP 200, body []) | 1.27 s (HTTP 200, body []) |
| same-size benign 1.2 MB PDF | 0.0006 s (library) / 0.219 s (served) | 0.185 s (served) |
Payload: 1,180,298 B, sha256 97d67e8d9d6eb9786cf6f7fcb08dcb05fc3cc31ace61c65780f812ef3236e132; its /Kids array names object 9999 20,000 times and object 9999 is never defined, so every reference is a cache miss. |
The patched lock was re-checked and installed with the repository's own uv 0.13.4 and its own build step before submission, and both pinned releases were re-run on the payload on this host.
Automated security patch from Superbot.