Skip to content

Security (1/5): FlateDecode/zlib limits — CVE-2025-55197, CVE-2026-27026, CVE-2026-41312#1

Open
icanhasmath wants to merge 2 commits into
1.28.6.xfrom
1.28.6-sec-filters-flate
Open

Security (1/5): FlateDecode/zlib limits — CVE-2025-55197, CVE-2026-27026, CVE-2026-41312#1
icanhasmath wants to merge 2 commits into
1.28.6.xfrom
1.28.6-sec-filters-flate

Conversation

@icanhasmath

Copy link
Copy Markdown
Collaborator

Part 1 of 5 of the PyPDF2 1.28.6 security backport (last Py2.7-compatible line), targeting 1.28.6.x. Scoped to PyPDF2/filters.py Flate/zlib paths.

CVE Sev Fix
CVE-2025-55197 Mod Cap FlateDecode output (75 MB) — zip-bomb
CVE-2026-27026 Mod Cap byte-by-byte zlib recovery input (5 MB)
CVE-2026-41312 Mod Cap PNG-predictor /Columns (250000)

Backported from upstream pypdf 6.0.0 / 6.7.1 / 6.10.2; adapted Py2.7-safe. Limits raise PdfReadError (upstream's LimitReachedError is avoided to keep these 5 PRs independent). New tests: Tests/test_security_flate.py (5). Validated under Python 2.7.18 — no new failures vs the pristine 1.28.6 baseline.

🤖 Generated with Claude Code

icanhasmath and others added 2 commits June 18, 2026 11:19
A crafted FlateDecode stream could exhaust memory (a small "zip bomb"
inflating to gigabytes — CVE-2025-55197) or, when malformed, pin the CPU
in the byte-by-byte zlib recovery fallback (CVE-2026-27026).

Rewrite `decompress()` to:
- cap decompressed output at ZLIB_MAX_OUTPUT_LENGTH (75 MB) using
  zlib.decompressobj().decompress(data, max_length) and checking
  unconsumed_tail (Py2.7-compatible), raising PdfReadError when exceeded;
- cap the malformed-stream recovery scan at ZLIB_MAX_RECOVERY_INPUT_LENGTH
  (5 MB) and also enforce the output cap there.

Mirrors upstream pypdf 6.0.0 (PR py-pdf#3430) and 6.7.1 (PR py-pdf#3644). Upstream
raises LimitReachedError; this backport reuses the existing PdfReadError
to avoid changing the public exception surface (for a memory/CPU bomb,
raising any exception defuses it).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A crafted FlateDecode stream with a PNG /Predictor and an enormous
/Columns value made the per-row prediction buffer (rowlength = columns
+ 1) allocate unbounded memory.

Reject /Columns greater than FLATE_MAX_COLUMNS (250000) with PdfReadError
before any per-row allocation. Mirrors upstream pypdf 6.10.2 (PR py-pdf#3734);
the upstream /Colors and /BitsPerComponent guards are N/A here because
1.28.x FlateDecode only uses /Columns for the row length.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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