20 reglas. Ninguna usa ML.

Cada regla es una condición determinística sobre el árbol sintáctico AST. El mismo input siempre produce el mismo resultado. Sin varianza estocástica, sin drift.

Cómo funcionan las reglas

Cuando una query llega al proxy de Vetro, el parser construye el AST (Abstract Syntax Tree) completo de la query. El engine recorre el árbol en profundidad buscando nodos que violen las condiciones definidas en cada regla activa.

El proceso es siempre el mismo:

  1. La query SQL llega al proxy como texto plano
  2. El parser selecciona el parser correcto según el dialecto (pg_query para Postgres, sqlparser-rs para MySQL, SQLite y Snowflake)
  3. El AST completo se construye en memoria
  4. El engine evalúa cada regla activa contra el árbol
  5. Si alguna regla se viola, la query es bloqueada antes de llegar a la base de datos

Cada regla define exactamente cinco propiedades:

  • Código — identificador único en formato VETRO-XXX o CUSTOM-XXX
  • Condición AST — el nodo y la propiedad que se evalúa (ej: DeleteStmt > WhereClause = NULL)
  • Dialecto(s) — uno o varios dialectos SQL donde aplica la regla
  • Severidad — CRITICAL, HIGH o MEDIUM
  • Query segura sugerida — la versión corregida de la query que se muestra en el log de bloqueo

El parsing AST añade en promedio menos de 0.4ms al tiempo de respuesta. El p99 total del proxy (parsing + evaluación de reglas + overhead de red) es inferior a 2ms.

Niveles de severidad y acciones por defecto

Vetro usa la taxonomía CVSS de 5 niveles. La acción por defecto se puede personalizar por workspace con una EnforcementPolicy.

Severidad Acción por defecto Comportamiento Alertas
CRITICAL BLOCK Bloqueo inmediato de la query. SQLSTATE 42501 al cliente. Alerta en tiempo real via webhook y dashboard
HIGH BLOCK Bloqueo de la query, registro completo en el audit trail. Alerta en tiempo real
MEDIUM FLAG La query se reenvía al upstream. Se registra y genera alerta pero no bloquea. Alerta (FLAG) en dashboard y webhook
LOW MONITOR La query se reenvía. Solo se registra en telemetría, sin alerta. Solo telemetría / audit trail
INFORMATIONAL MONITOR La query se reenvía. Registro informativo, sin acción. Solo métricas

Los planes Builder y superiores permiten personalizar la EnforcementPolicy de cada workspace (cambiar la acción por severidad, activar el Modo Monitor para dry-run).

Reglas CRITICAL

Las reglas CRITICAL detectan operaciones que pueden causar pérdida irreversible de datos masivos. Se activan en todos los dialectos soportados salvo indicación contraria.

Código Nombre Condición AST Dialectos Query segura sugerida
VETRO-001 DELETE sin WHERE DeleteStmt > WhereClause = NULL Todos DELETE FROM {tabla} WHERE id = $1
VETRO-003 DELETE con WHERE siempre verdadero DeleteStmt > WhereClause = ALWAYS_TRUE (1=1, true) Todos DELETE FROM {tabla} WHERE id = $1
VETRO-010 DROP TABLE / DROP DATABASE DropStmt (excluye DROP INDEX) Todos Usa migraciones versionadas (Flyway, Prisma Migrate, Alembic)
VETRO-011 TRUNCATE TABLE TruncateStmt (nodo presente) Todos DELETE FROM {tabla} WHERE created_at < NOW() - INTERVAL '90 days'
VETRO-012 DROP SCHEMA DropStmt > ObjectType = SCHEMA Todos Usa migraciones versionadas
VETRO-030 UPDATE sin WHERE (tablas principales) UpdateStmt > WhereClause != Present Todos UPDATE {tabla} SET {col} = $1 WHERE id = $2
VETRO-042 UPDATE sin cláusula WHERE UpdateStmt > WhereClause = NULL (incluye WHERE trivial) Todos UPDATE {tabla} SET {col} = $1 WHERE id = $2

Reglas HIGH

Las reglas HIGH detectan operaciones de alto riesgo que pueden causar pérdida parcial de datos o cambios estructurales irreversibles.

Código Nombre Condición AST Dialectos Query segura sugerida
VETRO-002 DELETE con LIMIT 0 DeleteStmt > LimitCount = 0 MySQL, SQLite DELETE FROM {tabla} WHERE id = $1 LIMIT 1
VETRO-013 DROP INDEX sin IF EXISTS DropStmt > ObjectType = INDEX & IF_EXISTS = false Todos DROP INDEX IF EXISTS {index_name}
VETRO-015 ALTER TABLE DROP COLUMN AlterTableStmt > AlterTableCmd.subtype = DROP_COLUMN Todos Usa soft-delete con columna deleted_at o migración versionada
VETRO-016 ALTER TABLE RENAME AlterTableStmt > Rename Todos Usa herramienta de migración y actualiza todas las referencias primero
VETRO-031 UPDATE sin WHERE anidado en CTE WithClause > UpdateStmt > WhereClause = NULL Postgres, Snowflake Agregar WHERE con predicado específico al UPDATE dentro del CTE
VETRO-033 DELETE sin WHERE en subquery/CTE WithClause/SubLink > DeleteStmt > WhereClause = NULL Todos Reescribir como DELETE con JOIN y WHERE explícitos
VETRO-040 INSERT INTO … SELECT sin filtro InsertStmt > source = SelectStmt Todos INSERT INTO {tabla} SELECT ... WHERE <condición> LIMIT N
VETRO-070 Uso de SLEEP() o PG_SLEEP() FunctionCall > name = sleep|pg_sleep Todos Eliminar la llamada a SLEEP del pipeline

Reglas MEDIUM

Las reglas MEDIUM detectan patrones de queries que pueden indicar un agente de IA operando sin contexto adecuado, o que podrían degradar el rendimiento de la base de datos.

Código Nombre Condición AST Dialectos Query segura sugerida
VETRO-050 SELECT sin LIMIT SelectStmt > LimitCount = NULL Todos SELECT ... WHERE <condición> LIMIT 1000
VETRO-051 SELECT * sin WHERE SelectStmt > TargetEntry = STAR & WhereClause = NULL Todos SELECT col1, col2 FROM ... WHERE <condición>
VETRO-060 INSERT sin columnas explícitas InsertStmt > Cols = NULL Todos INSERT INTO {tabla} (col1, col2) VALUES ($1, $2)
VETRO-061 INSERT batch con más de 10k filas InsertStmt > ValuesList count > 10000 Todos Dividir en lotes de ≤1,000 filas con múltiples INSERT o COPY

Reglas de SQL Injection

Detección determinística de patrones de SQL injection en queries generadas por LLMs. A diferencia de los WAFs tradicionales basados en patrones de texto, Vetro analiza el AST — lo que hace que la detección sea inmune a ofuscaciones que preservan la semántica.

Código Nombre Condición AST Dialectos Por qué cero falsos positivos
VETRO-090 Tautología OR en WHERE WhereClause > BoolExpr(OR) > always_true_branch Todos Un LLM generando queries legítimas nunca tiene razón para incluir OR 1=1. Solo existen en intentos de bypass de autenticación.

Cobertura de VETRO-090: aplica a las cláusulas WHERE de SELECT, DELETE y UPDATE. Detecta patrones como OR 1=1, OR 'a'='a', OR true, y tautologías anidadas como AND (condición OR 1=1).

Reglas custom (YAML)

Los planes Builder y superiores permiten definir reglas personalizadas en YAML. Puedes crear reglas que bloqueen operaciones específicas en tablas concretas, sin tocar el código de tu aplicación.

Las reglas custom se evalúan después de las reglas built-in con la misma latencia. Ejemplo de regla custom:

id: CUSTOM-001
name: Bloquear UPDATE en tabla payments
severity: critical
dialect: postgres
condition:
  node: UpdateStmt
  relation: payments
message: "Las actualizaciones en la tabla payments requieren revisión manual"

Los campos disponibles para condición son:

  • node — tipo de nodo AST (ej: UpdateStmt, DeleteStmt, SelectStmt)
  • relation — nombre exacto de la tabla (opcional)
  • where_nulltrue para requerir ausencia de WHERE clause
  • columns — lista de columnas que activan la regla (opcional)

Las reglas custom se cargan en caliente sin reiniciar el proxy. El tiempo de propagación es inferior a 5 segundos desde que guardas el archivo en el dashboard.

Las reglas custom también se pueden versionar en Git y aplicar via CLI: vetro rules push --file custom-rules.yaml --workspace ws_xxx

Índice de códigos

Código Descripción Severidad Acción por defecto
VETRO-001DELETE sin cláusula WHERECRITICALBLOCK
VETRO-002DELETE con LIMIT 0 (MySQL/SQLite)HIGHBLOCK
VETRO-003DELETE con WHERE siempre verdadero (1=1, true)CRITICALBLOCK
VETRO-010DROP TABLE o DROP DATABASECRITICALBLOCK
VETRO-011TRUNCATE TABLECRITICALBLOCK
VETRO-012DROP SCHEMACRITICALBLOCK
VETRO-013DROP INDEX sin IF EXISTSHIGHBLOCK
VETRO-015ALTER TABLE DROP COLUMNHIGHBLOCK
VETRO-016ALTER TABLE RENAME (tabla o columna)HIGHBLOCK
VETRO-030UPDATE sin WHERE en tabla principalCRITICALBLOCK
VETRO-031UPDATE sin WHERE dentro de CTEHIGHBLOCK
VETRO-033DELETE sin WHERE en subquery o CTEHIGHBLOCK
VETRO-040INSERT INTO … SELECT sin filtroHIGHBLOCK
VETRO-042UPDATE sin cláusula WHERECRITICALBLOCK
VETRO-050SELECT sin LIMITMEDIUMFLAG
VETRO-051SELECT * sin cláusula WHEREMEDIUMFLAG
VETRO-060INSERT sin columnas explícitasLOWMONITOR
VETRO-061INSERT batch con más de 10k filasMEDIUMFLAG
VETRO-070Uso de SLEEP() o PG_SLEEP()HIGHBLOCK
VETRO-090SQL injection — tautología OR en WHERE (OR 1=1)CRITICALBLOCK