Skip to content

fix: raise the pypdf and urllib3 security floors - #191

Merged
nelsonduarte merged 1 commit into
mainfrom
fix/pypdf-floor-6.19
Oct 5, 2026
Merged

nelsonduarte merged 1 commit into
mainfrom
fix/pypdf-floor-6.19

Conversation

@nelsonduarte

Copy link
Copy Markdown
Owner

What changes

  • requirements.txt: the pypdf floor moves from >=6.16.2 to >=6.19.0, and the urllib3 floor from >=2.7.0 to >=2.8.0. The comments above both entries are rewritten (see below).
  • flatpak/requirements-pinned.txt: the Flatpak pin moves from pypdf==6.16.2 to pypdf==6.19.0.
  • flatpak/python-modules.yml: the pypdf wheel URL and sha256 are updated to match the 6.19.0 pin.
  • tests/test_dependency_security_floors.py (new): fails when a requirements.txt floor for pypdf, cryptography, urllib3, lxml or idna admits a release below the first one clear of every advisory OSV listed on 2026-10-05, or admits a release listed as affected. It also rejects a floor conditioned by an environment marker, since pip skips that line wherever the marker is false.

Why

pypdf. Releases 6.16.2 through 6.18.1 carry some or all of PYSEC-2026-4153 to PYSEC-2026-4160, all memory or runtime exhaustion on crafted PDFs. 6.19.0 is the first release clear of all eight (and of the six earlier advisories the old floor already covered).

This is not theoretical for shipped builds. Builds resolve dependencies at build time, and build.yml installed pypdf 6.18.1 for every v1.15.0 binary (run 34720950897), which still carries three of these advisories.

PYSEC-2026-4157 is reachable from the app. The editor's form tab sends every field back through PdfWriter.update_page_form_field_values (app/editor/tab.py:1399) with auto_regenerate=True and flatten=False. That path still regenerates the appearance stream of /Tx and /Ch fields, although the advisory says it "requires updating form field values with flattening enabled". Measured: a 1.4 MB PDF whose multiline /Tx value has 100,000 lines held the GUI thread for 51 s on 6.18.1 against 1.5 s on 6.19.0, and the cost grows quadratically with the line count. PYSEC-2026-4159 and PYSEC-2026-4160 are not reachable: app/ never calls PdfReader.page_labels or .attachments, the only entry points to the fixed code.

Why the audit did not catch the floor. pip-audit -r requirements.txt audits the newest release that satisfies >=, not the floor itself. A floor that admits vulnerable releases therefore audits clean for as long as a fixed release exists. The new test closes that blind spot for the five packages it covers.

urllib3. PYSEC-2026-4175, PYSEC-2026-4176 and PYSEC-2026-4177 (published 2026-10-01) all affect 2.7.0 and are fixed in 2.8.0. The Flatpak build does not install urllib3.

The old comments called urllib3 a transitive dependency of cryptography and requests, and idna one of urllib3 and requests. In a venv installed from requirements.txt alone, pip show reports an empty Required-by for both, urllib3 does not depend on idna, and app/ imports neither. Only requests, pulled in by pip-audit from requirements-dev.txt, depends on them. The comments now say so.

Fixes the red scheduled security-deps run on main

The scheduled security-deps.yml run on main (run 37313643981, 2026-10-05) failed its strict gate on the Flatpak pin pypdf==6.16.2, with eight findings. This PR moves that pin to 6.19.0 and should turn the gate green. The requirements.txt half of the same gate passed on that run, for the reason described above.

Limits of the new test

Left open (not in this PR)

  • Whether urllib3 and idna should move from requirements.txt to requirements-dev.txt, given that only a dev dependency needs them.

🤖 Generated with Claude Code

pypdf 6.16.2 through 6.18.1 carry some or all of PYSEC-2026-4153 to
4160, all memory or runtime exhaustion on crafted PDFs; 6.19.0 is the
first release clear of all eight. The requirements.txt floor moves from
6.16.2 to 6.19.0, and so does the Flatpak pin (requirements-pinned.txt
plus the wheel URL and sha256 in python-modules.yml).

The scheduled security-deps.yml run on main (run 37313643981,
2026-10-05) failed its strict gate on the Flatpak pin pypdf==6.16.2,
with eight findings; this commit fixes it. The requirements.txt half of
that gate passed on the same run although its floor admitted every
affected release: "pip-audit -r" audits the newest release that
satisfies ">=", not the floor. The floor still matters because builds
resolve at build time: build.yml installed pypdf 6.18.1 for every
v1.15.0 binary (run 34720950897).

PYSEC-2026-4157 is reachable from the app: the editor's form tab sends
every field back through PdfWriter.update_page_form_field_values
(app/editor/tab.py:1399) with auto_regenerate=True and flatten=False,
which still regenerates the appearance stream of /Tx and /Ch fields,
although the advisory says it "requires updating form field values with
flattening enabled". A 1.4 MB PDF whose multiline /Tx value has 100,000
lines held the GUI thread for 51 s on 6.18.1 against 1.5 s on 6.19.0;
the cost grows quadratically with the line count. 4159 and 4160 are not
reachable: app/ never calls PdfReader.page_labels or .attachments, the
only entry points to the fixed code.

The urllib3 floor moves from 2.7.0 to 2.8.0 for PYSEC-2026-4175 / 4176 /
4177 (published 2026-10-01, all affecting 2.7.0). The Flatpak build does
not install urllib3. The requirements.txt comments called urllib3 a
transitive dependency of cryptography and requests, and idna one of
urllib3 and requests. In a venv installed from requirements.txt alone,
pip show reports an empty Required-by for both, urllib3 does not depend
on idna, and app/ imports neither; only requests, pulled in by pip-audit
from requirements-dev.txt, depends on them. The comments now say so.
Whether the two entries belong in requirements-dev.txt is left open.

tests/test_dependency_security_floors.py fails when a requirements.txt
floor for pypdf, cryptography, urllib3, lxml or idna admits a release
below the first one clear of every advisory OSV listed on 2026-10-05,
or admits a release listed as affected. It also rejects a floor
conditioned by an environment marker, since pip skips that line
wherever the marker is false. It only knows the advisories it lists,
and as of 2026-10-05 no workflow on main runs pytest.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 5, 2026

Copy link
Copy Markdown
Contributor

Python dependencies security check

pip-audit: requirements.txt

No known vulnerabilities.

pip-audit: flatpak/requirements-pinned.txt

No known vulnerabilities.

Outdated check (informational)

Package Pin Latest on PyPI Status
PySide6 PySide6>=6.11.1 6.11.2 outdated
pypdf pypdf>=6.19.0 6.19.0 up-to-date
cryptography cryptography>=50.0.1 50.0.2 outdated
qtawesome qtawesome>=1.4.2 1.4.2 up-to-date
pillow pillow>=12.3.0 12.3.0 up-to-date
pymupdf pymupdf>=1.28.0 1.28.2 outdated
pytesseract pytesseract>=0.3.13 0.3.13 up-to-date
python-docx python-docx>=1.2.0 1.2.0 up-to-date
python-pptx python-pptx>=1.0.2 1.0.2 up-to-date
openpyxl openpyxl>=3.1.5 3.1.5 up-to-date
beautifulsoup4 beautifulsoup4>=4.15.0 4.15.0 up-to-date
ebooklib ebooklib>=0.20 0.20 up-to-date
lxml lxml>=6.1.1 6.1.3 outdated
urllib3 urllib3>=2.8.0 2.8.0 up-to-date
idna idna>=3.18 3.20 outdated
pyinstaller pyinstaller>=6.21.0 6.22.3 outdated

Auto-generated by security-deps workflow. Merge is blocked only when pip-audit --strict reports vulnerabilities.

@nelsonduarte
nelsonduarte merged commit eba6961 into main Oct 5, 2026
5 checks 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.

1 participant