Cyber News / Article / The Hidden DoS Vector in SQL Parsers

The Hidden DoS Vector in SQL Parsers
Home>Blog>The Hidden DoS Vector in SQL Parsers
OriNakar
Oct 5, 20267 min read
SQL parsers are critical components of the modern data stack. They validate queries before they reach the database, transpile between dialects, and lint codebases for style violations. Increasingly, they also power AI-driven SQL generation in LLM-integrated data tools.
Our research focused on two popular Python-based parsers:SQLGlotandSQLFluff, both with around 10k GitHub stars each. These libraries sit at the foundation of the data ecosystem, trusted by thousands of projects, and we believe the underlying issues are relevant to other parsers and other programming languages as well.
But these parsers carry a hidden flaw. They are highly susceptible to resource exhaustion from seemingly “simple,” syntactically valid SQL queries. Not injection. Not malformed input. Just normal-looking SQL that happens to be shaped in the wrong way.
In this post, we describe our findings of new vulnerabilities stemming from two root causes:Recursive Stack OverflowandParser AST Object-Inflation. We show how these flaws cascade into downstream applications, giving concrete examples from several major projects we found vulnerable, with many more still to be explored. We then explain the underlying mechanics and conclude with practical fix suggestions for both parser maintainers and application developers. We reported every issue to the respective maintainers and contributed to the fixes that now ship upstream; the SQLFluff findings were assignedCVE-2026-46373andCVE-2026-46374.
Our research began with a simple question: what happens when you feed a deeply nested query to a SQL parser?
The answer: the Python interpreter crashes with aRecursionError. At higher concurrency, it segfaults.
This isn’t a contrived edge case. The query is syntactically valid SQL. Any database would reject it for being absurd, but a parser’s job is toparseit – and both SQLGlot and SQLFluff attempt to do so without any depth limit. At 50+ levels of nesting, the recursive descent parser exhausts the call stack.
The fix seems obvious in hindsight: enforce a maximum recursion depth (e.g., 30 levels) and abort gracefully. But neither parser does this.
The recursion crash was just the beginning. As we explored further, we discovered a more insidious problem:AST amplification.
SQL parsers work by converting raw SQL text into an Abstract Syntax Tree (AST) – a structured representation where each token (literal, identifier, operator, dot) becomes a Python object. These objects carry metadata: type information, position tracking, parent references. They’re heavyweight.
The question became: what if we crafted a query that wasshortbut produced an enormous number of AST nodes?
The result was striking. In SQLGlot, a SQL string under2MBin size demanded over1.5GB of RAMto parse – roughly a750x amplification ratio. SQLFluff showed the same pattern: at width=5000, it consumed over 1GB.
This is the core vulnerability: each SQL token gets wrapped in a heavy Python object. A compact input with thousands of columns and deep expression chains generatesmillionsof AST nodes, far exceeding what any reasonable container or server can handle. The process is killed by the OOM killer – or simply hangs until it starves out everything else on the machine.
To see where the cost comes from, it helps to follow the input through each stage of parsing. The payload starts small, but every step multiplies it: tokenization splits the string into hundreds of thousands of pieces, AST construction wraps each one in a heavyweight Python object, and the resulting tree balloons into gigabytes of memory. The diagram below traces that roughly 750x expansion from a 2MB string to a 1.5GB+ footprint.
The key insight is thatobject inflationis the root cause. It isn’t about the input being “large”, it’s about the multiplicative cost of turning each token into a rich object. A 2MB string is a perfectly normal payload by any standard. But the parser amplifies it by orders of magnitude.
A vulnerability in a parser library is concerning on its own. But parsers don’t exist in isolation, they’re embedded deep in application stacks. When the parser crashes, the application may crash with it.
We traced this cascade through several major projects.
Apache Superset(~75k stars) uses SQLGlot under the hood. Its SQL Lab feature allows authenticated users to write and execute queries.
The weakness lives in thepre-execution phase. When a user submits a query through SQL Lab, Superset hands the raw SQL to SQLGlot for parsing and validationbeforeit ever reaches the database and before any complexity checks are applied. There is no limit on query size, nesting depth, or AST node count at this boundary. An authenticated user with ordinary SQL Lab access is enough; the query never has to run.
Depending on the payload size, the attack produces two distinct denial-of-service states:
The attack is simple: authenticate as a normal user, then send a batch of concurrent requests to/api/v1/sqllab/execute/, each carrying a payload built from a large number of columns of a deeply nestedx=x=x…expression. The number of columns determines which failure mode you hit:
The exact thresholds depend on available memory – a 16 GB host behaves differently from a 4 GB container – but either way, a single authenticated user takes down SQL Lab, and the shared worker pool, for everyone.
Dify(~150k stars) Uses SQLGlot within its plugin ecosystem. We found two vulnerable plugins – db-client-node and dify-bigquery-plugin – and that the plugin framework’s architecture amplified the parser vulnerability into a system-wide failure.
A large SQL payload (10,000 columns x 60 depth) executed through a workflow that triggers 5 concurrent database queries caused a5GB RAM spike. This didn’t just kill the plugin – it destroyed the IPC bridge between Dify’s Go-based daemon and its Python workers.
The daemon lost track of healthy workers. The system entered a “Blackout” state for approximately 60 seconds, during whichalltool calls across the entire framework returned errors – not just those involving the parser.
SQLFluff Online(source) exposes the parser through a web API. The frontend enforces a 3,000-character input limit. The backend does not.
By sending a crafted payload directly to the/fluffedendpoint – bypassing the frontend – a single request consumed 2GB+ of RAM and saturated the CPU. The service locked up entirely.
Pathway(~60k stars) uses SQLGlot internally and exposes apw.sqlinterface that accepts user queries. We submitted a crafted query (10,000 columns x 70 depth) and watched memory grow unboundedly, consuming8GB+of RAM. The server was killed withOOMKilled: trueandExitCode: 137. Pathway produced no error or warning before the crash.
The security community has spent decades hardening systems againstSQL Injection,the manipulation of query structure to execute unauthorized commands. This is a different class of attack entirely.
Parser Exhaustiondoesn’t inject anything. It doesn’t exploit string concatenation or missing parameterization. The queries are syntactically valid. They would parse correctly on any SQL grammar. They just happen to be shaped in a way that overwhelms the parser’s resource consumption.
This distinction matters because Parser Exhaustion bypasses many traditional defenses:
As the industry moves towardautomated SQL generationandLLM-integrated data tools, this attack surface grows. LLMs can generate arbitrarily complex SQL. If that SQL passes through a parser – for validation, linting, or transpilation – the parser becomes an attack vector. Not because the SQL is malicious in the traditional sense, but because it’s expensive.
The parser is no longer just a utility. It’s a trust boundary.
The good news: these vulnerabilities are straightforward to mitigate. Simple limits on recursion depth and AST size can harden parsers against this entire class of attack.
1. Recursion depth limit:abort parsing if nesting exceeds a threshold:
2. AST node limit:count nodes during construction and abort if a threshold is exceeded:
We reported both issues to the maintainers of SQLGlot and SQLFluff and contributed to the fixes. SQLGlot now enforces a configurable recursion/complexity limit during parsing (merged ahead of the v30.5.0 release), and SQLFluff adopted comparable guards. If you depend on either library, upgrade to a patched version and keep the default limits enabled.
The bad news: not all parsers support limits. If the parser you use enforces a recursion or node limit, enabling it is the best way to mitigate these vulnerabilities. If it doesn’t, defend at the application level:
SQL parsers are not special. The root causes – unbounded recursion and object inflation – are properties of recursive-descent parsers in general. We found the same patterns in query languages built on entirely different grammars.
Neo4j’sCypherquery language (~17k stars) exhibits both failure modes:
GraphQL (~20k stars) is the instructive counter-example: the spec supports amax_tokenslimit, but whether it’s enforced by default varies by implementation.
The takeaway: this is a parser-design problem, not a SQL problem. Any parser that turns untrusted text into a rich object tree without bounding depth or node count is exposed.
We disclosed vulnerabilities in SQLGlot, SQLFluff (CVE-2026-46373,CVE-2026-46374), and several downstream applications – all stemming from the same root cause:parsers that trust their input to be reasonable. Beyond reporting, we worked with both maintainer teams and contributed to the fixes that now ship upstream, so every project depending on these libraries benefits by upgrading. The fixes themselves are straightforward: depth limits, node counting, input size validation. But the lesson is broader.
Parsers have quietly become critical infrastructure. They’re embedded in data platforms, CI/CD pipelines, AI agents, and production workflows. Yet they’ve historically been treated as safe, deterministic utilities that “just work.” Our findings show that even syntactically correct queries can be weaponized to dismantle the systems that depend on them.
As the industry moves toward automated SQL generation and LLM-integrated data tools, the parser is no longer a passive utility – it’s an active attack surface. Hardening it requires the same discipline we apply to any other trust boundary: validate input, limit resource consumption, and assume that anything coming from outside the system is potentially adversarial.
It’s time to move beyond SQL Injection. Welcome toParser Exhaustion.
Protect your business for 30 days on Imperva.
Protect your business for 30 days on Imperva.
RonMasas
Oct 22, 20264 min read
NadavAvital
,BarMenachem
Oct 21, 20266 min read
GabiSharadin
Oct 8, 20264 min read
GabiSharadin
Sep 10, 20262 min read
RonMasas
Aug 10, 20268 min read
MulyLevy
Aug 10, 20264 min read
Cookie PreferencesTrust CenterModern Slavery StatementPrivacyLegal
Cookie PreferencesTrust CenterModern Slavery StatementPrivacyLegal
Copyright © 2026 Imperva. All rights reserved
