Ver exactamente qué bloquea Vetro y por qué.
Ejemplos reales de queries generadas por agentes de IA. Para cada una: el AST infractor, la regla activada, y la versión segura sugerida.
Estos son ejemplos reales de queries que agentes de IA (LangChain, Vercel AI SDK, OpenAI function calling, MCP servers, etc.) generan al conectarse a bases de datos en producción. Hemos anonimizado los nombres de tablas pero el patrón de cada query es idéntico al original.
DELETE queries
DELETE masivo sin condición
BLOQUEADADELETE FROM users;
DeleteStmt > WhereClause = NULL
VETRO-001
CRITICAL
DELETE FROM users WHERE id = $1;
DELETE en CTE sin WHERE
BLOQUEADAWITH old_orders AS (
DELETE FROM orders
RETURNING id
)
SELECT COUNT(*) FROM old_orders;
WithClause > DeleteStmt > WhereClause = NULL
VETRO-001
CRITICAL
WITH old_orders AS (
DELETE FROM orders
WHERE created_at < NOW() - INTERVAL '90 days'
RETURNING id
)
SELECT COUNT(*) FROM old_orders;
DELETE con WHERE siempre verdadero
BLOQUEADADELETE FROM products WHERE 1=1;
DeleteStmt > WhereClause > BoolExpr = ALWAYS_TRUE
VETRO-003
CRITICAL
DELETE FROM products WHERE id = $1;
DELETE con subquery sin predicado externo
BLOQUEADADELETE FROM logs
WHERE id IN (SELECT id FROM logs);
DeleteStmt > WhereClause > SubLink — sin predicado adicional
VETRO-033
HIGH
DELETE FROM logs
WHERE id IN (
SELECT id FROM logs
WHERE created_at < NOW() - INTERVAL '30 days'
);
UPDATE queries
UPDATE de rol a todos los usuarios
BLOQUEADAUPDATE users SET role = 'admin';
UpdateStmt > WhereClause = NULL
VETRO-042
CRITICAL
UPDATE users SET role = 'admin' WHERE id = $1;
UPDATE de precio a cero en todo el catálogo
BLOQUEADAUPDATE products SET price = 0;
UpdateStmt > WhereClause = NULL
VETRO-042
CRITICAL
UPDATE products SET price = $1 WHERE id = $2;
UPDATE masivo de estado en CTE sin WHERE
BLOQUEADAWITH affected AS (
UPDATE orders SET status = 'cancelled'
RETURNING id
)
SELECT id FROM affected;
WithClause > UpdateStmt > WhereClause = NULL
VETRO-031
HIGH
WITH affected AS (
UPDATE orders SET status = 'cancelled'
WHERE status = 'pending' AND created_at < NOW() - INTERVAL '7 days'
RETURNING id
)
SELECT id FROM affected;
DROP queries
DROP TABLE en producción
BLOQUEADADROP TABLE users;
DropStmt (nodo presente)
VETRO-010
CRITICAL
-- Usar migración versionada con herramienta de migración
-- (Flyway, Liquibase, Prisma Migrate, Alembic, Rails migrations)
-- Nunca ejecutar DROP TABLE directamente desde un agente
DROP DATABASE de producción
BLOQUEADADROP DATABASE production;
DropStmt (nodo presente, object_type = DATABASE)
VETRO-010
CRITICAL
-- Las operaciones a nivel de DATABASE nunca deben ejecutarse
-- desde agentes de IA. Requieren intervención humana con acceso
-- administrativo explícito y autorización documentada.
TRUNCATE queries
TRUNCATE en tabla de órdenes
BLOQUEADATRUNCATE TABLE orders;
TruncateStmt (nodo presente)
VETRO-011
CRITICAL
DELETE FROM orders
WHERE created_at < NOW() - INTERVAL '90 days';
TRUNCATE con CASCADE
BLOQUEADATRUNCATE TABLE users CASCADE;
TruncateStmt (nodo presente, restart_seqs = true)
VETRO-011
CRITICAL
DELETE FROM users WHERE created_at < $1
AND NOT EXISTS (
SELECT 1 FROM subscriptions
WHERE subscriptions.user_id = users.id
AND subscriptions.status = 'active'
);
Queries seguras permitidas
Vetro no bloquea queries legítimas. Cualquier operación que incluya predicados específicos y no presente patrones de destrucción masiva pasa sin modificación. La latencia añadida es inferior a 2ms p99.
DELETE con WHERE específico
PERMITIDADELETE FROM users WHERE id = $1;
DeleteStmt > WhereClause > ColumnRef (id)
UPDATE con WHERE específico
PERMITIDAUPDATE users SET name = $1 WHERE id = $2;
UpdateStmt > WhereClause > ColumnRef (id)
SELECT con filtro temporal
PERMITIDASELECT * FROM orders
WHERE created_at > NOW() - INTERVAL '7 days';
SelectStmt > WhereClause > A_Expr (temporal)
INSERT con columnas explícitas
PERMITIDAINSERT INTO events (user_id, action) VALUES ($1, $2);
InsertStmt > Cols = [user_id, action]
Casos edge
Algunos patrones merecen explicación adicional porque el comportamiento de Vetro puede no ser intuitivo a primera vista.
WHERE 1=1 — siempre verdadero
BLOQUEADADELETE FROM temp_table WHERE 1=1;
DeleteStmt > WhereClause > Integer(1) = Integer(1)
VETRO-003
CRITICAL
Un WHERE con condición siempre verdadera (1=1, true, 'a'='a') es semánticamente equivalente a no tener WHERE. El AST lo detecta evaluando si el predicado puede ser false para algún valor. Si no puede, el engine lo trata como ausente.
DELETE con LIMIT en MySQL
PERMITIDADELETE FROM mysql_table LIMIT 10;
DeleteStmt > LimitCount = 10 (MySQL)
En MySQL y SQLite, DELETE ... LIMIT N es una extensión del estándar SQL que acota el número de filas eliminadas. Un LIMIT con valor > 0 previene la eliminación masiva, por lo que Vetro lo considera un predicado efectivo. Esta excepción no aplica a Postgres ni Snowflake, donde DELETE LIMIT no es sintaxis válida.
DELETE en CTE con WHERE válido
PERMITIDAWITH deleted AS (
DELETE FROM sessions
WHERE expired_at < NOW()
RETURNING id
)
SELECT COUNT(*) FROM deleted;
WithClause > DeleteStmt > WhereClause > A_Expr (temporal)
El DELETE dentro del CTE incluye una cláusula WHERE con un predicado temporal real (expired_at < NOW()). El engine evalúa la presencia y validez del WHERE dentro del CTE exactamente igual que en un DELETE standalone.