Reglas Custom.

Define condiciones AST determinísticas propias para bloquear queries específicas de tu stack — sin IA, sin varianza estocástica.

¿Qué son las reglas custom?

Las reglas estándar de Vetro cubren los patrones destructivos más comunes (DELETE sin WHERE, DROP TABLE, TRUNCATE, etc.). Las reglas custom permiten extender ese ruleset con condiciones específicas de tu negocio, definidas mediante una condición YAML sobre el árbol sintáctico AST de la query.

Como todas las reglas de Vetro, las custom son determinísticas: el mismo input produce siempre el mismo resultado. No hay modelos de ML, no hay varianza. Una query cumple la condición o no la cumple — sin ambigüedad.

Ejemplos de uso habitual:

  • Bloquear SELECT * en tablas de pagos o usuarios (evita exfiltración masiva de datos)
  • Prevenir UPDATE sin cláusula WHERE en tablas de alta criticidad
  • Detectar llamadas a funciones peligrosas como SLEEP() o PG_SLEEP()
  • Bloquear queries que acceden a esquemas internos (information_schema, pg_catalog)
  • Forzar el uso de índices en columnas específicas (prohibir queries sin predicado)

Disponibilidad por plan

Las reglas custom están disponibles desde el plan BUILDER ($49/mes).

PlanReglas customLímite
FreeNo disponible
Builder ($49/mes)✅ IncluidoHasta 50 reglas custom
Team ($149/mes)✅ IncluidoIlimitadas

Si intentas crear una regla custom en el plan Free, la API responde con 403 Payment Required y un link de upgrade.

Esquema YAML

Cada regla custom lleva una condición YAML que define cuándo Vetro debe bloquear una query. El YAML debe tener al menos los campos rule y node_type.

rule: nombre-interno-de-la-regla   # identificador libre
node_type: DeleteStmt              # tipo de nodo AST a capturar
condition:
  where_clause: null               # solo si falta WHERE

Campos del YAML

rule Requerido string

Identificador interno de la regla. Aparece en los logs y el audit trail. Usa kebab-case, ej: block-select-star-payments.

node_type Requerido string

Tipo de nodo del AST que activa la condición. Ver tipos de nodo disponibles.

condition Opcional objeto

Predicados adicionales sobre el nodo. Si se omite, la regla se dispara para todo nodo del node_type indicado. Ver condiciones disponibles.

message Opcional string

Mensaje personalizado que se incluye en la respuesta de bloqueo y en el audit trail. Máx. 256 caracteres.

Tipos de nodo AST

Los nodos del AST representan el tipo de sentencia o expresión SQL que Vetro detecta en el árbol sintáctico. El dialecto determina qué parser se usa (pg_query para PostgreSQL, sqlparser-rs para MySQL).

node_typeDescripciónDialecto
DeleteStmtSentencia DELETEpostgres / all
UpdateStmtSentencia UPDATEpostgres / all
SelectStmtSentencia SELECTpostgres / all
InsertStmtSentencia INSERTpostgres / all
DropStmtSentencia DROP (TABLE, DATABASE, INDEX, SCHEMA)postgres / all
TruncateStmtSentencia TRUNCATEpostgres
AlterTableStmtALTER TABLE (DROP COLUMN, RENAME, etc.)postgres
FuncCallLlamada a función SQL (SLEEP, PG_SLEEP, etc.)postgres / all

Condiciones disponibles

Dentro de condition: puedes usar los siguientes predicados según el tipo de nodo:

Para DELETE / UPDATE / SELECT

PredicadoValorSignificado
where_clause: nullnullLa query NO tiene cláusula WHERE
where_always_true: truetrueWHERE trivialmente verdadero (1=1, true)

Para SELECT

PredicadoValorSignificado
target_list: "*""*"La query usa SELECT *
has_limit: falsefalseLa query no incluye LIMIT

Para FuncCall

PredicadoValorSignificado
func_name: "nombre"stringNombre de la función a bloquear (case-insensitive)

Para DropStmt

PredicadoValorSignificado
object_type: "table""table", "schema", "index"Tipo de objeto que se está eliminando

Ejemplos prácticos

1. Bloquear SELECT * (exfiltración masiva)

rule: block-select-star
node_type: SelectStmt
condition:
  target_list: "*"

Bloquea queries como SELECT * FROM users o SELECT * FROM payments. Permite queries con columnas explícitas como SELECT id, email FROM users.

2. Bloquear UPDATE sin WHERE

rule: block-update-no-where
node_type: UpdateStmt
condition:
  where_clause: null

Bloquea UPDATE users SET status = 'blocked' pero permite UPDATE users SET status = 'blocked' WHERE id = $1.

3. Detectar tautologías SQL injection

rule: block-or-tautology
node_type: DeleteStmt
condition:
  where_always_true: true

Bloquea queries como DELETE FROM users WHERE id = 1 OR 1=1 detectando el branch OR trivialmente verdadero en el AST.

4. Bloquear llamadas a SLEEP (DoS)

rule: block-sleep-calls
node_type: FuncCall
condition:
  func_name: sleep

Bloquea SELECT SLEEP(10) (MySQL) y SELECT PG_SLEEP(10) (PostgreSQL) para prevenir ataques de Denial of Service.

5. Bloquear SELECT sin LIMIT

rule: require-limit-on-select
node_type: SelectStmt
condition:
  has_limit: false
message: "Las queries SELECT deben incluir cláusula LIMIT para evitar scans completos de tabla"

Útil para tablas muy grandes donde un full scan sin límite puede degradar el rendimiento significativamente.

6. Bloquear DROP de cualquier objeto

rule: block-all-drops
node_type: DropStmt

Sin condition:, la regla se dispara para cualquier DROP (TABLE, INDEX, SCHEMA). Útil en entornos de producción donde ningún DROP debe ejecutarse desde la aplicación.

Previsualización antes de activar

Antes de guardar una regla custom, el dashboard ofrece una previsualización que evalúa el YAML contra las queries históricas del workspace de los últimos 7 días.

La previsualización muestra:

  • Si el YAML es válido (validation_result.valid: true/false)
  • Cuántas queries históricas hubiera bloqueado esta regla
  • Un ejemplo de query que dispara la condición
  • Lista de eventos del audit trail que coinciden

La previsualización es solo de lectura — no bloquea nada. La regla solo empieza a bloquear queries en tiempo real cuando haces clic en Crear regla.

API REST para reglas custom

Crear una regla custom

POST /api/v1/workspaces/:workspace_id/rules/custom
Authorization: Bearer <token>

{
  "name": "Bloquear SELECT * en pagos",
  "severity": "warning",
  "dialect": "postgres",
  "ast_condition_yaml": "rule: block-select-star\nnode_type: SelectStmt\ncondition:\n  target_list: \"*\""
}

// Response 201
{
  "rule_id": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
  "code": "CUSTOM-001",
  "name": "Bloquear SELECT * en pagos",
  "severity": "warning",
  "is_active": true,
  "created_at": "2025-06-20T10:00:00Z",
  "validation_result": { "valid": true, "errors": [] }
}

Previsualizar antes de guardar

POST /api/v1/workspaces/:workspace_id/rules/custom/preview
Authorization: Bearer <token>

{
  "ast_condition_yaml": "rule: block-select-star\nnode_type: SelectStmt\ncondition:\n  target_list: \"*\"",
  "dialect": "postgres",
  "lookback_days": 7
}

// Response 200
{
  "matching_queries": [...],
  "total_matches": 3,
  "validation_result": { "valid": true, "errors": [] },
  "example_triggering_query": "SELECT * FROM users"
}

Campos requeridos

CampoTipoDescripción
namestring (1–128 chars)Nombre descriptivo de la regla
severity"critical" / "warning" / "info"Severidad — determina si dispara alertas
dialect"postgres" / "mysql" / "all"Dialecto SQL al que aplica la regla
ast_condition_yamlstring YAML (10–16384 chars)Condición AST que define cuándo bloquear

Limitaciones actuales

  • Las condiciones YAML solo soportan los predicados documentados arriba — no se puede escribir expresiones arbitrarias sobre el AST todavía.
  • El campo condition.table_name (filtrar por nombre de tabla específica) está en roadmap pero no disponible aún.
  • Máximo 50 reglas custom en plan Builder, ilimitadas en plan Team.
  • El YAML se valida en el servidor — un YAML sintácticamente incorrecto devuelve 400 Bad Request con los errores de validación.
  • Las reglas custom no soportan CTE data-modifying todavía (ej: WITH x AS (DELETE ...)). Las reglas estándar VETRO-001 a VETRO-020 sí las detectan.

Usa siempre la previsualización antes de activar una regla custom en producción. Una regla mal configurada puede bloquear queries legítimas. El equipo de Vetro recomienda activar primero en staging y validar durante 24h antes de pasar a producción.

¿Tienes un caso de uso que las condiciones actuales no cubren? Escríbenos — los casos reales de clientes guían el roadmap de nuevos predicados.