Skip to content

Bump pypdf from 6.11.0 to 6.21.2 - #595

Open
superbot-helper wants to merge 1 commit into
Unstructured-IO:mainfrom
superbot-helper:security/bump-pypdf-6.21.2
Open

superbot-helper wants to merge 1 commit into
Unstructured-IO:mainfrom
superbot-helper:security/bump-pypdf-6.21.2

Conversation

@superbot-helper

@superbot-helper superbot-helper commented Oct 30, 2026 •

Copy link
Copy Markdown

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 — pypdf moves 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.

View guided diff

GHSA-6c7f-9265-g8fw (CVE-2026-115572): pypdf returns early from its object
cache only when the lookup is not None, and a missing object is cached as
None, so each reference to the same absent object re-copies and re-scans the
whole stream. A 1.2 MB PDF whose page tree references one never-defined object
20,000 times takes about 70 s in the page-tree walk on 6.11.0 and 0.025 s on
6.21.2.

The API image installs exactly this lock with
`uv sync --no-dev --no-install-project --locked`, and _check_pdf runs that
walk on every PDF upload to POST /general/v0/general before the route has any
chance to time out or reject the file. uv.lock only; no source changes.
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedpypi/​pypdf@​6.11.0 ⏵ 6.21.299100 +75100100100

View full report

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant