The Critical Juncture for AI-Generated SQL
When Large Language Models (LLMs) generate PostgreSQL queries for your application, a critical security window exists: the moment after the model returns SQL text, but before your application executes it via a database connection (e.g., db.query()).
While prompt engineering can steer an LLM towards desired query structures, it offers no guarantees against malicious or unintended actions. Prompt rules alone cannot dictate which tables the application is permitted to access, nor can they prevent the execution of multiple statements in a single call, or the invocation of sensitive database functions. These are fundamental security concerns that require a more robust validation mechanism.
To address this gap, the open-source project sql-guard has emerged. Developed in TypeScript, this package focuses on parsing PostgreSQL queries into an Abstract Syntax Tree (AST). It then rigorously checks this AST against an explicitly defined security policy, rejecting any query that cannot be confidently validated.

Why Regex Fails for SQL Validation
SQL is a complex, structured language. A single query can involve intricate combinations of joins, subqueries, aliases, unions, and Common Table Expressions (CTEs). Attempting to validate such queries using regular expressions (regex) is fundamentally flawed. Regex excels at pattern matching in unstructured or semi-structured text, but it struggles to comprehend the hierarchical and relational nature of SQL.
A regex might catch a forbidden keyword like DROP TABLE, but it cannot reliably determine the context or intent behind it. For instance, it cannot differentiate between a legitimate DROP TABLE statement within a controlled script and a malicious one injected into user input. Regex also fails to understand query scope, variable binding, or function calls, making it an insufficient tool for securing dynamic SQL generation. The inherent complexity and nesting of SQL constructs make regex-based validation brittle, prone to false positives and, more critically, false negatives.
Abstract Syntax Trees: A Structured Approach
An Abstract Syntax Tree (AST) represents the grammatical structure of source code as a tree. For SQL, an AST breaks down a query into its constituent components—keywords, identifiers, operators, expressions, clauses, and functions—and arranges them in a hierarchical structure that mirrors the query's logic.
Parsing SQL into an AST allows for deep, semantic analysis. Instead of looking at raw text, the validator inspects the structured representation. This means it can understand not just what words are present, but how they relate to each other and what operation they are intended to perform.
For example, an AST can clearly distinguish between a SELECT statement targeting a permitted table and an unauthorized DELETE statement on the same table. It can identify if a query attempts to execute a stored procedure, access system catalogs, or perform multiple operations, all of which can be flagged based on predefined rules.
Defining and Enforcing Security Policies
The core of sql-guard lies in its policy definition. This policy is an explicit set of rules that dictate what is permissible within generated SQL. Administrators or developers define these rules, specifying:
- Allowed operations (e.g.,
SELECT,INSERTon specific tables). - Disallowed operations (e.g.,
DELETE,UPDATE,DROP). - Permitted tables and schemas.
- Allowed functions and procedures.
- Restrictions on multi-statement queries.
- Limitations on query complexity or resource usage.
Once the policy is defined, sql-guard parses the incoming AI-generated SQL query into an AST. It then traverses this AST, comparing each node and its context against the defined policy. If any part of the AST violates a rule—for instance, if a DELETE statement targets a table not explicitly permitted for modification—the query is rejected immediately. This provides a deterministic and auditable way to ensure that AI-generated SQL adheres to security best practices before it ever touches the database.
The sql-guard Implementation
sql-guard leverages existing robust PostgreSQL parsers to generate the AST. The package then provides a framework for defining and applying these security policies. Developers integrate sql-guard into their application's data access layer. The workflow looks like this:
- An LLM generates a PostgreSQL query.
- The generated SQL string is passed to sql-guard's validation function.
- sql-guard parses the SQL into an AST.
- The AST is checked against the configured security policy.
- If validation passes, sql-guard returns the validated SQL string (or a confirmation).
- If validation fails, sql-guard throws an error, preventing the execution of unsafe SQL.
This process effectively acts as a security gatekeeper. It ensures that even if an LLM produces a potentially harmful query, it is intercepted and neutralized before it can cause damage. The explicit policy definition means that security teams have clear visibility and control over what actions AI-generated code can perform on the database.
Broader Implications for AI in Development
The introduction of tools like sql-guard highlights a growing awareness of the security challenges posed by AI-assisted development. As LLMs become more integrated into coding workflows, the need for automated, robust validation of their output becomes paramount. This is not just about SQL; similar AST-based validation approaches could be applied to other code generation tasks, such as validating generated Python scripts, JavaScript snippets, or infrastructure-as-code configurations.
The surprising detail here is not the existence of the problem—untrusted AI output—but the elegant and precise solution offered by returning to fundamental computer science principles: parsing and structural analysis. It’s a reminder that while AI can generate novel code, its safe integration requires traditional, rigorous engineering practices. The gap between AI output and safe execution demands tools that understand the structure and semantics of the code, not just its surface-level text. This shift from regex to AST-based validation for AI-generated code represents a significant step toward more secure AI-augmented software development.
