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



GHSA-G75F-G53V-794X

GHSA-G75F-G53V-794X: CPU Exhaustion via Unbounded Email Regular Expression Scanning in Bleach

Amit Schendel
Amit Schendel
Senior Security Researcher

Jun 16, 2026·6 min read·20 visits

Executive Summary (TL;DR)

A ReDoS vulnerability in Bleach's email linkifier allows remote attackers to cause severe CPU exhaustion by submitting a 30KB payload of repeating dot-atom sequences, resulting in thread starvation and denial of service.

An uncontrolled resource consumption vulnerability exists in the Python package Bleach when parsing text to linkify email addresses. When `parse_email=True` is enabled, the regular expression engine is forced into a quadratic-time complexity scan on specially crafted payloads lacking an '@' symbol. This causes immediate CPU exhaustion and blocks application server worker processes.

Vulnerability Overview

The Python bleach package provides HTML sanitization and linkification utilities commonly used to parse user-submitted text and render safe HTML content. One key feature is the linkify module, which converts plain-text URLs and email addresses into clickable HTML anchor tags. When processing text with email linkification enabled, the library relies on a regular expression compilation function to locate and format valid email addresses.

This vulnerability belongs to the Inefficient Regular Expression Complexity class (CWE-1333), also categorized under Uncontrolled Resource Consumption (CWE-400). The attack surface is exposed whenever an application accepts untrusted text inputs and processes them using bleach.linkify() with the parse_email=True parameter enabled.

Because the underlying regular expression engine executes without an explicit timeout, input length boundaries, or linear-time pre-filtering, an attacker can construct input sequences that exploit the pattern matching logic. The resulting CPU exhaustion can degrade application performance, consume all available server worker threads, and trigger a denial of service condition.

Root Cause Analysis

The vulnerability resides in the build_email_re function inside bleach/linkifier.py, which constructs the regular expression used to scan text tokens. The function utilizes a complex pattern to match the local-part (the section before the @ symbol) of email addresses. This pattern is structured around a sequence of valid characters followed by optional repetitions of a dot and additional characters.

The specific dot-atom sub-pattern in the compiled regular expression is defined as ([-!#$%&'*+/=?^_{}|~0-9A-Z]+(.[-!#$%&'*+/=?^_{}|~0-9A-Z]+)*. This matching rule requires that each period character (.) be followed by at least one valid local-part character. The engine scans the input token sequentially, attempting to validate the expression.

When the input contains a repeating sequence of characters like a. (such as a.a.a.a.a.a...) but lacks the mandatory @ symbol and domain component, the engine suffers a design flaw during the lookup phase. The engine first matches the entire pattern up to the end of the input string. Once it reaches the end of the string and fails to locate the @ symbol, the match attempt at the current index fails.

Instead of abandoning the search, the engine shifts its scan pointer forward. The engine advances to the next valid starting position and repeats the entire sequence matching process down to the end of the string. For an input of length $N$, this results in overlapping scans that scale quadratically: the first scan processes $N$ characters, the second scans $N-2$, the third scans $N-4$, and so on. This produces a total instruction complexity proportional to $O(N^2)$, causing significant CPU time accumulation.

Code Analysis

The vulnerable code path is initiated during tokenization within the LinkifyFilter.handle_email_addresses method. When iterating over text tokens, if the token type is identified as "Characters", the library executes self.email_re.finditer(text) to locate matching instances.

# Vulnerable implementation in bleach/linkifier.py
 
def build_email_re(tlds=TLDS):
    return re.compile(
        r"""(?<!//)
        (([-!#$%&'*+/=?^_`{{}}|~0-9A-Z]+
            (\.[-!#$%&'*+/=?^_`{{}}|~0-9A-Z]+)*  # Dot-atom local-part
        |^"([\001-\010\013\014\016-\037!#-\[\]-\177]
            |\\[\001-\011\013\014\016-\177])*"  # Quoted-string local-part
        )@(?:[A-Z0-9](?:[A-Z0-9-]{{0,61}}[A-Z0-9])?\.)+(?:{0}))
        """.format(
            "|".join(tlds)
        ),
        re.IGNORECASE | re.MULTILINE | re.VERBOSE,
    )

The matching loops are executed sequentially within the token handler method:

def handle_email_addresses(self, src_iter):
    """Handle email addresses in character tokens"""
    for token in src_iter:
        if token["type"] == "Characters":
            text = token["data"]
            new_tokens = []
            end = 0
 
            # This call triggers the O(N^2) evaluation loop
            for match in self.email_re.finditer(text):
                # Process the matches...

Because finditer processes the entire string from multiple starting positions sequentially, it cannot determine that a match is impossible without traversing the entire remaining string length on each attempt. This behavior occurs because the pattern allows multiple overlapping permutations of dot-atoms before checking for the static @ character.

Exploitation Methodology

Exploiting this vulnerability does not require authentication if the target application processes user-supplied text on a public endpoint. An attacker needs to submit a long text string consisting of repeating local-part character groups separated by periods, intentionally omitting the @ character. A payload size of approximately 30,000 bytes is sufficient to cause measurable thread blocking.

import bleach
import time
 
# Construct the exploit payload (30,001 bytes)
payload = ("a." * 15000) + "a"
 
print("Executing linkify parsing...")
start = time.time()
 
# Triggers the quadratic scanning behavior
bleach.linkify(payload, parse_email=True)
 
print(f"Execution completed in {time.time() - start:.4f} seconds")

When a single core executes this script, the CPU utilization spikes to 100 percent for approximately 8.7 seconds. In a production web application using multi-worker servers like Gunicorn, uWSGI, or Celery, sending multiple concurrent requests containing this payload will exhaust all available worker threads. While the worker threads are occupied recalculating the regex matches, the application will fail to respond to any incoming legitimate traffic.

Impact Assessment

The security impact is restricted to a localized Denial of Service (DoS). The vulnerability does not allow remote code execution, data exfiltration, or unauthorized privilege escalation. However, because many web frameworks deploy a limited number of synchronous worker processes, a sustained flood of small payloads can cause a prolonged service outage.

The CVSS v3.1 base score is assessed at 4.3 (Medium), with the vector string CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:L. This reflects that the vulnerability is remotely exploitable, has low attack complexity, requires low privileges, requires no user interaction, and has a low but distinct impact on application availability.

Because the bleach package is officially deprecated by its maintainers, no official patches or security releases are planned. Consequently, the vulnerability is likely to remain present in systems that continue to use the package without manual mitigation.

Remediation and Mitigation

To mitigate this vulnerability, developers can implement several programmatic workarounds. The most direct approach is to disable the parse_email argument. If email address parsing is not a core functional requirement of your application, ensure that parse_email is set to False.

If email parsing is required, a highly efficient linear-time ($O(N)$) pre-filter check should be implemented. Because an email address must contain an @ character, checking for its presence using Python's optimized in keyword will prevent the regular expression engine from running on invalid inputs. This check resolves the performance issue for malicious payloads with zero computational overhead.

def safe_linkify(text, parse_email=True):
    # If parse_email is True but no '@' symbol is present,
    # bypass email linkification to prevent CPU exhaustion.
    if parse_email and "@" not in text:
        return bleach.linkify(text, parse_email=False)
    
    return bleach.linkify(text, parse_email=parse_email)

Additionally, applications should enforce strict length boundaries on all incoming user-submitted text fields. Limiting input fields to a maximum of 2,000 characters prevents attackers from submitting the large strings necessary to trigger prolonged CPU stalls.

Technical Appendix

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

Affected Systems

bleach Python package

Affected Versions Detail

Product
Affected Versions
Fixed Version
bleach
Mozilla
<= 6.3.0None (Deprecated)
AttributeDetail
CWE IDCWE-1333
Attack VectorNetwork
CVSS Score4.3
ImpactDenial of Service (CPU Exhaustion)
Exploit StatusProof of Concept Available
KEV StatusNot Listed

MITRE ATT&CK Mapping

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

The regular expression engine can be forced into an inefficient execution path when evaluating inputs, leading to high CPU usage.

Vulnerability Timeline

Vulnerability published to GitHub Advisory Database
2026-06-16
Advisory updated and verified in bleach 6.3.0
2026-06-16

References & Sources

  • [1]GitHub Security Advisory GHSA-G75F-G53V-794X
  • [2]Mozilla Bleach Security Advisories Archive
  • [3]Mozilla Bleach GitHub Repository

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

•30 minutes ago•CVE-2026-67437
7.5

CVE-2026-67437: Unauthenticated Denial of Service via OAuth2 State Memory Exhaustion in OliveTin

An uncontrolled resource consumption vulnerability (CWE-400) in OliveTin allows unauthenticated remote attackers to exhaust server memory and trigger a denial of service (DoS). By repeatedly initiating the OAuth2 login flow without completing it, attackers can force the server to allocate state variables in an unbounded in-memory map. This heap-based resource exhaustion eventually causes the host operating system to terminate the OliveTin process via the Out-Of-Memory (OOM) killer.

Amit Schendel
Amit Schendel
1 views•8 min read
•about 2 hours ago•CVE-2026-67439
4.3

CVE-2026-67439: Incorrect Authorization Leading to Log Leak in OliveTin

An incorrect authorization vulnerability (CWE-863) exists in OliveTin prior to version 3000.17.0. The flaw allows authenticated users who are authorized to execute commands but restricted from viewing logs to bypass this restriction. By utilizing synchronous endpoints, attackers can directly access execution outputs containing sensitive system data, credentials, and environmental configurations.

Alon Barad
Alon Barad
4 views•5 min read
•about 3 hours ago•CVE-2026-67438
6.6

CVE-2026-67438: OS Command Injection via Custom regex: Argument Type Bypassing Shell Safety Check in OliveTin

An OS command injection vulnerability exists in OliveTin versions >= 3000.2.0 and < 3000.17.0. The flaw stems from a validation bypass in the shell safety engine, which fails to recognize custom regular expression arguments as unsafe for actions run in shell execution mode. Furthermore, because these custom regex checks evaluate partial string matches, attackers can append arbitrary shell metacharacters to valid inputs. This allows unauthenticated or low-privilege users who are authorized to run configured actions to inject shell commands and achieve arbitrary remote code execution on the host system.

Amit Schendel
Amit Schendel
4 views•6 min read
•about 3 hours ago•CVE-2026-63118
6.9

CVE-2026-63118: DNS-Rebinding and Cross-Origin Request Execution in Model Context Protocol (MCP) Ruby SDK

A critical vulnerability (CVE-2026-63118) in the Model Context Protocol (MCP) Ruby SDK allows attackers to execute arbitrary JSON-RPC commands and exfiltrate sensitive local data from an MCP server bound to the local loopback interface. This is achieved through DNS-rebinding and cross-origin request execution due to missing validation of the HTTP Host and Origin headers in the StreamableHTTPTransport component.

Alon Barad
Alon Barad
6 views•6 min read
•about 5 hours ago•CVE-2026-63119
6.2

CVE-2026-63119: Denial of Service via Uncontrolled Resource Consumption in Model Context Protocol Ruby SDK

CVE-2026-63119 is a high-impact denial-of-service vulnerability in the Model Context Protocol (MCP) Ruby SDK (distributed as the 'mcp' gem) before version 0.23.0. The vulnerability allows an attacker to cause resource exhaustion and process termination by streaming unbounded input to standard I/O streams.

Alon Barad
Alon Barad
5 views•6 min read
•about 6 hours ago•CVE-2026-67430
5.3

CVE-2026-67430: Denial of Service via Unbounded Session Retention in Model Context Protocol Ruby SDK

CVE-2026-67430 is a medium-severity Denial of Service (DoS) vulnerability in the Model Context Protocol (MCP) Ruby SDK (packaged as the mcp gem) versions prior to 0.23.0. In stateful deployments using the StreamableHTTPTransport class, client session states are retained in an in-memory hash map. Because the transport implements a nil idle timeout by default, the background scavenger process is suppressed. Remote, unauthenticated attackers can flood the endpoint with initialize requests, rapidly consuming system memory and triggering an Out-of-Memory (OOM) crash.

Alon Barad
Alon Barad
6 views•8 min read