soupsieve CVE-2026-49477
HIGHSeverity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
Remote low-complexity ReDoS needing no auth or interaction where untrusted selectors are compiled; availability-only impact gives C:N/I:N/A:H with scope unchanged.
Primary rating from Vendor (https://github.com/facelessuser/soupsieve).
CVSS VectorVendor: https://github.com/facelessuser/soupsieve
Lifecycle Timeline
1Blast Radius
ecosystem impact- 11 pypi packages depend on soupsieve (8 direct, 3 indirect)
Ecosystem-wide dependent count for version 2.8.4.
DescriptionCVE.org
Summary
The CSS selector parser in soupsieve (the CSS selector engine for Beautiful Soup 4) contains a regular expression vulnerable to catastrophic backtracking. When processing an attribute selector with an unterminated quoted value, the VALUE regex pattern in css_parser.py enters exponential backtracking. A payload of only 300 bytes causes the regex engine to hang for over 3 seconds, enabling a trivial Regular Expression Denial of Service (ReDoS) attack.
To be completely transparent, AI tools helped surface this issue. However, this was independently reproduced and carefully validated.
Any application that passes untrusted CSS selector strings to soupsieve.compile() or Beautiful Soup's .select() / .select_one() is affected.
Details
Affected code: soupsieve/css_parser.py, line ~121 - RE_VALUES / VALUE regex pattern
The soupsieve CSS parser uses a compiled regular expression to tokenise attribute selector values. This pattern matches both quoted strings ("value" or 'value') and unquoted identifiers. The regex contains alternation branches for:
- Double-quoted strings:
"[^"\\]*(?:\\.[^"\\]*)*" - Single-quoted strings:
'[^'\\]*(?:\\.[^'\\]*)*' - Unquoted identifiers
When an attribute selector contains an unterminated quoted value - e.g., [a="xxxx... (opening " but no closing ") -” the regex engine attempts to match the quoted-string branch. After that branch fails (no closing quote), the engine backtracks and attempts to match the remaining input against subsequent alternation branches and parent patterns. The structure of the pattern causes catastrophic backtracking where the number of backtracking steps grows exponentially with the length of the content between the opening quote and the end of the string.
Root cause: The regex pattern does not anchor or guard against the case where a quoted string is never terminated. The overlapping character classes across alternation branches create exponential backtracking when the quoted-string branch fails on long input.
Key characteristics:
- Input size: Only 300 bytes are needed to trigger a >3 second hang
- Amplification: Each additional character approximately doubles the backtracking time
- No memory impact: The attack consumes CPU only (regex backtracking is compute-bound)
Proof of Concept
import time
import soupsieve as sv
PAYLOAD_LEN = 300
# Control: well-formed selector with terminated quote (completes instantly)
well_formed = '[a="' + ('x' * PAYLOAD_LEN) + '"]'
start = time.perf_counter()
try:
sv.compile(well_formed)
except Exception:
pass
control_time = time.perf_counter() - start
print(f"Well-formed selector ({len(well_formed)} bytes): {control_time:.4f}s")
# Exploit: unterminated quote triggers catastrophic regex backtracking
malformed = '[a="' + ('x' * PAYLOAD_LEN)
start = time.perf_counter()
try:
sv.compile(malformed)
# WARNING: This will hang for >3 seconds
except Exception:
pass
exploit_time = time.perf_counter() - start
print(f"Malformed selector ({len(malformed)} bytes): {exploit_time:.4f}s")
slowdown = exploit_time / max(control_time, 1e-9)
print(f"Slowdown: {slowdown:.0f}x")
# Expected output:
# Well-formed selector (306 bytes): ~0.001s
# Malformed selector (304 bytes): >3.0s (may need to be killed)
# Slowdown: >3000x
#
# NOTE: On some systems the malformed selector may hang indefinitely.
# Use a timeout mechanism (signal.alarm, threading.Timer) when testing.Safe testing variant with timeout:
import signal
import soupsieve as sv
def timeout_handler(signum, frame):
raise TimeoutError("ReDoS confirmed: regex backtracking exceeded timeout")
PAYLOAD_LEN = 300
malformed = '[a="' + ('x' * PAYLOAD_LEN)
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(3)
# 3-second timeout
try:
sv.compile(malformed)
print("Selector compiled (not vulnerable)")
except TimeoutError as e:
print(f"VULNERABLE: {e}")
except Exception as e:
print(f"Other error: {e}")
finally:
signal.alarm(0)
# Cancel the alarmImpact
Severity: High
An attacker can cause CPU exhaustion on any server-side Python application that compiles user-supplied CSS selectors via soupsieve. The attack is particularly dangerous because:
- Tiny payload: Only 300 bytes are needed - well within typical URL parameter, form field, or API request limits
- No special characters: The payload consists entirely of printable ASCII characters (
[a="xxx...) - Exponential scaling: Each additional byte approximately doubles the backtracking time, making the attack easily tuneable
- Thread blocking: The regex engine blocks the calling thread with no opportunity for interruption (except via OS signals)
| Parameter | Value |
|---|---|
| Input size | 300 bytes |
| CPU time consumed | >3 seconds (exponential with payload length) |
| Memory consumed | Negligible (CPU-only attack) |
| Authentication required | None |
| User interaction required | None |
Deployment impact: In threaded or async web applications, a single malicious request blocks a worker thread for the duration of the backtracking. An attacker can submit multiple concurrent requests to exhaust all available workers, causing complete service denial. The small payload size makes the attack easy to deliver and difficult to detect via request size limits.
Downstream exposure: soupsieve is an automatic dependency of beautifulsoup4, one of the most widely installed Python packages. Any web application, API, or service that accepts CSS selectors from users is potentially affected.
---
Credit
The vulnerability was discovered by a security research team from the University of Sydney, whose focus is detecting open source software vulnerabilities. Liyi Zhou: https://lzhou1110.github.io/ Ziyue Wang: https://zyy0530.github.io/ Strick: https://str1ckl4nd.github.io/ Maurice: https://maurice.busystar.org/ Chenchen Yu: https://7thparkk.github.io/
Articles & Coverage 1
AnalysisAI
Denial of service in soupsieve, the CSS selector engine bundled with Beautiful Soup 4, lets remote attackers hang a worker thread by submitting a ~300-byte attribute selector with an unterminated quoted value (e.g. '[a="xxxx...'), triggering catastrophic regular-expression backtracking in the VALUE pattern of css_parser.py. Any Python service that passes untrusted selector strings to soupsieve.compile() or Beautiful Soup's .select()/.select_one() is affected, and each added byte roughly doubles CPU time, so a handful of concurrent requests can exhaust all workers. Publicly available exploit code exists (a working PoC is embedded in the advisory), but no exploit is identified as being used in active attacks and it is not listed in CISA KEV.
Technical ContextAI
soupsieve tokenises CSS attribute-selector values with a single compiled regular expression (RE_VALUES / VALUE, around line 121 of css_parser.py) offering alternation branches for double-quoted strings ("[^"\\]*(?:\\.[^"\\]*)*"), single-quoted strings, and unquoted identifiers. This is the classic CWE-400 (Uncontrolled Resource Consumption) root-cause class realised as a ReDoS: the quoted-string branches use nested, overlapping character classes with no anchor guarding the never-terminated case, so when the closing quote is absent the engine repeatedly re-partitions the long run of characters between alternatives and parent patterns, and the number of backtracking steps grows exponentially with input length. Because soupsieve is the mandatory selector backend for beautifulsoup4 (CPE pkg:pip/soupsieve), the same code path is reached transparently through Beautiful Soup's high-level .select() API. The attack is compute-bound only - it burns CPU on the calling thread and consumes negligible memory.
RemediationAI
Patch available per vendor advisory (GHSA-836r-79rf-4m37); the provided data does not include an exact fixed version, so upgrade soupsieve to the fixed release named in the advisory at https://github.com/facelessuser/soupsieve/security/advisories/GHSA-836r-79rf-4m37 and verify that version there before deploying. Because soupsieve is pulled in transitively by beautifulsoup4, update the transitive pin, not just direct dependencies. Where immediate patching is not possible and the application accepts user-supplied selectors, the most effective compensating control is to stop passing untrusted input to soupsieve.compile()/.select()/.select_one() - validate selectors against a strict allowlist or reject any selector containing an unbalanced quote before compilation (trade-off: code changes required and some legitimate exotic selectors may be rejected). As defence-in-depth, run selector compilation under a hard timeout or in a separate cancellable worker/process and enforce a tight length cap on selector input (trade-off: signal/thread-based timeouts add complexity and per-call overhead, and length caps can break legitimate long selectors). None of these should replace upgrading once the fixed version is confirmed.
Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t
BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser
pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi
The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python
BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica
OpenSSL before 0.9.8za, 1.0.0 before 1.0.0m, and 1.0.1 before 1.0.1h does not properly restrict processing of ChangeCiph
pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.
Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301
In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse
Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to
Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/
pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne
Same weakness CWE-400 – Uncontrolled Resource Consumption
View allSame technique Denial Of Service
View allVendor StatusVendor
SUSE
Severity: Important| Product | Status |
|---|---|
| SUSE Linux Enterprise Desktop 15 SP7 SUSE Linux Enterprise High Performance Computing 15 SP7 SUSE Linux Enterprise Server 15 SP7 SUSE Linux Enterprise Server for SAP Applications 15 SP7 | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP4-ESPOS | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP4-LTSS | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP5-ESPOS | Fixed |
| SUSE Linux Enterprise High Performance Computing 15 SP5-LTSS | Fixed |
| SUSE Linux Enterprise Module for Basesystem 15 SP7 | Fixed |
| SUSE Linux Enterprise Module for Python 3 15 SP7 | Fixed |
| SUSE Linux Enterprise Server 15 SP4-LTSS | Fixed |
| SUSE Linux Enterprise Server 15 SP5-LTSS | Fixed |
| SUSE Linux Enterprise Server 15 SP6-LTSS | Fixed |
| SUSE Linux Enterprise Server 16.0 SUSE Linux Enterprise Server for SAP applications 16.0 | Fixed |
| SUSE Linux Enterprise Server for SAP Applications 15 SP4 | Fixed |
| SUSE Linux Enterprise Server for SAP Applications 15 SP5 | Fixed |
| SUSE Linux Enterprise Server for SAP Applications 15 SP6 | Fixed |
| SUSE Manager Proxy LTS 4.3 | Fixed |
| SUSE Manager Retail Branch Server LTS 4.3 | Fixed |
| SUSE Manager Server LTS 4.3 | Fixed |
| openSUSE Leap 16.0 | Fixed |
| SUSE Linux Enterprise Desktop 15 SP7 | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP7 | Affected |
| SUSE Linux Enterprise Module for Basesystem 15 SP7 | Affected |
| SUSE Linux Enterprise Module for Python 3 15 SP7 | Affected |
| SUSE Linux Enterprise Server 15 SP7 | Affected |
| SUSE Linux Enterprise Server 16.0 | Affected |
| SUSE Linux Enterprise Server 16.1 | Affected |
| SUSE Linux Enterprise Server for SAP Applications 15 SP7 | Affected |
| SUSE Linux Enterprise Server for SAP applications 16.0 | Affected |
| SUSE Linux Enterprise Server for SAP applications 16.1 | Affected |
| openSUSE Leap 16.0 | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP4 | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP4-LTSS | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP5 | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP5-LTSS | Affected |
| SUSE Linux Enterprise Module for Basesystem 15 SP4 | Affected |
| SUSE Linux Enterprise Module for Basesystem 15 SP5 | Affected |
| SUSE Linux Enterprise Module for Basesystem 15 SP6 | Affected |
| SUSE Linux Enterprise Module for Python 3 15 SP6 | Affected |
| SUSE Linux Enterprise Server 15 SP4 | Affected |
| SUSE Linux Enterprise Server 15 SP4-LTSS | Affected |
| SUSE Linux Enterprise Server 15 SP5 | Affected |
| SUSE Linux Enterprise Server 15 SP5-LTSS | Affected |
| SUSE Linux Enterprise Server 15 SP6 | Affected |
| SUSE Linux Enterprise Server 15 SP6-LTSS | Affected |
| SUSE Linux Enterprise Server for SAP Applications 15 SP6 | Affected |
| SUSE Manager Proxy 4.3 | Affected |
| SUSE Manager Proxy LTS 4.3 | Affected |
| SUSE Manager Retail Branch Server 4.3 | Affected |
| SUSE Manager Retail Branch Server LTS 4.3 | Affected |
| SUSE Manager Server 4.3 | Affected |
| SUSE Manager Server LTS 4.3 | Affected |
| SUSE Enterprise Storage 7 | Affected |
| SUSE Enterprise Storage 7.1 | Affected |
| SUSE Linux Enterprise Desktop 15 SP2 | Affected |
| SUSE Linux Enterprise Desktop 15 SP3 | Affected |
| SUSE Linux Enterprise Desktop 15 SP4 | Affected |
| SUSE Linux Enterprise Desktop 15 SP5 | Affected |
| SUSE Linux Enterprise Desktop 15 SP6 | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP2 | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP2-ESPOS | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP2-LTSS | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP3 | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP3-ESPOS | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP3-LTSS | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP4-ESPOS | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP5-ESPOS | Affected |
| SUSE Linux Enterprise High Performance Computing 15 SP6 | Affected |
| SUSE Linux Enterprise Module for Basesystem 15 SP2 | Affected |
| SUSE Linux Enterprise Module for Basesystem 15 SP3 | Affected |
| SUSE Linux Enterprise Real Time 15 SP2 | Affected |
| SUSE Linux Enterprise Real Time 15 SP3 | Affected |
| SUSE Linux Enterprise Real Time 15 SP4 | Affected |
| SUSE Linux Enterprise Server 15 SP2 | Affected |
| SUSE Linux Enterprise Server 15 SP2-BCL | Affected |
| SUSE Linux Enterprise Server 15 SP2-LTSS | Affected |
| SUSE Linux Enterprise Server 15 SP3 | Affected |
| SUSE Linux Enterprise Server 15 SP3-BCL | Affected |
| SUSE Linux Enterprise Server 15 SP3-LTSS | Affected |
| SUSE Linux Enterprise Server for SAP Applications 15 SP2 | Affected |
| SUSE Linux Enterprise Server for SAP Applications 15 SP3 | Affected |
| SUSE Linux Enterprise Server for SAP Applications 15 SP4 | Affected |
| SUSE Linux Enterprise Server for SAP Applications 15 SP5 | Affected |
| SUSE Manager Proxy 4.1 | Affected |
| SUSE Manager Proxy 4.2 | Affected |
| SUSE Manager Retail Branch Server 4.1 | Affected |
| SUSE Manager Retail Branch Server 4.2 | Affected |
| SUSE Manager Server 4.1 | Affected |
| SUSE Manager Server 4.2 | Affected |
| openSUSE Leap 15.3 | Affected |
| openSUSE Leap 15.4 | Affected |
| openSUSE Leap 15.5 | Affected |
| openSUSE Leap 15.6 | Affected |
Share
External POC / Exploit Code
Leaving vuln.today
GHSA-836r-79rf-4m37