Skip to content

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

Merged
icanhasmath merged 2 commits into
1.28.6.xfrom
1.28.6-sec-filters-flate
Jun 23, 2026
Merged

Security (1/5): FlateDecode/zlib limits — CVE-2025-55197, CVE-2026-27026, CVE-2026-41312#1
icanhasmath merged 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>

@martinPavesio martinPavesio left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good!

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Backports upstream pypdf security hardening to the PyPDF2 1.28.6 (Py2.7) line by adding explicit limits around FlateDecode/zlib decompression to mitigate DoS vectors (zip-bomb output growth, unbounded recovery scanning, and excessive PNG predictor /Columns).

Changes:

  • Add module-level caps for FlateDecode output size, recovery-scan input size, and PNG predictor /Columns maximum.
  • Update decompress() to enforce output and recovery-scan limits and raise PdfReadError when exceeded.
  • Add regression tests covering the new limits and a basic roundtrip decode.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
PyPDF2/filters.py Implements Flate/zlib decompression and predictor parameter caps, raising PdfReadError on limit violations.
Tests/test_security_flate.py Adds regression tests for the decompression output cap, recovery input cap, and /Columns cap.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread PyPDF2/filters.py
Comment thread PyPDF2/filters.py
Comment thread PyPDF2/filters.py
@icanhasmath icanhasmath merged commit 9eb1b88 into 1.28.6.x Jun 23, 2026
1 check passed
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.

3 participants