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:
- La query SQL llega al proxy como texto plano
- El parser selecciona el parser correcto según el dialecto (
pg_querypara Postgres,sqlparser-rspara MySQL, SQLite y Snowflake) - El AST completo se construye en memoria
- El engine evalúa cada regla activa contra el árbol
- 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-XXXoCUSTOM-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_null—truepara requerir ausencia de WHERE clausecolumns— 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-001 | DELETE sin cláusula WHERE | CRITICAL | BLOCK |
VETRO-002 | DELETE con LIMIT 0 (MySQL/SQLite) | HIGH | BLOCK |
VETRO-003 | DELETE con WHERE siempre verdadero (1=1, true) | CRITICAL | BLOCK |
VETRO-010 | DROP TABLE o DROP DATABASE | CRITICAL | BLOCK |
VETRO-011 | TRUNCATE TABLE | CRITICAL | BLOCK |
VETRO-012 | DROP SCHEMA | CRITICAL | BLOCK |
VETRO-013 | DROP INDEX sin IF EXISTS | HIGH | BLOCK |
VETRO-015 | ALTER TABLE DROP COLUMN | HIGH | BLOCK |
VETRO-016 | ALTER TABLE RENAME (tabla o columna) | HIGH | BLOCK |
VETRO-030 | UPDATE sin WHERE en tabla principal | CRITICAL | BLOCK |
VETRO-031 | UPDATE sin WHERE dentro de CTE | HIGH | BLOCK |
VETRO-033 | DELETE sin WHERE en subquery o CTE | HIGH | BLOCK |
VETRO-040 | INSERT INTO … SELECT sin filtro | HIGH | BLOCK |
VETRO-042 | UPDATE sin cláusula WHERE | CRITICAL | BLOCK |
VETRO-050 | SELECT sin LIMIT | MEDIUM | FLAG |
VETRO-051 | SELECT * sin cláusula WHERE | MEDIUM | FLAG |
VETRO-060 | INSERT sin columnas explícitas | LOW | MONITOR |
VETRO-061 | INSERT batch con más de 10k filas | MEDIUM | FLAG |
VETRO-070 | Uso de SLEEP() o PG_SLEEP() | HIGH | BLOCK |
VETRO-090 | SQL injection — tautología OR en WHERE (OR 1=1) | CRITICAL | BLOCK |