Skip to content

deps: add a soupsieve>=2.9 security floor - #208

Merged
nelsonduarte merged 1 commit into
mainfrom
deps/soupsieve-floor
Oct 16, 2026
Merged

nelsonduarte merged 1 commit into
mainfrom
deps/soupsieve-floor

Conversation

@nelsonduarte

Copy link
Copy Markdown
Owner

Why

soupsieve 2.8.4 has PYSEC-2026-4170 and PYSEC-2026-4171 (ReDoS in the selector parser), fixed in 2.9. 2.8.3 also has PYSEC-2026-3071 and PYSEC-2026-3072, fixed in 2.8.4.

soupsieve is a transitive of beautifulsoup4, which only asks for soupsieve>=1.6.1. Without a line of its own in requirements.txt, pip does not upgrade it in an existing venv unless run with --upgrade --upgrade-strategy eager (table below), and PyInstaller bundles it.

Why not 3.x

Every soupsieve 3.x requires Python >= 3.11. Requires-Python on PyPI, measured on 2026-10-16:

soupsieve Requires-Python Note
2.9 >=3.10
2.10 >=3.10 last release that installs on 3.10
3.0 >=3.11 yanked
3.0.1 >=3.11 yanked
3.0.2 >=3.11.5
3.0.3 >=3.11.5

Two builds install requirements.txt on Python 3.10: the appimage job in build.yml (ubuntu-22.04, Python 3.10), which the release job needs, and the snap (core22, Python 3.10).

Measured with a real Python 3.10.9: soupsieve>=2.9 resolves to 2.10, and soupsieve>=3.0.3 gives "No matching distribution".

A Dependabot PR raising this to >=3.0.3 will go red on test_soupsieve_py310.py; close it by hand while the AppImage/snap build on Python 3.10.

Changes

  • requirements.txt: soupsieve>=2.9, with a comment covering the advisories, the Python 3.10 ceiling and when to lift it.
  • tests/test_soupsieve_py310.py (new): fails if the soupsieve line stops admitting 2.10 or gains an environment marker.
  • tests/test_dependency_security_floors.py: new SECURITY_FLOORS entry, "soupsieve": ("2.9", ("2.8.3", "2.8.4")).
  • tests/test_flatpak_dependency_pins.py: soupsieve added to FLATPAK_OMITTED (beautifulsoup4 is not in the Flatpak either); comment above the set rewritten.
  • flatpak/README.md: nine omitted entries instead of eight, a soupsieve entry under the floor-only pins, and the pyinstaller entry corrected (it builds the Windows, macOS and Linux executables in build.yml, not only the Windows one).

Verification

Full suite on this change: Windows 996 passed, 2 skipped; Linux 995 passed, 3 skipped.

Mutations of the soupsieve line in requirements.txt, each run against test_soupsieve_py310.py, test_dependency_security_floors.py, test_flatpak_dependency_pins.py and test_pyside6_ceiling.py:

Mutation Tests that fail
soupsieve>=2.9 (unchanged) none
soupsieve>=3.0.3 test_requirements_keep_admitting_soupsieve_2_10
line removed test_requirements_keep_admitting_soupsieve_2_10, test_specifier_rejects_every_release_below_the_first_clean_one[soupsieve], test_specifier_rejects_every_known_affected_release[soupsieve]
soupsieve>=2.8.4 test_specifier_rejects_every_release_below_the_first_clean_one[soupsieve], test_specifier_rejects_every_known_affected_release[soupsieve]
soupsieve>2.8.4 test_specifier_rejects_every_release_below_the_first_clean_one[soupsieve]
soupsieve>=2.9rc1 test_specifier_rejects_every_release_below_the_first_clean_one[soupsieve]

pip-audit==2.10.1 --strict: "No known vulnerabilities found" on both requirements.txt and flatpak/requirements-pinned.txt.

pip behaviour, in a venv with beautifulsoup4 4.15.0 and soupsieve 2.8.4 (pip 26.1.2, Python 3.14), resetting to 2.8.4 before each case:

Case Command soupsieve after
a pip install -r with beautifulsoup4>=4.15.0 only 2.8.4
b pip install --upgrade -r with beautifulsoup4>=4.15.0 only 2.8.4
c pip install --upgrade --upgrade-strategy eager -r with beautifulsoup4>=4.15.0 only 3.0.3
d pip install -r with beautifulsoup4>=4.15.0 and soupsieve>=2.9 3.0.3

🤖 Generated with Claude Code

soupsieve 2.8.4 has PYSEC-2026-4170 and PYSEC-2026-4171 (ReDoS in the
selector parser), fixed in 2.9. 2.8.3 also has PYSEC-2026-3071 and
PYSEC-2026-3072, fixed in 2.8.4.

soupsieve is a transitive of beautifulsoup4, which only asks for
soupsieve>=1.6.1. Without a line of its own, pip does not upgrade it in
an existing venv unless run with --upgrade --upgrade-strategy eager,
and PyInstaller bundles it.

The floor cannot go to 3.x: every soupsieve 3.x requires Python >=3.11
(>=3.11.5 from 3.0.2). The appimage job in build.yml (Python 3.10) and
the snap (core22, Python 3.10) both install requirements.txt, and the
release job needs the appimage job. Measured with a real Python 3.10.9:
">=2.9" resolves to 2.10, and ">=3.0.3" gives "No matching
distribution".

New tests/test_soupsieve_py310.py fails if the soupsieve line stops
admitting 2.10, so a Dependabot PR that raises it goes red.

Also: a new SECURITY_FLOORS entry in
tests/test_dependency_security_floors.py, soupsieve added to
FLATPAK_OMITTED (beautifulsoup4 is not in the Flatpak either), and
flatpak/README.md corrected to match.

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

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.12 6.12.0 outdated
pypdf pypdf>=6.19.0 6.21.0 outdated
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.2 1.28.2 up-to-date
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.3 6.1.3 up-to-date
urllib3 urllib3>=2.8.0 2.8.0 up-to-date
idna idna>=3.18 3.20 outdated
soupsieve soupsieve>=2.9 3.0.3 outdated
pyinstaller pyinstaller>=6.22.3 6.22.3 up-to-date

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

@nelsonduarte
nelsonduarte merged commit a53e48d into main Oct 16, 2026
6 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