Volver al blog
Guía · Seguridad

Por qué dar a un agente de IA acceso SQL directo es peligroso (y qué hacer)

El SQL directo deja que un agente filtre, corrompa o borre datos en segundos. Los riesgos reales, por qué fallan los prompts y el rol de solo lectura.

Claix · Actualizado noviembre 2026. Los riesgos reales de dar a un agente de IA una conexión a la base de datos, por qué un prompt y un rol de solo lectura se quedan cortos, y los patrones más seguros en producción. Relacionado: siete huecos de un rol de Postgres de solo lectura (/es/blog/read-only-postgres-role-for-ai-agents), cómo evitar que un agente borre la base (/es/blog/how-to-stop-an-ai-agent-from-deleting-your-database) y el incidente de PocketOS (/es/blog/pocketos-ai-agent-database-deletion).

La versión corta

  • Acceso SQL directo significa que el agente tiene una conexión a la base de datos y escribe sus propias consultas.
  • El modelo es el único guardián. Un modelo se puede manipular, puede equivocarse y puede ser impredecible.
  • Un prompt no es un permiso. Las reglas de un prompt se pueden ignorar. Los privilegios de la base de datos, no.
  • Un rol de solo lectura ayuda, y no basta. Una configuración habitual en PostgreSQL 16 sigue teniendo huecos.
  • Las lecturas y los cambios necesitan controles distintos: una capa de recuperación controlada para leer, y una comprobación de reglas para INSERT, UPDATE y DELETE.

¿Qué significa el acceso SQL directo para un agente de IA?

Acceso SQL directo significa que a un agente de IA se le da una conexión a la base de datos, o una herramienta que la envuelve, y el agente escribe el SQL. Convierte una petición en una consulta y la ejecuta. Así funcionan muchas demos, muchos montajes de text-to-SQL y un servidor MCP de base de datos tal como viene.

El modelo decide qué tablas consulta, qué columnas lee, qué filas cambia y cuándo. Todo lo que permitan las credenciales, el agente puede hacerlo.

¿Por qué es peligroso el acceso SQL directo?

Nueve riesgos se repiten una y otra vez.

1. El agente se puede manipular

Instrucciones ocultas en un mensaje de usuario, en un documento que el agente lee o en un campo de texto de tu propia base de datos pueden cambiar lo que hace el agente. Esto es prompt injection. La documentación de Supabase lo señala como el riesgo principal de conectar un agente a tus datos. La inyección SQL clásica se resolvió separando la consulta de la entrada. Con text-to-SQL, el modelo escribe toda la consulta como texto cada vez, así que no hay una forma fija que proteger.

2. Una sentencia destructiva cabe en una llamada

Un DELETE o un UPDATE sin WHERE afecta a todas las filas de la tabla. Un DROP o un TRUNCATE la elimina. Existen herramientas de código abierto como SQLGuard MCP porque los agentes pueden ejecutar por accidente sentencias como DELETE FROM users o DROP TABLE orders.

DELETE FROM reservations;
UPDATE orders SET discount_percent = 90;

Las dos son SQL válido, las dos se ejecutan sin error y ninguna dice nada sobre la intención.

3. Una consulta válida puede seguir siendo incorrecta

Una consulta puede ejecutarse, parecer razonable y responder a la pregunta equivocada. En nuestras pruebas, una consulta que escribió status = 'canceled' en lugar de 'cancelled' funcionó, no coincidió con ninguna fila y no lanzó ningún error. Un join malo puede duplicar filas, y un filtro de tenant ausente puede mezclar clientes. Nada falla, y alguien actúa sobre el resultado.

4. El agente puede leer lo que no debería

Si las credenciales pueden leer una columna, el agente puede pedirla. Una consulta como SELECT password_hash FROM users WHERE 1=1 es válida, y la base de datos la ejecuta sin quejarse. Lo mismo ocurre con datos de otro tenant cuando el filtro falta o está mal.

5. Las reglas de negocio no son reglas de base de datos

Un descuento del 90 por ciento, un saldo de menos 99.999 o un estado que no está en la lista aprobada son valores válidos para el tipo de su columna. Los permisos responden a si un rol puede tocar una tabla. No responden a si este cambio tiene sentido para el negocio.

6. Se pueden abusar los recursos

Una consulta lenta o pesada puede dañar una base de datos de producción. Un timeout ayuda, pero una sesión a menudo puede cambiar su propio timeout.

7. La salida es impredecible

Una ejecución devuelve un booleano y la siguiente una frase. Una automatización que espera una forma fija se rompe, y se rompe en silencio.

8. No hay registro

Cuando una respuesta o un cambio parece incorrecto después, necesitas la pregunta, la sentencia y la decisión. Una conexión en bruto no guarda nada de eso por ti.

9. Las credenciales son el punto débil

Un token con más autoridad de la que necesita la tarea convierte cualquier error en uno grande. En el incidente reportado de PocketOS, un token creado para operaciones rutinarias tenía, según los informes, autoridad general sobre la API del proveedor. Aquel incidente fue una llamada de infraestructura, no una sentencia SQL, y la lección se traslada: un agente con credenciales amplias, una acción destructiva y ninguna comprobación independiente.

¿Por qué un prompt no mantiene al agente a raya?

Un prompt puede reducir la probabilidad de un error. No puede impedir uno. El modelo lo lee como texto y lo pondera con todo lo demás, incluido su objetivo y el texto que ve por el camino. En los informes de PocketOS, el agente tenía reglas de seguridad y, según se cuenta, solo las reconoció después de actuar. Lo que detiene una acción es algo que el modelo no puede sortear hablando: un permiso de base de datos, una restricción o una comprobación determinista fuera del modelo.

Los permisos ordinarios responden a «¿puede este rol tocar esta tabla?», no a «¿cuánto va a cambiar esta sentencia?» ni a «¿puedo deshacerlo?».

¿Basta un rol de base de datos de solo lectura?

No. Un rol de solo lectura es la base, y no basta por sí solo. Probamos una configuración habitual en PostgreSQL 16 e intentamos rodearla como lo haría un agente manipulado o una consulta descuidada. Destacan seis cosas.

  • El ajuste de solo lectura es un valor por defecto, no un candado. default_transaction_read_only = on hace que las transacciones nuevas sean de solo lectura, y una sesión puede ejecutar SET default_transaction_read_only = off. Con un rol que tenía privilegios de escritura, la escritura pasaba. Lo que impide las escrituras es la ausencia del privilegio.
  • Los timeouts se pueden apagar. Con statement_timeout en dos segundos, un sleep de tres segundos se cancelaba, y tras SET statement_timeout = 0 llegaba hasta el final.
  • Una función SECURITY DEFINER puede escribir en nombre del rol. Se ejecuta con los privilegios de su propietario y, por defecto, todo el mundo puede ejecutarla. En nuestra prueba insertó una fila en una tabla que el rol no podía tocar.
  • Los nombres de tabla siguen siendo visibles. pg_tables listaba una tabla a la que el rol no tenía acceso, aunque su contenido seguía protegido.
  • SELECT * falla con grants a nivel de columna, y el error nombra la tabla, no la columna.
  • El row-level security sin política devuelve cero filas, lo que falla de forma segura y parece una tabla vacía.

Un rol no puede proteger lo que ya concediste. Si puede leer una columna, un agente manipulado puede pedirla. El SQL y el detalle están en la guía del rol de Postgres de solo lectura para agentes de IA (/es/blog/read-only-postgres-role-for-ai-agents).

¿Qué ocurre cuando sale mal?

Cuatro patrones cubren la mayoría de los incidentes.

  • Cambio masivo. Una sentencia sin una condición precisa toca todas las filas.
  • Suposición errónea. El agente actúa según una conjetura sobre el alcance, como en qué entorno o tenant está, sin verificarlo.
  • Exceso de alcance. La credencial permite más de lo que necesitaba la tarea, así que un error pequeño tiene un efecto grande.
  • Error silencioso. La consulta se ejecuta, devuelve algo verosímil y está mal.

El incidente de PocketOS, según los informes, combinó el segundo y el tercero. Un agente de programación que trabajaba en staging, con un token que llegaba a producción, borró un volumen de producción y sus copias en unos nueve segundos. Se reportó como una llamada a una API de infraestructura. Claix Guard no habría interceptado esa llamada concreta. El mismo fallo a nivel de base de datos es para lo que sirve una comprobación independiente.

¿Cómo das acceso a una base de datos a un agente de IA de forma segura?

No hay un único control. Usa capas.

  • No des al agente credenciales que puedan hacer más de lo que necesita la tarea. Usa un rol dedicado con SELECT sobre columnas concretas, y deja las credenciales de escritura solo en un ejecutor de tu código.
  • Separa staging y producción en credenciales y cuentas, no solo en los nombres.
  • Describe tus datos en lenguaje natural, para que el agente no adivine.
  • Acota lo que puede usar cada agente, en lugar de exponer todo el esquema.
  • Devuelve respuestas tipadas, no texto que el siguiente paso tenga que interpretar.
  • Comprueba cada INSERT, UPDATE y DELETE contra reglas antes de ejecutarlo, con una comprobación que el modelo no pueda anular.
  • Exige a una persona las acciones irreversibles. Esa revisión vive en tu flujo, después de una denegación.
  • Mantén los backups fuera del alcance del agente.
  • Registra cada petición y cada decisión.
  • Prueba con escenarios hostiles y equivocados, no solo con el camino feliz.

¿Cuáles son las alternativas al acceso SQL directo?

  • Funciones predefinidas. Escribes funciones fijas y el agente las llama. Es seguro y predecible, y solo cubre las preguntas para las que escribiste código.
  • Una capa de recuperación controlada para las lecturas. El agente hace preguntas y una capa decide qué tablas y columnas se pueden usar, y devuelve respuestas tipadas. El agente nunca tiene una conexión.
  • Una comprobación de reglas para los cambios. El agente propone un INSERT, UPDATE o DELETE, y un comprobador decide si las reglas lo permiten antes de que se ejecute nada.
  • Guardrails de código abierto. Varios proyectos en fase temprana cubren partes del problema: una librería que comprueba el SQL contra un archivo de políticas antes de ejecutarlo, un servidor MCP que clasifica consultas y pide confirmación antes de las mutaciones, una capa de seguridad para Postgres que mide una escritura antes de que ocurra y retiene las grandes para aprobación, y un sandbox que valida los cambios antes de sincronizarlos. Merece la pena evaluarlos. La mayoría están en alfa o beta, así que comprueba primero su madurez y sus límites.

¿Cómo elimina Claix la necesidad de acceso SQL directo?

Claix es una capa de control gestionada entre los agentes de IA y tu base de datos, con dos partes.

Claix Retrieve controla lo que un agente puede leer. Conectas tu base de datos con un rol de solo lectura, eliges qué tablas y columnas puede usar cada ruta y das a cada agente su propio endpoint. El agente hace preguntas en lenguaje natural y recibe respuestas tipadas. Nunca tiene una conexión a la base de datos y nunca escribe SQL directamente contra tus tablas. Cada petición queda trazada. Producto: https://www.claix.dev/es

Claix Guard controla lo que un agente puede cambiar. Antes de que se ejecute un INSERT, UPDATE o DELETE, tu aplicación envía la sentencia propuesta a Claix. Claix la comprueba contra reglas que escribiste en lenguaje natural y aprobaste. Responde allow o deny, con la razón. Una denegación sigue siendo HTTP 200. No hay un tercer veredicto. Si un cambio debe revisarlo una persona, Guard lo deniega y tu propio flujo envía esa denegación a Slack, email o n8n. Ningún modelo decide en el momento de la comprobación, y Claix nunca ejecuta la sentencia. Lo hace tu código. Producto: https://www.claix.dev/es/guard

Juntos sustituyen la parte peligrosa del acceso SQL directo: el agente escribe la consulta y nada fuera del modelo la comprueba.

¿Cuándo Claix no es la opción adecuada?

  • Necesitas que cada usuario final vea solo sus propias filas dentro de la herramienta. Claix acota el acceso por agente, no por usuario final. Aplícalo con row-level security o en la capa anterior al agente.
  • Solo tienes un puñado de preguntas fijas. Unas pocas funciones bien escritas pueden bastar.
  • Tienes que alojarlo todo tú. Claix es un servicio gestionado.
  • Necesitas cuadros de mando, gráficos o métricas de negocio gobernadas para analistas.
  • Usas una base de datos que Claix todavía no soporta. Claix soporta PostgreSQL, MySQL y MariaDB.

Checklist antes de dar a un agente acceso a la base de datos

  • Crea un rol dedicado con privilegios estrechos. Nunca uses un superusuario ni el usuario principal de tu aplicación.
  • Concede SELECT sobre columnas concretas, o expón vistas.
  • Revisa las funciones que se ejecutan con los privilegios de su propietario y revoca el execute público de las que escriben.
  • Configura timeouts y no des al agente una sesión SQL en bruto.
  • Describe tus tablas y relaciones en lenguaje natural.
  • Limita lo que puede usar cada agente.
  • Pon una comprobación determinista antes de cada INSERT, UPDATE y DELETE.
  • Envía los cambios irreversibles a una persona después de que Guard los deniegue.
  • Mantén los backups donde el agente no pueda llegar.
  • Registra cada petición y prueba con escenarios hostiles.

Fuentes y lecturas

  • Documentación de Supabase, servidor MCP (modo de solo lectura, uso en desarrollo, prompt injection): https://supabase.com/docs/guides/getting-started/mcp
  • Documentación de LangChain, agentes SQL y seguridad: https://docs.langchain.com/docs/use_cases/sql/
  • sql-guardrail (comprobador de políticas SQL de código abierto): https://pypi.org/project/sql-guardrail/
  • SQLGuard MCP (capa de seguridad MCP de código abierto): https://github.com/sealca/sqlguard-mcp
  • Interdict (capa de seguridad de Postgres de código abierto): https://pypi.org/project/interdict-db/
  • SafeAgentDB (sandbox de código abierto para escrituras de agentes): https://pypi.org/project/safeagentdb/
  • MIT AI Incident Database, incidente PocketOS: https://airisk.mit.edu/ai-incidents/1469-pocketos-production-database-was-reportedly-deleted
  • Documentación de PostgreSQL, GRANT: https://www.postgresql.org/docs/current/sql-grant.html
  • Documentación de PostgreSQL, CREATE FUNCTION y SECURITY DEFINER: https://www.postgresql.org/docs/current/sql-createfunction.html

Claix es una capa de control gestionada entre los agentes de IA y tu base de datos. Claix Retrieve controla lo que pueden leer, y Claix Guard comprueba cada INSERT, UPDATE y DELETE que proponen.

Preguntas frecuentes

¿Es seguro dar a un agente de IA acceso a una base de datos?
Puede serlo, si el acceso está limitado y se comprueba fuera del modelo. Usa credenciales de mínimo privilegio, pon una capa controlada entre el agente y la base de datos, y comprueba cada INSERT, UPDATE y DELETE antes de ejecutarlo. Dar al agente una conexión en bruto con privilegios amplios no es seguro.
¿Qué es el acceso SQL directo para un agente de IA?
Significa que el agente tiene una conexión a la base de datos, o una herramienta que la envuelve, y escribe y ejecuta su propio SQL.
¿Puede un agente de IA borrar mi base de datos?
Puede borrar lo que permitan sus credenciales. Un DELETE sin WHERE elimina todas las filas de una tabla, y un DROP elimina la tabla. Las credenciales, no el prompt, deciden cuánto daño es posible.
¿Qué es el prompt injection en un agente de base de datos?
Es cuando instrucciones ocultas en un mensaje de usuario, un documento o un campo de la base de datos cambian lo que hace el agente, por ejemplo haciéndole leer datos o ejecutar una sentencia que no debía.
¿Es seguro el text-to-SQL en producción?
Solo con controles alrededor: un rol de solo lectura estrecho, una comprobación de cada consulta antes de ejecutarla, límites de tiempo, filas y coste, y logs. Sin ellos, una consulta escrita por un modelo puede ser dañina, incorrecta o las dos cosas.
¿Basta un rol de solo lectura para proteger mi base de datos de un agente de IA?
No. Una sesión puede cambiar ajustes como el valor por defecto de solo lectura y el timeout, una función que se ejecuta con los privilegios de su propietario puede seguir escribiendo, y todo lo que concediste lo puede leer un agente manipulado.
¿Puede un system prompt impedir que un agente ejecute SQL peligroso?
No. Un prompt puede reducir la probabilidad de un error, y el modelo puede ignorarlo o ser manipulado para rodearlo. Usa permisos y comprobaciones deterministas que el modelo no pueda anular.
¿Cómo impido que un agente de IA ejecute un DELETE sin WHERE?
No des al agente credenciales de escritura, envía cada cambio por una única función de ejecución y haz que esa función pregunte primero a un comprobador de reglas. Una regla que exija que cada UPDATE o DELETE nombre una sola fila hace que una sentencia sin WHERE se deniegue. Guard responde allow o deny. No devuelve un tercer veredicto.
¿Cuál es la forma más segura de dejar que un agente de IA lea mis datos?
Usa una capa de recuperación controlada: un rol de solo lectura, un conjunto limitado de tablas y columnas por agente, y respuestas tipadas. El agente hace preguntas y nunca tiene una conexión.
¿Cuál es la forma más segura de dejar que un agente de IA cambie mis datos?
No dejes que el agente ejecute los cambios. Deja que los proponga, comprueba cada uno contra reglas y ejecuta en tu propio código solo los permitidos. Envía las denegaciones irreversibles a una persona.
¿Claix ejecuta mi SQL?
No. Claix Retrieve responde preguntas a partir de las tablas y columnas que permites, y Claix Guard solo comprueba los cambios que propone tu agente. Tu propio código ejecuta cualquier cambio, y solo después de que Guard devuelva allowed: true.
¿Los guardrails de código abierto resuelven esto?
Resuelven partes, y algunos son un buen punto de partida. La mayoría están en una fase temprana, y difieren en qué comprueban, dónde se ejecutan y si conservan tus credenciales de base de datos. Evalúa cada uno según tus necesidades.