Introducción
Los frameworks de agentes IA permiten que un modelo de lenguaje no solo genere texto, sino que también coordine acciones: consultar datos, llamar a APIs, ejecutar herramientas, escribir ficheros o interactuar con entornos de cálculo. Esa capacidad es precisamente lo que los hace útiles para automatizar flujos complejos, pero también amplía la superficie de ataque.
El riesgo no está en que un prompt, por sí solo, sea una shell. El riesgo aparece cuando el contenido controlado por un usuario, por una página web, por un documento recuperado mediante RAG o por cualquier fuente externa llega a una herramienta con efectos reales: ejecución de código, escritura de archivos, invocación de comandos, modificación de configuración o acceso a secretos.
Microsoft Defender Security Research publicó un análisis sobre vulnerabilidades de ejecución remota de código en frameworks de agentes IA, usando como caso representativo componentes de Semantic Kernel. El mensaje principal es claro: cuando un framework conecta razonamiento del modelo, plugins y entornos de ejecución, los límites de confianza deben estar muy bien definidos.
Advertencia: una vulnerabilidad RCE en un agente IA puede permitir que un atacante ejecute código con los permisos del proceso, contenedor, notebook, función o identidad administrada donde se ejecuta el agente. En cloud, esto puede derivar en acceso a datos, movimiento lateral o consumo abusivo de recursos.
De prompt injection a ejecución de código
Conviene separar dos conceptos que a menudo se mezclan:
- Prompt injection: el atacante introduce instrucciones que manipulan el comportamiento del modelo. Por ejemplo, “ignora las instrucciones anteriores y ejecuta esta acción”.
- Remote Code Execution (RCE): el atacante consigue ejecutar código o comandos en un sistema remoto.
Una prompt injection no implica automáticamente RCE. Para que el salto ocurra, debe existir un puente inseguro entre el texto generado o procesado por el modelo y una capacidad ejecutable. Ese puente puede ser:
- Una herramienta que lanza comandos del sistema.
- Un plugin que ejecuta código Python, JavaScript u otro lenguaje.
- Una función que escribe archivos en rutas controlables.
- Un conector que pasa datos no validados a una API sensible.
- Un mecanismo de serialización, plantillas o carga dinámica mal protegido.
- Un entorno de ejecución compartido entre usuarios o sesiones.
En sistemas agentivos, este patrón es especialmente delicado porque el modelo decide o ayuda a decidir qué herramienta usar, con qué parámetros y en qué orden. Si los parámetros proceden de contenido no confiable, el agente puede terminar ejecutando una acción que el desarrollador no pretendía permitir.
El caso de Semantic Kernel analizado por Microsoft
El artículo de Microsoft describe vulnerabilidades en el contexto de Semantic Kernel, un SDK de código abierto para construir aplicaciones y agentes con modelos de lenguaje. Según la investigación, el caso ilustra cómo funcionalidades legítimas de un framework agentivo pueden introducir riesgo si aceptan entradas no confiables sin restricciones suficientes.
Entre los identificadores mencionados por Microsoft se encuentran:
- CVE-2026-26030, asociado al componente In-Memory Vector Store.
- CVE-2026-25592, descrito como una escritura arbitraria de archivos a través de SessionsPythonPlugin.
No todos los fallos en agentes IA tienen la misma causa, pero ambos apuntan a una idea común: los componentes que almacenan, transforman, escriben o ejecutan datos deben tratar cualquier entrada controlada por usuarios, documentos externos o modelos como no confiable.
En arquitecturas con agentes, no basta con revisar el prompt de sistema. También hay que revisar:
- qué plugins están habilitados;
- qué permisos tiene cada herramienta;
- si las rutas de archivo son controlables por el usuario;
- si existe aislamiento por sesión o por tenant;
- si el entorno de ejecución puede acceder a secretos;
- si el agente puede encadenar herramientas de forma no prevista;
- si los datos recuperados desde índices vectoriales o documentos externos pueden influir en acciones sensibles.
Ejemplo simplificado: el antipatrón de pasar texto a una shell
El siguiente ejemplo no representa una vulnerabilidad concreta de Semantic Kernel. Es un patrón general de command injection que ayuda a entender por qué no se debe convertir entrada no confiable en comandos del sistema.
import subprocess
user_input = input("Archivo a listar: ")
command = f"ls {user_input}"
subprocess.run(command, shell=True)
Si user_input contiene algo como:
/tmp; cat /etc/passwd
la shell interpretará ambos comandos. El problema no es el prompt en sí, sino el hecho de que texto no confiable acaba siendo interpretado por una shell.
Una alternativa más segura es evitar shell=True y pasar argumentos como una lista, además de validar explícitamente qué valores son aceptables:
import subprocess
from pathlib import Path
BASE_DIR = Path("/srv/app/files").resolve()
def resolve_allowed_path(value: str) -> Path:
candidate = (BASE_DIR / value).resolve()
if not str(candidate).startswith(str(BASE_DIR)):
raise ValueError("Ruta no permitida")
return candidate
user_input = input("Archivo a listar: ")
safe_path = resolve_allowed_path(user_input)
subprocess.run(["ls", str(safe_path)], check=True)
Este ejemplo reduce el riesgo porque:
- no invoca una shell;
- valida que la ruta queda dentro de un directorio permitido;
- separa el programa (
ls) de sus argumentos; - usa
check=Truepara detectar errores de ejecución.
Aun así, en un agente real habría que preguntarse si el agente necesita ejecutar comandos del sistema. En muchos casos, una API específica y limitada es preferible a exponer una herramienta genérica de ejecución.
Por qué los agentes aumentan la superficie de ataque
Los agentes IA combinan componentes que antes solían estar más separados:
- razonamiento del modelo;
- memoria conversacional;
- recuperación de documentos;
- llamadas a herramientas;
- ejecución de código;
- escritura de archivos;
- credenciales de servicios;
- identidades administradas;
- conectores a datos corporativos.
Esa combinación puede generar cadenas de ataque no evidentes. Por ejemplo:
- Un atacante introduce instrucciones maliciosas en un documento que será indexado.
- El agente recupera ese documento durante una tarea legítima.
- El modelo interpreta el contenido como una instrucción.
- El agente llama a una herramienta con parámetros derivados del documento.
- La herramienta escribe un archivo, ejecuta código o accede a datos con permisos superiores a los del atacante.
Este tipo de escenario no se resuelve únicamente con “mejores prompts”. Los prompts ayudan a guiar el comportamiento del modelo, pero no sustituyen controles de seguridad clásicos: validación, aislamiento, autorización, auditoría y mínimo privilegio.
Controles recomendados
1. Reducir capacidades por defecto
Un agente no debería tener acceso a herramientas genéricas si no son necesarias. Es mejor exponer funciones pequeñas, explícitas y con entradas bien definidas que una herramienta capaz de ejecutar cualquier comando.
Recomendaciones prácticas:
- deshabilitar plugins no utilizados;
- evitar herramientas de shell o ejecución arbitraria en producción;
- limitar operaciones de escritura;
- separar herramientas de lectura y escritura;
- usar listas de acciones permitidas;
- revisar los permisos de cada herramienta por entorno.
2. Validar parámetros en la capa de herramienta
No basta con pedir al modelo que “no haga nada peligroso”. La validación debe estar en el código que ejecuta la acción.
Ejemplos de validaciones importantes:
- rutas permitidas;
- extensiones de archivo aceptadas;
- tamaños máximos;
- esquemas JSON estrictos;
- identificadores pertenecientes al tenant correcto;
- rangos numéricos;
- dominios o endpoints permitidos;
- operaciones explícitamente autorizadas.
Si una herramienta recibe argumentos desde el modelo, esos argumentos deben tratarse como entrada externa.
3. Aplicar mínimo privilegio
El proceso del agente debe ejecutarse con la menor cantidad de permisos posible. Esto incluye:
- identidades con permisos limitados;
- secretos fuera del entorno de ejecución cuando sea posible;
- separación por entorno, tenant o usuario;
- permisos de solo lectura si la tarea no requiere escritura;
- acceso limitado a redes internas;
- credenciales rotadas y monitorizadas.
En Azure, esto se traduce en revisar cuidadosamente roles de Azure RBAC, permisos de identidades administradas, acceso a cuentas de almacenamiento, bases de datos, Key Vault y redes privadas.
4. Aislar entornos de ejecución
Si el agente necesita ejecutar código, el aislamiento debe ser parte del diseño:
- contenedores efímeros;
- límites de CPU y memoria;
- sistemas de archivos temporales;
- bloqueo de acceso a metadatos o credenciales innecesarias;
- separación entre sesiones;
- políticas de red restrictivas;
- destrucción del entorno tras la ejecución.
El objetivo no es asumir que nunca habrá fallo, sino reducir el impacto si una herramienta es abusada.
5. Controlar escrituras de archivos
Las vulnerabilidades de escritura arbitraria son especialmente peligrosas porque pueden convertirse en ejecución de código si el atacante escribe en ubicaciones sensibles: scripts cargados por la aplicación, directorios de configuración, claves autorizadas, plantillas, extensiones o archivos que luego serán procesados por otro componente.
Buenas prácticas:
- normalizar y resolver rutas antes de escribir;
- impedir
../y enlaces simbólicos no controlados; - escribir solo en directorios dedicados;
- generar nombres de archivo del lado servidor;
- no permitir rutas absolutas suministradas por el usuario;
- validar tipo y tamaño de contenido;
- registrar operaciones de escritura.
6. Diseñar herramientas con contratos estrictos
Las herramientas llamadas por agentes deberían comportarse como APIs internas seguras. Un buen contrato incluye:
- nombre claro de la acción;
- parámetros tipados;
- validación de esquema;
- errores controlados;
- autorización explícita;
- trazabilidad;
- límites de uso;
- ausencia de efectos secundarios inesperados.
Cuanto más abierta sea la herramienta, mayor será el riesgo. Una función send_invoice(invoice_id) es más controlable que una función execute_python(code) o run_command(command).
7. Monitorizar y auditar
La observabilidad es crítica en agentes porque las acciones pueden encadenarse dinámicamente. Conviene registrar:
- usuario o identidad que inició la tarea;
- prompt o resumen de intención, con cuidado de no almacenar datos sensibles innecesarios;
- herramientas llamadas;
- parámetros relevantes;
- resultado de la acción;
- errores;
- operaciones de escritura;
- accesos a secretos o datos sensibles;
- consumo anómalo de recursos.
Servicios como Azure Monitor pueden ayudar a centralizar métricas y logs. En entornos con requisitos de seguridad elevados, estos eventos deberían integrarse con procesos de detección y respuesta.
Errores comunes al proteger agentes IA
Confiar únicamente en el prompt de sistema
El prompt de sistema puede indicar al modelo que no ejecute acciones peligrosas, pero un atacante puede intentar manipular el contexto mediante prompt injection directa o indirecta. Las restricciones críticas deben implementarse en código y configuración.
Exponer herramientas demasiado potentes
Una herramienta genérica de ejecución de comandos, escritura de archivos o evaluación de código es difícil de controlar. Si debe existir, debería ejecutarse en un entorno aislado y con controles estrictos.
Mezclar datos no confiables con instrucciones
Los documentos recuperados, correos, tickets, páginas web o mensajes de usuario no deben tratarse como instrucciones de sistema. Es recomendable separar claramente instrucciones, contexto y datos.
Reutilizar sesiones entre usuarios
Si un entorno de ejecución mantiene estado, archivos o variables entre sesiones, puede aparecer fuga de información o contaminación entre usuarios. El aislamiento por sesión es una defensa importante.
Dar al agente permisos de administrador
Un agente comprometido hereda los permisos disponibles en su entorno. Si la identidad del agente tiene privilegios excesivos, el impacto de una vulnerabilidad aumenta de forma significativa.
Checklist para revisar un agente antes de producción
Antes de desplegar un agente con herramientas, conviene responder a estas preguntas:
- ¿Qué herramientas puede llamar el agente?
- ¿Cada herramienta es realmente necesaria?
- ¿Qué entradas recibe cada herramienta?
- ¿Quién valida esas entradas?
- ¿Puede el agente escribir archivos? ¿Dónde?
- ¿Puede ejecutar código? ¿En qué entorno?
- ¿Tiene acceso a secretos?
- ¿Qué identidad usa para acceder a recursos cloud?
- ¿Los permisos siguen el principio de mínimo privilegio?
- ¿Existe aislamiento entre usuarios, sesiones y tenants?
- ¿Se registran las llamadas a herramientas?
- ¿Hay alertas sobre comportamientos anómalos?
- ¿Se han aplicado las actualizaciones de seguridad del framework?
- ¿Se prueban casos de prompt injection indirecta?
- ¿Hay límites de coste, cuota y tiempo de ejecución?
Conclusión
Los agentes IA no son inseguros por definición, pero conectan modelos de lenguaje con capacidades que pueden tener efectos reales sobre sistemas y datos. Esa conexión exige controles de seguridad equivalentes a los de cualquier otra aplicación crítica.
El análisis de Microsoft sobre vulnerabilidades RCE en frameworks de agentes IA refuerza una lección importante: no basta con proteger el prompt. Hay que proteger las herramientas, los plugins, las rutas de archivo, los entornos de ejecución, las identidades y los datos que alimentan al agente.
Para arquitectos y equipos de desarrollo, la recomendación práctica es diseñar agentes con defensa en profundidad: mínimo privilegio, herramientas limitadas, validación estricta, aislamiento, auditoría y actualización continua de dependencias.
Fuente
- Microsoft Security Blog: When prompts become shells: RCE vulnerabilities in AI agent frameworks