Skip to main content
Updated in v7.0.0 (breaking). SQLVerifier.verify_sql() now returns a DiagnosticResult instead of an ad-hoc dict, and a proven-malicious query is reported as VERIFIED (truth) with a separate admission decision (policy). See the changelog for migration details.
SQL query validation and injection detection.

Overview

The SQL Engine validates queries for:
  • SQL injection patterns
  • Destructive operations
  • Schema compliance
  • Syntax correctness
Verification is static AST analysis (SQLGlot). The engine never connects to a database.

The DiagnosticResult contract

verify_sql() returns a DiagnosticResult with a status, an agent-safe agent_message, structured developer_fields, and a proof_ref bound to the query AST: Proving that a query is malicious is a successful proof, so a malicious query is VERIFIED — not BLOCKED. BLOCKED is reserved for cases where verification itself could not complete, and blocked results never carry a proof_ref. If the DDL schema fails to parse, the incomplete analysis is BLOCKED even when the query itself looks malicious (schema_parse_error takes precedence). agent_message never leaks detection rules, rule IDs, or raw parser output. Rule-level detail lives in developer_fields.

Admission is a separate decision

Do not gate execution on status alone. POST /verify/sql returns an explicit admission field (ADMIT or BLOCKED) alongside the verdict. A malicious query is VERIFIED at the truth layer but BLOCKED at the admission layer. Gate on admission (or developer_fields.is_valid), never on status == "VERIFIED".

Usage

Schema compliance

When you pass schema_ddl, every table the query reads or writes must be declared in that DDL. A reference to an undeclared table is an admission failure: the result is BLOCKED with is_valid: false and constraint_id: "sql_verifier.schema_violation". Names the query defines itself, such as CTEs, are not treated as tables. Without schema_ddl, the engine does not check table names.
Before v7.2.3, a query on a table outside the schema was admitted with a warning. See GHSA-q5g6-6cw2-cjm3.

MySQL and MariaDB executable comments

MySQL and MariaDB run SQL placed inside executable comments (/*! ... */, /*!NNNNN ... */, and /*M! ... */). The SQL engine expands these comments before analysis, so injection, destructive-operation, and schema checks apply to the SQL inside them. The engine expands them whatever dialect you declare. developer_fields.executable_comments_expanded is true when the query contained an executable comment.

Injection detection

Detected patterns

Destructive operations

Administrative commands

The SQL engine also blocks administrative SQL commands by default:
A resource-limit violation is a CRITICAL admission failure but not evidence of malicious intent. Only true-malice issue types set malicious_classification: true.

Supported dialects

  • PostgreSQL
  • MySQL
  • SQLite
  • SQL Server
  • BigQuery