Why an operation allowlist is not enough: the case of UPDATE without WHERE

Allowlists block by the first token. AST parsing evaluates the full semantics. The difference matters when the AI agent generates exactly the patterns an allowlist cannot detect.

8 min read
AST PARSING SQL SECURITY

The problem with allowlists

When engineering teams think about protecting a database from LLM queries, the first idea is usually an allowlist: only allow SELECT, block DELETE and DROP.

The problem is that allowlists operate on the first token of the query. SELECT always passes. DELETE always blocks. But an intelligent AI agent generates queries that the allowlist cannot classify correctly.

An allowlist does not know the difference between UPDATE users SET status = "inactive" WHERE id = $1 and UPDATE users SET status = "deleted".

Vericto evaluates the complete tree in depth. It does not matter at what level the destructive node is: if it is in the tree, it is detected.

What an allowlist cannot detect

These are the four patterns that AI agents frequently generate and that an allowlist cannot detect:

1. UPDATE without WHERE

-- Un agente responde a "actualiza el precio del producto"
-- con contexto ambiguo y genera esto:
UPDATE products SET price = 0;

Modifies all rows in the table. Syntactically valid, semantically catastrophic.

2. DELETE with always-true WHERE

-- El LLM fue instruido para "limpiar registros viejos" pero
-- generó una condición trivialmente verdadera:
DELETE FROM sessions WHERE 1=1;

The allowlist blocks it for being DELETE. But the agent can reframe it as a mass UPDATE.

3. TRUNCATE inside a CTE

-- Patrón observado en agentes que construyen queries multi-step:
WITH cleanup AS (
  SELECT id FROM old_data
)
TRUNCATE TABLE orders;

The query starts with WITH: a first-token allowlist does not detect it as TRUNCATE.

4. DROP TABLE in nested subquery

-- Raro pero documentado en modelos con function calling agresivo:
DO $$
BEGIN
  DROP TABLE IF EXISTS users;
END $$;

Documented in advanced reasoning models. The outer query can be an innocuous SELECT.

How AST parsing works against these cases

The AST (Abstract Syntax Tree) is the structured representation of a query. Instead of evaluating the text, Vericto evaluates the semantic tree.

For an UPDATE without WHERE, the tree has an UpdateStmt node with the property whereClause = null. For a CTE with TRUNCATE, the tree has a CommonTableExpr node containing a TruncateStmt.

UpdateStmt
  ├── relation: "products"
  ├── targetList:
  │   └── ResTarget
  │       ├── name: "price"
  │       └── val: Integer(0)
  └── whereClause: NULL  ← el nodo que activa VERICTO-042

VERICTO-042 detects UPDATE without WHERE. VERICTO-031 detects UPDATE without WHERE in CTEs. Both rules are active by default.

The WHERE 1=1 pattern is the most common case. The allowlist allows it because it is a SELECT. AST parsing detects that the WHERE is trivially true.

DeleteStmt
  ├── relation: "sessions"
  └── whereClause:
      └── A_Expr
          ├── kind: AEXPR_OP
          ├── name: "="
          ├── lexpr: Integer(1)
          └── rexpr: Integer(1)  ← ambos operandos son literales iguales
                                  → evaluable estáticamente → siempre true

AST parsing produces the same result for the same query, always. You can write a test that verifies the exact behavior. You can audit the blocking decision. You can certify the control.

Aren't database permissions enough?

This is the most common objection. "If the DB user only has SELECT, it cannot cause harm." The problem is this is not true in practice.

The least privilege principle is correct, but applying it correctly to AI agents is notoriously difficult. Vericto complements permissions with a semantic layer.

Permissions and AST parsing are complementary layers. Permissions limit what the agent can do. AST parsing validates that what it does makes sense.

Database permissions and AST parsing are complementary defense layers, not alternatives. Vericto does not replace permissions: it complements them with semantic validation.

Why determinism matters

The alternative to AST parsing for detecting dangerous queries is an ML model. ML models have false positives, stochastic variance, and are not auditable. For a security control, this is unacceptable.

  • Database permissions are fragile and hard to audit in complex systems
  • AI agents need write access to function (INSERT results, UPDATE state, etc.)
  • A revoked permission breaks agent functionality, not just destructive operations

Determinism is not just a technical property: it is a requirement for the control to be auditable and certifiable for SOC2 or ISO27001.

How to implement it in <5 minutes

If you have an LLM-to-SQL pipeline, Vericto integration requires a single change: the host in your connection string.

- DATABASE_URL=postgres://user:pass@prod-db.host:5432/mydb
+ DATABASE_URL=postgres://user:pass@localhost:5433/mydb

Your ORM or driver does not know there is a proxy in the middle. Clean queries pass through. Destructive ones are blocked with a standard permissions error.

Vericto's 28 standard rules cover all these patterns.