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

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

Amit Schendel
Amit Schendel
Senior Security Researcher

Sep 18, 2026·7 min read·5 visits

Executive Summary (TL;DR)

Unauthenticated remote attackers can cause denial of service (CPU exhaustion) via crafted CSS selectors in Soup Sieve's parser before version 2.9.

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.

Vulnerability Overview

The Soup Sieve library is a highly utilized component in the Python ecosystem, serving as the default CSS selector implementation for the ubiquitous Beautiful Soup 4 library. It allows developers to search and filter parsed HTML/XML documents using complex CSS selector patterns, mirroring modern browser capability. Because of this, Soup Sieve is commonly integrated into automated data ingestion systems, web scrapers, data aggregators, and document processing backends. These applications frequently accept and process external, user-supplied data, making selector parsing a critical boundary for system stability and security.

Prior to version 2.9, Soup Sieve's selector compiler contained a vulnerability within its regular expression patterns. An unauthenticated attacker capable of providing a custom, crafted CSS selector string could trigger a massive resource consumption state. This is tracked as CVE-2026-86000 and is classified under CWE-1333 (Inefficient Regular Expression Complexity) and CWE-400 (Uncontrolled Resource Consumption).

The vulnerability is activated when Soup Sieve processes custom selectors using functions such as soupsieve.compile(), soupsieve.select(), or BeautifulSoup.select(). When a long or unclosed CSS selector pattern is compiled, the backtracking regular expression engine attempts to resolve overlapping paths. This results in quadratic time complexity ($O(n^2)$) relative to the length of the string, keeping the system process bound to the CPU, locking the Global Interpreter Lock, and completely stalling service for any other tasks.

Root Cause Analysis

To understand the technical root cause of CVE-2026-86000, we must examine how the Soup Sieve parser processes CSS identifiers. In src/soupsieve/css_parser.py, the tokenization engine depends on a hand-written regular expression sub-pattern named IDENTIFIER. This pattern is responsible for matching selectors such as tags, IDs, class names, and attributes.

The vulnerable definition of IDENTIFIER was structured with two adjacent quantified sub-groups. The first group, representing the identifier prefix, was defined as (?:-?(?:[^\x00-\x2f\x30-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES})+|--). The second group, matching the identifier continuation, was defined as (?:[^\x00-\x2c\x2e\x2f\x3A-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES})*. The critical vulnerability resides in the fact that these two adjacent groups match heavily overlapping character classes.

The character classes in both groups permit standard alphanumeric characters, such as lowercase and uppercase letters (a-z, A-Z) and underscores (_). When a long string consisting entirely of overlapping characters is evaluated, the Python standard re module (which implements a backtracking NFA-based engine) experiences high ambiguity. It cannot deterministically determine where the first group (quantified with +) ends and where the second group (quantified with *) begins.

If the input eventually fails downstream—such as when a long alphanumeric identifier is terminated with an invalid character like !—the NFA engine is forced to backtrack. It evaluates every possible split of characters between the first and second groups to find a valid match. The number of splits grows quadratically ($O(n^2)$) relative to the length of the string. This leads to massive CPU exhaustion, pinning a CPU core at 100% until the evaluation is complete.

Code Analysis

Comparing the code of src/soupsieve/css_parser.py before and after the version 2.9 release demonstrates a clean remediation of this regular expression complexity. The vulnerability was resolved in commit ce44e4996e6632871c18cdd7a7fb641be8ef34ef by making the prefix matching deterministic.

Before the patch, the IDENTIFIER regular expression was defined as follows:

# Vulnerable code in soupsieve/css_parser.py
IDENTIFIER = fr'''
(?:(?:-?(?:[^\x00-\x2f\x30-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES})+|--)
(?:[^\x00-\x2c\x2e\x2f\x3A-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES})*)
'''

The presence of the + quantifier in the first group allows it to consume an arbitrary length of valid identifier characters. Because the second group also consumes standard identifier characters via the * quantifier, the engine is forced to explore a massive state space when backtracking occurs.

The patch successfully resolved the flaw by refactoring the expression to remove the variable quantifier from the prefix group:

# Patched code in soupsieve/css_parser.py (v2.9)
IDENTIFIER = fr'''
(?:(?:--|-?(?:[^\x00-\x2f\x30-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES}))
(?:[^\x00-\x2c\x2e\x2f\x3A-\x40\x5B-\x5E\x60\x7B-\x9f]|{CSS_ESCAPES})*)
'''

By replacing + with a deterministic requirement matching exactly one character or double hyphens (--), the engine is forced to consume precisely one character in the prefix group. Any remaining characters are consumed strictly by the continuation group. This completely eliminates the ambiguity, changing the matching operation's time complexity from $O(n^2)$ back to linear $O(n)$ time. This fix is complete and robust because it removes the foundational mechanism required for catastrophic backtracking.

Exploitation Methodology

Exploiting CVE-2026-86000 is straightforward and requires no special system privileges. An attacker simply needs to submit a crafted CSS selector to any system that processes inputs with the vulnerable Soup Sieve library. Since the vulnerability is located inside the tokenizing engine, simply compiling a malformed selector is sufficient to trigger the CPU hang.

There are two main payload variants that trigger the backtracking behaviour. The first is a plain identifier payload where a very long string of alphanumeric characters is terminated with a syntax-breaking character (like an exclamation mark). This forces the engine to parse the long string as an identifier, reach the end, realize the match has failed, and backtrack through the entire string:

/* Plain identifier payload */
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... [10,000+ chars] ...aaa!

The second vector involves unquoted attribute-value selectors. The Soup Sieve parser embeds the vulnerable IDENTIFIER definition inside the pattern used to evaluate attribute values. If an attacker submits an unclosed attribute selector containing a long run of unquoted characters, the engine experiences identical backtracking during EOF resolution:

/* Unquoted attribute-value payload */
[a=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa... [12,000+ chars]

When a Python process executes either payload, the regular expression engine holds the Python Global Interpreter Lock (GIL). This prevents any other threads in the same process from executing, stalling the entire application worker. An attacker can easily weaponize this by sending multiple concurrent requests to fully saturate all worker processes on the application server, resulting in complete denial of service.

Impact Assessment

The primary impact of CVE-2026-86000 is a complete Denial of Service (DoS) of the affected Python application. Because the execution of the regular expression engine occurs within native C code in the Python standard library, it runs at maximum processor speed, pinning a CPU core at 100%. If the host application is single-process or has limited worker threads, a single malicious request can completely lock up the service.

When the regular expression engine is forced to backtrack over a malicious payload, it consumes 100% of the allocated CPU core. Because Python's Global Interpreter Lock (GIL) is held during the C-level execution of the re module, even multi-threaded application servers (such as those running under certain configurations of gunicorn or uWSGI) can experience complete lockups. The entire process becomes unresponsive to health checks and incoming user traffic.

In environments where multiple worker processes are deployed, an attacker can trivially send a small number of concurrent malicious requests (matching the number of worker processes) to completely exhaust the application pool. This results in an immediate, sustained denial of service across the entire platform. Since the exploit complexity is low and requires no special privileges, systems that parse arbitrary, user-supplied HTML documents or support custom selectors are highly exposed.

Official Patches

facelessuserOfficial patch removing adjacent overlapping quantifiers

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

Soup SieveBeautiful Soup 4 (via select method)

Affected Versions Detail

Product
Affected Versions
Fixed Version
soupsieve
facelessuser
< 2.92.9
AttributeDetail
CWE IDCWE-1333
Attack VectorNetwork (AV:N)
CVSS v3.1 Score5.3 (Medium)
EPSS ScoreNot Available
Primary ImpactDenial of Service (CPU Exhaustion)
Exploit StatusProof-of-Concept Available
CISA KEV StatusNot Listed

MITRE ATT&CK Mapping

T1499Endpoint Denial of Service
Impact
CWE-1333
Inefficient Regular Expression Complexity

The product uses a regular expression that can take a very long time to evaluate when faced with specific inputs, leading to a Denial of Service.

Vulnerability Timeline

Vulnerability identified and disclosed via GitHub Security Advisory
2026-02-01
Official patch commit ce44e4996e6632871c18cdd7a7fb641be8ef34ef merged
2026-02-01
Soup Sieve version 2.9 released
2026-02-01

References & Sources

  • [1]GitHub Security Advisory GHSA-gjv8-xp57-g29c
  • [2]Official Fix Commit ce44e499
  • [3]Official Release Tag (v2.9)
  • [4]NVD Advisory Entry
  • [5]CVE.org Authority Record
  • [6]OSV Machine-Readable Vulnerability Registry

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-85999
5.3

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

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.

Amit Schendel
Amit Schendel
2 views•6 min read
•about 3 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 4 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 5 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 6 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
•about 7 hours ago•CVE-2026-75827
8.8

CVE-2026-75827: Grav Arbitrary File Write & Remote Code Execution

An arbitrary file write and remote code execution vulnerability exists in Grav CMS before version 2.0.15. The vulnerability is caused by using an incomplete denylist validation approach for bare PHP functions in the Blueprint dynamic-data compiler, allowing authenticated users with page-editing or blueprint-configuration privileges to execute arbitrary functions such as error_log.

Alon Barad
Alon Barad
6 views•4 min read