Soup Sieve: Exponential ReDoS in selector compilation via \9-run in CSS_ESCAPES/IDENTIFIER
🔗 CVE IDs covered (1)
📋 Description
Summary
The IDENTIFIER/CSS_ESCAPES regex (css_parser.py:119-124) exhibits exponential backtracking on a run of ambiguous digit-escapes (\9) in an attribute-name or tag position of an otherwise well-formed selector. It fires at compile time (before the SELECTOR_LIMIT guard) via the public soupsieve.compile() and BeautifulSoup .select().
PoC (verified on soupsieve 2.9.2)
import soupsieve as sv
sv.compile('[a' + '\\9'*26 + '=x]') # ~57 bytes -> ~10s; ~16x time per +4 chars
Novelty
Distinct from the patched GHSA-836r-... (VALUE regex) and GHSA-2wc2-... (comma-list) advisories, which are fixed in 2.9.2; this is a different regex/vector.
Reachability
CSS selectors are usually developer-controlled, so exposure requires an application that compiles UNTRUSTED selector strings (web-scraping-as-a-service, no-code/query builders, user-defined extraction rules). Where selectors are user-supplied, a ~60-byte string hangs the worker.
Note
This issue was fixed in version 3.0.0, which has been yanked from the PyPI registry. Use versions 3.0.2 and above to upgrade.
🎯 Affected products1
- pip/soupsieve:<= 2.10
🔗 References (6)
- https://github.com/facelessuser/soupsieve/security/advisories/GHSA-6655-6qjp-jx7x
- https://nvd.nist.gov/vuln/detail/CVE-2026-126191
- https://github.com/facelessuser/soupsieve/pull/300
- https://github.com/facelessuser/soupsieve/commit/dbfa2854ff31a863326bd6660d4e55c6f068db9e
- https://github.com/facelessuser/soupsieve/releases/tag/3.0
- https://github.com/advisories/GHSA-6655-6qjp-jx7x