30 reglas. Ninguna usa ML.
Todas las reglas estándar de Vericto y cómo configurarlas.
Cómo funcionan las reglas
Cuando una query llega al proxy de Vericto, 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 engine selecciona el parser correcto según el dialecto (
pg_querypara Postgres,sqlparser-rspara MySQL, Oracle, SQL Server, Snowflake y SQLite). PostgreSQL y MySQL pueden evaluarse por el proxy TCP; Oracle, SQL Server, Snowflake y SQLite, por la API HTTP - 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
VERICTO-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: uno de los 5 niveles CVSS — CRITICAL, HIGH, MEDIUM, LOW o INFORMATIONAL
- 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
Vericto 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 |
En todos los planes, el owner y los admins del workspace pueden personalizar la EnforcementPolicy (cambiar la acción por severidad o activar el modo observación). Es útil durante la adopción para observar el tráfico antes de activar bloqueos.
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 |
|---|---|---|---|---|
VERICTO-001 |
DELETE sin WHERE | DeleteStmt > WhereClause = NULL |
Todos | DELETE FROM {tabla} WHERE id = $1 |
VERICTO-003 |
DELETE con WHERE siempre verdadero | DeleteStmt > WhereClause = ALWAYS_TRUE (1=1, true) |
Todos | DELETE FROM {tabla} WHERE id = $1 |
VERICTO-010 |
DROP TABLE / DROP DATABASE | DropStmt (excluye DROP INDEX) |
Todos | Usa migraciones versionadas (Flyway, Prisma Migrate, Alembic) |
VERICTO-011 |
TRUNCATE TABLE | TruncateStmt (nodo presente) |
Todos | DELETE FROM {tabla} WHERE created_at < NOW() - INTERVAL '90 days' |
VERICTO-012 |
DROP SCHEMA | DropStmt > ObjectType = SCHEMA |
Todos | Usa migraciones versionadas |
VERICTO-030 |
UPDATE sin WHERE (tablas principales) | UpdateStmt > WhereClause != Present |
Todos | UPDATE {tabla} SET {col} = $1 WHERE id = $2 |
VERICTO-042 |
UPDATE sin cláusula WHERE | UpdateStmt > WhereClause = NULL (incluye WHERE trivial) |
Todos | UPDATE {tabla} SET {col} = $1 WHERE id = $2 |
VERICTO-080 |
COPY … TO/FROM PROGRAM | CopyStmt > program = true |
Postgres | Usa COPY … TO/FROM STDIN o rutas de archivo controladas; nunca ejecutes comandos de shell desde SQL |
VERICTO-081 |
Bloque de código anónimo DO | DoStmt (DO $$ … $$) |
Postgres | Mueve la lógica a una función/migración revisada en lugar de un bloque anónimo opaco al parser |
VERICTO-086 |
Texto SQL que MySQL y el motor leerían distinto | Texto que no se puede resolver con certeza a una sola sentencia por cómo MySQL lee sus comentarios y escapes de string | MySQL | Siempre activa: no se desactiva ni se baja de severidad. Envía SQL sin comentarios ni escapes ambiguos |
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 |
|---|---|---|---|---|
VERICTO-002 |
DELETE con LIMIT 0 | DeleteStmt > LimitCount = 0 |
MySQL, SQLite | DELETE FROM {tabla} WHERE id = $1 LIMIT 1 |
VERICTO-013 |
DROP INDEX sin IF EXISTS | DropStmt > ObjectType = INDEX & IF_EXISTS = false |
Todos | DROP INDEX IF EXISTS {index_name} |
VERICTO-015 |
ALTER TABLE DROP COLUMN | AlterTableStmt > AlterTableCmd.subtype = DROP_COLUMN |
Todos | Usa soft-delete con columna deleted_at o migración versionada |
VERICTO-016 |
ALTER TABLE RENAME | AlterTableStmt > Rename |
Todos | Usa herramienta de migración y actualiza todas las referencias primero |
VERICTO-017 |
ALTER TABLE DROP CONSTRAINT | AlterTableStmt > DropConstraint (FK/PK/CHECK, DROP PRIMARY KEY) |
Todos | Elimina la restricción solo en una migración revisada, tras confirmar que ningún dato ni código depende de ella |
VERICTO-018 |
ALTER TABLE ALTER COLUMN TYPE | AlterTableStmt > AlterColumnType |
Todos | Haz el cambio de tipo en una migración por fases (columna nueva + backfill) para evitar reescritura bloqueante o cast con pérdida |
VERICTO-019 |
ALTER TABLE DISABLE TRIGGER / RLS | AlterTableStmt > DisableTrigger | DisableRowSecurity |
Todos | No desactives triggers ni Row Level Security en producción; si es imprescindible, hazlo en una ventana controlada y reactívalos de inmediato |
VERICTO-031 |
UPDATE sin WHERE anidado en CTE | WithClause > UpdateStmt > WhereClause = NULL |
Postgres | Agregar WHERE con predicado específico al UPDATE dentro del CTE |
VERICTO-033 |
DELETE sin WHERE en subquery/CTE | WithClause/SubLink > DeleteStmt > WhereClause = NULL |
Todos | Reescribir como DELETE con JOIN y WHERE explícitos |
VERICTO-040 |
INSERT INTO … SELECT sin filtro | InsertStmt > source = SelectStmt |
Todos | INSERT INTO {tabla} SELECT ... WHERE <condición> LIMIT N |
VERICTO-070 |
Uso de SLEEP() o PG_SLEEP() | FunctionCall > name = sleep|pg_sleep |
Todos | Eliminar la llamada a SLEEP del pipeline |
VERICTO-082 |
GRANT / REVOKE | GrantStmt (GRANT o REVOKE) |
Todos | Gestiona privilegios mediante migraciones de permisos revisadas, no desde queries de aplicación |
VERICTO-083 |
MERGE | MergeStmt |
Todos | Acota el MERGE con condiciones específicas; puede mutar en masa como un UPDATE/DELETE sin WHERE efectivo |
VERICTO-084 |
CREATE TABLE AS SELECT | CreateTableAsStmt / SELECT … INTO |
Todos | Añade un WHERE/LIMIT a la fuente para no duplicar una tabla completa |
VERICTO-085 |
Lectura de una columna sensible | Proyección que deriva de una columna marcada (SELECT, RETURNING, COPY … TO) |
Todos | La deciden las columnas sensibles de cada base: lista las columnas en lugar de SELECT * y no proyectes las marcadas |
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 |
|---|---|---|---|---|
VERICTO-050 |
SELECT sin LIMIT | SelectStmt > LimitCount = NULL |
Todos | SELECT ... WHERE <condición> LIMIT 1000 |
VERICTO-051 |
SELECT * sin WHERE | SelectStmt > TargetEntry = STAR & WhereClause = NULL |
Todos | SELECT col1, col2 FROM ... WHERE <condición> |
VERICTO-060 |
INSERT sin columnas explícitas | InsertStmt > Cols = NULL |
Todos | INSERT INTO {tabla} (col1, col2) VALUES ($1, $2) |
VERICTO-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, Vericto 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é no genera falsos positivos |
|---|---|---|---|---|
VERICTO-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 VERICTO-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 de Snowflake
Siete reglas para Snowflake (vericto-engine 4.0.0). Solo leen lo que registra el parser de Snowflake, así que nunca se disparan en otro dialecto. Snowflake no tiene proxy TCP: estas reglas se aplican en la API HTTP, la CLI en CI/CD y MCP.
| Código | Nombre | Condición AST | Dialectos | Query segura sugerida |
|---|---|---|---|---|
VERICTO-091 |
Descarga a un stage o transferencia de archivos | COPY INTO @stage | 's3://…' | 'azure://…' | 'gcs://…', GET, PUT |
Snowflake | Carga desde el stage (COPY INTO tabla FROM @stage); las descargas de datos van por un proceso revisado fuera de la aplicación |
VERICTO-092 |
Stage externo o integración | CREATE|ALTER STAGE … URL = | CREDENTIALS, CREATE STORAGE | EXTERNAL ACCESS | API INTEGRATION, CREATE EXTERNAL FUNCTION |
Snowflake | Usa un stage interno; las integraciones y los stages externos se crean en migraciones revisadas |
VERICTO-093 |
Compartir con otra cuenta | GRANT … TO SHARE, CREATE SHARE, ALTER SHARE … ADD | SET ACCOUNTS, CREATE LISTING |
Snowflake | Compartir datos es una decisión de la cuenta: tómala fuera del SQL de la aplicación |
VERICTO-094 |
Recuperación reducida | DATA_RETENTION_TIME_IN_DAYS = 0, CREATE OR REPLACE TABLE | SCHEMA | DATABASE, INSERT OVERWRITE, UNDROP, ALTER ACCOUNT |
Snowflake | CREATE TABLE IF NOT EXISTS y una retención mayor que 0; en CI se marca (flag) como un DROP TABLE |
VERICTO-095 |
Costo de warehouse | CREATE|ALTER WAREHOUSE … WAREHOUSE_SIZE | MAX_CLUSTER_COUNT | AUTO_SUSPEND = 0, ALTER RESOURCE MONITOR |
Snowflake | Crea el warehouse con los valores por defecto o con AUTO_SUSPEND mayor que 0; el tamaño se cambia en una migración revisada |
VERICTO-096 |
Código que se ejecuta después | CREATE TASK | STREAM | PIPE | PROCEDURE | FUNCTION | ALERT, ALTER TASK … RESUME | MODIFY AS, EXECUTE TASK |
Snowflake | Crea tareas y procedimientos en migraciones revisadas; desde la aplicación, llámalos con CALL |
VERICTO-097 |
Cambio de rol | USE ROLE, USE SECONDARY ROLES ALL | <roles> |
Snowflake | Conéctate con el rol que la aplicación necesita; USE SECONDARY ROLES NONE no se reporta |
Reglas de SQLite
Cuatro reglas para SQLite (vericto-engine 4.1.0). Solo leen lo que registra el parser de SQLite, así que nunca se disparan en otro dialecto. SQLite es una biblioteca dentro de tu aplicación, sin servidor ni protocolo de red, así que no hay proxy TCP: estas reglas se aplican en la API de runtime, la CLI en CI/CD y MCP; los SDK de Python y Node llegan próximamente (SQLite).
| Código | Nombre | Condición AST | Dialectos | Query segura sugerida |
|---|---|---|---|---|
VERICTO-098 |
ATTACH DATABASE en SQLite | ATTACH [DATABASE] <archivo> AS <nombre> |
SQLite | No adjuntes archivos desde la aplicación; abre cada base con su propia conexión. DETACH no se reporta |
VERICTO-099 |
PRAGMA que desactiva una protección | PRAGMA writable_schema | trusted_schema = ON | foreign_keys = OFF | ignore_check_constraints = ON | journal_mode = OFF | synchronous = OFF | cell_size_check = OFF | query_only = OFF | schema_version = n | temp_store_directory |
SQLite | Lecturas (PRAGMA table_info(t)) y ajustes seguros (foreign_keys = ON, journal_mode = WAL) no se reportan; en CI se marca (flag) como un DROP TABLE |
VERICTO-100 |
Carga de extensiones o funciones de archivos | load_extension(), fts3_tokenizer(), readfile(), writefile(), edit(), fsdir(), zipfile() en cualquier cláusula |
SQLite | Carga las extensiones al abrir la conexión, desde el código de la aplicación, nunca desde SQL |
VERICTO-101 |
VACUUM INTO en SQLite | VACUUM [esquema] INTO <archivo> |
SQLite | Un VACUUM simple no se reporta; las copias de seguridad van por un proceso revisado (la API de backup de SQLite) |
Las reglas estándar en SQLite
- Se aplican tal cual (15):
VERICTO-001,002(DELETE … LIMIT 0, en builds conSQLITE_ENABLE_UPDATE_DELETE_LIMIT),010,013,015,016,019(DROP TRIGGER; SQLite no tieneDISABLE TRIGGERni RLS),030,040,042,050,051,060,061(lotes de más de 10.000 filas; no hayCOPY) y084(CREATE TABLE … AS SELECT). - Con una variante para SQLite (5):
003y090(en SQLite un string con prefijo numérico distinto de cero, comoWHERE '1abc', es verdadero; también como nombre entre comillas dobles,"1", por DQS),070(SQLite no tienesleep: se detectarandomblob(N)ozeroblob(N)con un N constante de 10.000.000 bytes o más, la sonda de inyección por tiempo),085(las máscaras de SQLite;hashbloquea) y087(nombres sin distinguir mayúsculas, esquemamainpor defecto). - No se aplican, nunca se disparan en SQLite (11):
011(TRUNCATE),012(DROP SCHEMA),017(DROP CONSTRAINT),018(ALTER COLUMN … TYPE),031y033(SQLite no tiene CTEs que modifiquen datos),080(COPY … PROGRAM),081(bloquesDO),082(GRANT/REVOKE),083(MERGE) y086(la ambigüedad léxica de MySQL). SQLite rechaza esas sentencias.
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. El YAML tiene node_type en el nivel superior y los predicados dentro de condition:
rule: block-update-on-payments
node_type: UpdateStmt
condition:
relation: payments
Los predicados de condition son ocho: relation, where_clause, where_always_true, target_list, has_limit, func_name, object_type y alter_kind. El nombre, la severidad y el dialecto no van en el YAML: son campos del formulario y de la API.
La referencia completa —los ocho tipos de nodo, los ocho predicados y ejemplos listos para copiar— está en la documentación de reglas custom.
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 se gestionan desde el dashboard del workspace. Desde el CLI puedes inspeccionar el catálogo efectivo con vericto rules list y ver el detalle de una regla con vericto rules show <CÓDIGO>.
Índice de códigos
| Código | Descripción | Severidad | Acción por defecto |
|---|---|---|---|
VERICTO-001 | DELETE sin cláusula WHERE | CRITICAL | BLOCK |
VERICTO-002 | DELETE con LIMIT 0 (MySQL, SQLite) | HIGH | BLOCK |
VERICTO-003 | DELETE con WHERE siempre verdadero (1=1, true) | CRITICAL | BLOCK |
VERICTO-010 | DROP TABLE o DROP DATABASE | CRITICAL | BLOCK |
VERICTO-011 | TRUNCATE TABLE | CRITICAL | BLOCK |
VERICTO-012 | DROP SCHEMA | CRITICAL | BLOCK |
VERICTO-013 | DROP INDEX sin IF EXISTS | HIGH | BLOCK |
VERICTO-015 | ALTER TABLE DROP COLUMN | HIGH | BLOCK |
VERICTO-016 | ALTER TABLE RENAME (tabla o columna) | HIGH | BLOCK |
VERICTO-017 | ALTER TABLE DROP CONSTRAINT (FK/PK/CHECK) | HIGH | BLOCK |
VERICTO-018 | ALTER TABLE ALTER COLUMN TYPE | HIGH | BLOCK |
VERICTO-019 | ALTER TABLE DISABLE TRIGGER / RLS | HIGH | BLOCK |
VERICTO-030 | UPDATE sin WHERE en tabla principal | CRITICAL | BLOCK |
VERICTO-031 | UPDATE sin WHERE dentro de CTE | HIGH | BLOCK |
VERICTO-033 | DELETE sin WHERE en subquery o CTE | HIGH | BLOCK |
VERICTO-040 | INSERT INTO … SELECT sin filtro | HIGH | BLOCK |
VERICTO-042 | UPDATE sin cláusula WHERE | CRITICAL | BLOCK |
VERICTO-050 | SELECT sin LIMIT | MEDIUM | FLAG |
VERICTO-051 | SELECT * sin cláusula WHERE | MEDIUM | FLAG |
VERICTO-060 | INSERT sin columnas explícitas | LOW | MONITOR |
VERICTO-061 | INSERT batch con más de 10k filas | MEDIUM | FLAG |
VERICTO-070 | Uso de SLEEP() o PG_SLEEP() | HIGH | BLOCK |
VERICTO-080 | COPY … TO/FROM PROGRAM (ejecución de shell) | CRITICAL | BLOCK |
VERICTO-081 | Bloque de código anónimo DO | CRITICAL | BLOCK |
VERICTO-082 | GRANT / REVOKE | HIGH | BLOCK |
VERICTO-083 | MERGE | HIGH | BLOCK |
VERICTO-084 | CREATE TABLE AS SELECT | HIGH | BLOCK |
VERICTO-085 | Lectura de una columna sensible | HIGH | SEGÚN LA ETIQUETA |
VERICTO-086 | Texto SQL que MySQL y el motor leerían distinto (MySQL) | CRITICAL | BLOCK |
VERICTO-090 | SQL injection: tautología OR en WHERE (OR 1=1) | CRITICAL | BLOCK |
VERICTO-091 | Descarga a un stage o transferencia de archivos (Snowflake) | CRITICAL | BLOCK |
VERICTO-092 | Stage externo o integración (Snowflake) | CRITICAL | BLOCK |
VERICTO-093 | Compartir con otra cuenta (Snowflake) | CRITICAL | BLOCK |
VERICTO-094 | Recuperación reducida (Snowflake) | HIGH | BLOCK |
VERICTO-095 | Costo de warehouse (Snowflake) | HIGH | BLOCK |
VERICTO-096 | Código que se ejecuta después (Snowflake) | HIGH | BLOCK |
VERICTO-097 | Cambio de rol (Snowflake) | HIGH | BLOCK |
VERICTO-098 | ATTACH DATABASE (SQLite) | HIGH | BLOCK |
VERICTO-099 | PRAGMA que desactiva una protección (SQLite) | HIGH | BLOCK |
VERICTO-100 | Carga de extensiones o funciones de archivos (SQLite) | CRITICAL | BLOCK |
VERICTO-101 | VACUUM INTO (SQLite) | HIGH | BLOCK |