CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-85999

CVE-2026-85999: Regular Expression Denial of Service (ReDoS) in Soup Sieve css_parser.py

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 18, 2026·6 min read·2 visits

Executive Summary (TL;DR)

A vulnerable unanchored regular expression in Soup Sieve's CSS parser allows unauthenticated remote attackers to trigger quadratic CPU exhaustion (ReDoS) and application denial of service by submitting a crafted CSS selector containing long runs of internal whitespace or comments. This issue is resolved in version 2.9.

A polynomial-time Regular Expression Denial of Service (ReDoS) vulnerability in Soup Sieve versions prior to 2.9 allows remote unauthenticated attackers to cause CPU exhaustion and thread-pool denial of service. The vulnerability resides in the trailing whitespace and comment preprocessing step of the CSS parser. An attacker can trigger quadratic backtracking by submitting a crafted CSS selector string containing a long run of internal spaces or comments terminated by a non-matching token. This blocks the Python Global Interpreter Lock (GIL) and halts worker threads.

Vulnerability Overview

The vulnerability designated as CVE-2026-85999 (also tracked under GHSA-j934-xhv5-fg8f) affects Soup Sieve, a CSS selector library designed for use with Beautiful Soup 4. The vulnerability is located within the preprocessing phase of CSS selector compilation inside soupsieve/css_parser.py. This component is responsible for parsing, tokenizing, and normalizing CSS queries before they are executed against structured HTML or XML trees.

An attacker who can influence the CSS selector queries processed by an application can exploit this vulnerability. The security flaw stems from an inefficient regular expression evaluation in the selector_iter function, which performs trailing trim operations on the selector patterns.

Because the trimming expression lacks a start anchor and is invoked using search methods, the Python regular expression engine evaluates candidate starting positions iteratively. This leads to excessive CPU cycles being expended when processing specific pattern distributions, degrading the availability of the host software.

Root Cause Analysis

The root cause is classified under CWE-1333: Inefficient Regular Expression Complexity and CWE-400: Uncontrolled Resource Consumption. Before tokenizing a CSS selector, the library executes a pre-processing step to strip leading and trailing whitespace and comments (WSC). The leading trim regular expression RE_WS_BEGIN is anchored with ^, ensuring linear evaluation.

However, the trailing trim regular expression, defined as RE_WS_END = re.compile(fr'{WSC}*$'), is evaluated without a start anchor. Because the .search() method is utilized, the backtracking engine of the Python re module attempts a match starting at every character offset from left to right.

When a CSS selector contains a long internal run of whitespace or comments followed by a non-matching character, the engine repeatedly attempts the greedy matching process. For a sequence of length $n$, the engine performs approximately $O(n^2)$ match operations. The failure of the end-of-string anchor $ at the terminating character forces the engine to shift by one index and retry, resulting in quadratic CPU consumption.

Code Analysis

In vulnerable versions prior to 2.9, the css_parser.py preprocessing implementation uses the following code path:

# Vulnerable Implementation
RE_WS_BEGIN = re.compile(fr'^{WSC}*')
RE_WS_END = re.compile(fr'{WSC}*$')
 
def selector_iter(self, pattern: str) -> Iterator[tuple[str, Match[str]]]:
    # Ignore whitespace and comments at start and end of pattern
    m = RE_WS_BEGIN.search(pattern)
    index = m.end(0) if m else 0
    m = RE_WS_END.search(pattern) # Vulnerable unanchored search
    end = (m.start(0) - 1) if m else (len(pattern) - 1)

The official fix, merged in commit cf198fcddc9230f06ed39f974eba0ce076b85cda, redesigns the verification flow. The developers redefined the comment parsing structure and introduced string reversal during preprocessing to safely anchor the regular expression.

# Patched Implementation
RE_WS_END = re.compile(fr'^(?:[ \t]|(?:\n\r|(?!\n\r)[\n\f\r])|{COMMENTS})*')
 
def selector_iter(self, pattern: str) -> Iterator[tuple[str, Match[str]]]:
    # Ignore whitespace and comments at start and end of pattern
    m = RE_WS_BEGIN.search(pattern)
    index = m.end(0) if m else 0
    # The pattern is reversed to match trailing items using a start anchor
    m = RE_WS_END.search(pattern[::-1])
    offset = m.end(0) if m else 0
    end = len(pattern) - (1 + offset)

By reversing the pattern string and utilizing the start anchor ^ on the reversed text, the regular expression engine is constrained to match strictly from index 0. If a mismatch is encountered at the beginning of the reversed pattern, the parser fails immediately in $O(1)$ time, mitigating the backtracking loop.

Exploitation Methodology

An attack can be executed if a target web application exposes an endpoint that compiles dynamic, user-supplied CSS selectors. This is common in web scraping utilities, content filtering tools, and administrative interfaces that run structural queries.

The exploit payload requires three elements: a valid CSS element selector, a long sequence of internal whitespace characters or CSS comments, and a single trailing character that does not match the trailing rules. An example string is: 'div' + ' ' * 20000 + 'b'. Alternatively, an exploit can be crafted using repeating CSS comments: 'div' + '/*comment*/' * 2000 + 'b'.

When the backend engine parses this query, the process halts. Because Python utilizes a Global Interpreter Lock (GIL), the CPU-bound regular expression processing prevents concurrent application threads from executing, leading to denial of service.

Impact Assessment

The impact is classified as a denial of service (DoS) vulnerability. Although CVSS v3.1 assigns a Medium severity of 5.3 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L), the practical impact on Python service deployments is high.

In synchronous or multi-threaded Python application servers (e.g., gunicorn, uWSGI), a thread locked in a regular expression backtracking loop will hold the GIL continuously. This starvation blocks other threads in the same process from handling incoming requests. If an attacker submits a small number of concurrent requests matching the exploit signature, they can exhaust the available worker pools, bringing down the application.

Because this vulnerability occurs during the initial preprocessing stage of Soup Sieve, it requires minimal system knowledge to exploit. The attack is highly repeatable and requires no authentication.

Remediation & Mitigation Guidance

Remediation requires upgrading the soupsieve package to version 2.9 or above, which replaces the unanchored search pattern with the reversed-string anchored match.

To upgrade the package using pip, execute:

pip install --upgrade soupsieve

If immediate dependency updates are not possible, developers should implement input validation limits. Restrict the character length of selectors accepted from untrusted sources to a conservative ceiling (e.g., 256 characters). Developers can also sanitize input strings by compressing consecutive whitespace and stripping comments before passing the selectors to Beautiful Soup APIs.

# Defensive sanitization wrapper
import re
 
def safe_select(soup, selector):
    # Compress internal whitespace sequences and strip comment blocks
    sanitized = re.sub(r'\s+', ' ', selector)
    sanitized = re.sub(r'/\*.*?\*/', '', sanitized)
    if len(sanitized) > 512:
        raise ValueError("Selector length exceeds safe limit")
    return soup.select(sanitized)

Official Patches

facelessuserPatch commit fixing ReDoS trailing trim issue
facelessuserSoup Sieve 2.9 Official Release Tag

Fix Analysis (1)

Technical Appendix

CVSS Score
5.3/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L

Affected Systems

Applications utilizing BeautifulSoup 4 with Soup Sieve versions prior to 2.9 for CSS selector queries.Python-based web scrapers, parsers, and browser-emulators processing dynamic CSS queries.

Affected Versions Detail

Product
Affected Versions
Fixed Version
soupsieve
facelessuser
< 2.92.9
AttributeDetail
CWE IDCWE-1333
Attack VectorNetwork
CVSS v3.1 Score5.3
EPSS ScoreNot Available
ImpactDenial of Service (DoS)
Exploit Statuspoc
KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499.004Endpoint Denial of Service: Application Exhaustion
Impact
CWE-1333
Inefficient Regular Expression Complexity

The product uses a regular expression that can be made to run in quadratic time relative to the input size, allowing attackers to consume excessive CPU cycles.

Vulnerability Timeline

Vulnerability fix implemented in source repository
2026-07-19
Soup Sieve version 2.9 released on PyPI
2026-09-17
GitHub Security Advisory GHSA-j934-xhv5-fg8f published
2026-09-17
CVE-2026-85999 published and assigned
2026-09-17

References & Sources

  • [1]GitHub Security Advisory GHSA-j934-xhv5-fg8f
  • [2]CVE Record CVE-2026-85999
  • [3]NVD Entry CVE-2026-85999

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 1 hour ago•CVE-2026-88976
6.1

CVE-2026-88976: HTML Deserialization Cross-Site Scripting in @platejs/core

Plate core HTML deserialization APIs parse supplied HTML strings in the active document. When an application passes untrusted or cross-user HTML to these APIs, certain HTML attributes can trigger browser behavior before the HTML is converted into editor nodes.

Amit Schendel
Amit Schendel
2 views•6 min read
•about 3 hours ago•CVE-2026-86000
5.3

CVE-2026-86000: Polynomial-Time Regular Expression Denial of Service in Soup Sieve Selector Parser

A regular expression denial of service (ReDoS) vulnerability in Soup Sieve prior to version 2.9 allows remote attackers to cause CPU exhaustion and service disruption. The issue lies within the definition of the IDENTIFIER and VALUE selector sub-patterns in the CSS parser component, which uses overlapping adjacent quantified groups. When parsing long, crafted, or unclosed CSS selectors, backtracking-based regular expression engines experience quadratic performance degradation. User-controlled selectors can reach this path through soupsieve.compile(), soupsieve.select(), or BeautifulSoup.select(), while applications using only hard-coded selectors are unaffected.

Amit Schendel
Amit Schendel
6 views•7 min read
•about 4 hours ago•CVE-2026-86003
7.5

CVE-2026-86003: Unintended Proxying of DNS UPDATE Requests via Alternative Transports in CoreDNS

A protocol-level validation bypass in CoreDNS versions prior to 1.14.7 allows unauthenticated remote attackers to proxy unauthorized DNS UPDATE messages (Opcode 5) using modern alternative transport layers such as DoH, DoH3, DoQ, and gRPC. If upstream authoritative servers trust the CoreDNS server's source IP and do not enforce TSIG authentication, attackers can inject, alter, or delete DNS zone records, leading to potential zone takeover or traffic redirection.

Alon Barad
Alon Barad
5 views•5 min read
•about 5 hours ago•CVE-2026-72695
8.1

CVE-2026-72695: Authenticated Path Traversal and Arbitrary File Deletion in Grav CMS MediaUploadTrait

A path traversal vulnerability exists in Grav CMS versions prior to 2.0.16. The flaw occurs within the file validation mechanisms of the MediaUploadTrait, enabling authenticated users with media management privileges to bypass sandbox limitations. This allows the deletion of arbitrary files on the filesystem, which can result in denial of service or remote code execution.

Amit Schendel
Amit Schendel
4 views•7 min read
•about 6 hours ago•CVE-2026-74907
5.9

CVE-2026-74907: Directory Traversal in Grav CMS Pre-Boot Static Asset Server

An unauthenticated directory traversal vulnerability exists in Grav CMS prior to version 2.0.15. Due to an insecure string-based containment check (str_starts_with) in the pre-boot static asset server, attackers can read files in sibling directories sharing a prefix with the configured asset path when plugin-asset-map.php is enabled.

Amit Schendel
Amit Schendel
6 views•7 min read
•about 7 hours ago•CVE-2026-75828
9.3

CVE-2026-75828: Stored Cross-Site Scripting (XSS) via Security Filter Bypass in Grav CMS

CVE-2026-75828 is a critical stored cross-site scripting (XSS) vulnerability in the getgrav Grav CMS before version 2.0.15. The vulnerability resides in the detectXss() security filter mechanism, where parser-differential mismatches between the regular-expression-based server-side validation and browser HTML5 tokenization allow authenticated editors to bypass event-handler detection and inject arbitrary JavaScript execution vectors.

Amit Schendel
Amit Schendel
6 views•4 min read