Prompts como shells: cuando la inyección de prompt se convierte en RCE en frameworks de agentes
Dos CVE divulgadas en Microsoft Semantic Kernel el 7 de mayo de 2026 (CVE-2026-25592, CVE-2026-26030) muestran cómo un único prompt inyectado puede pasar del texto a la ejecución remota de código en el host del agente.
Qué ocurrió
El 7 de mayo de 2026, el Microsoft Security Response Center divulgó dos vulnerabilidades críticas en el framework de agentes Semantic Kernel: CVE-2026-25592 (CVSS 10.0) en el SDK de .NET y CVE-2026-26030 (CVSS 9.8) en el SDK de Python. Ambas convierten una inyección de prompt textual — el modelo recibiendo instrucciones controladas por el atacante mediante contenido no confiable — en ejecución remota de código sobre el host que aloja al agente. Los parches llegaron el mismo día: semantic-kernel Python 1.39.4 y .NET 1.71.0.
La publicación de investigación que acompaña la divulgación, When prompts become shells, identifica un patrón más amplio: los frameworks de agentes exponen al modelo un registro de herramientas, sandboxes y funciones auxiliares, y cualquier helper que toque un sink de ejecución de código (eval, exec, deserialización, escritura de archivos, shell) queda alcanzable mediante un único prompt bien diseñado.
Cómo funciona
Un agente entrega al LLM un registro de herramientas invocables. El modelo decide cuáles llamar y suministra los argumentos. Dos bugs distintos, misma forma:
CVE-2026-26030 — eval() de Python en el vector store en memoria. El componente InMemoryVectorStore por defecto construía expresiones de filtrado pasando cadenas influenciadas por el atacante a un lambda de Python compilado con eval(). Un LLM engañado por un prompt inyectado podía pedir al store que filtrase registros con un payload que ejecuta Python arbitrario.
# Esquema conceptual — NO ejecutar.
# Un campo controlado por contenido no confiable llega a eval().
filter_expr = f"lambda r: r.score > {model_supplied_value}"
predicate = eval(filter_expr) # [REDACTED]: el payload corre en el proceso anfitrión
CVE-2026-25592 — DownloadFileAsync expuesto como [KernelFunction] en el sandbox .NET. El SessionsPythonPlugin ejecuta el código generado por el modelo dentro de una sesión dinámica de Azure Container Apps. Un helper interno, DownloadFileAsync, fue anotado por error como [KernelFunction] y registrado como herramienta invocable sin validación de ruta. Un prompt podía pedir al agente que “descargase” un archivo remoto en una ruta local arbitraria, escribiendo contenido del atacante fuera del sandbox y sobre el host.
En ambos casos el punto de entrada es texto. Sin corrupción de memoria, sin exploit del navegador. El modelo interpreta la petición, escoge una herramienta y pasa los parámetros a un sink de ejecución.
Por qué importa
No es una historia exclusiva de Semantic Kernel. El mismo patrón ha aparecido repetidamente en 2026 en frameworks de agentes (PraisonAI, Flowise, LMDeploy, mcp-remote — ver el tracker mensual de Adversa AI). La causa estructural es idéntica:
- El framework expone un registro de herramientas al LLM.
- Al menos una herramienta alcanza un sink inseguro (
eval,exec, deserialización pickle, escritura de ruta, shell). - El agente procesa texto no confiable — documentos recuperados, páginas web, resultados de herramientas — junto a sus propias instrucciones.
- No existe una frontera impuesta entre datos e instrucciones.
Esto es exactamente el lethal trifecta descrito por Simon Willison en junio de 2025 — acceso a datos privados, exposición a contenido no confiable y capacidad de acción externa — y la Regla de dos propuesta por el equipo de AI Security de Meta el 31 de octubre de 2025: un agente debe mantener como máximo dos de esas tres propiedades por sesión. Cuando las tres coexisten, la seguridad determinista colapsa y un prompt textual se convierte en un shell.
Defensas
Las mitigaciones son arquitectónicas, no heurísticas — el filtrado de prompts por sí solo es insuficiente.
- Aplicar parches primero. Actualizar Semantic Kernel a Python
>=1.39.4y .NET>=1.71.0. Auditar cualquier framework de agentes en producción siguiendo el tracker mensual de Adversa. - Eliminar
eval/execsobre cadenas suministradas por el modelo. Sustituirlos por parseadores estructurados (allowlists AST, DSL de filtrado tipado). El parche de Microsoft apila cuatro comprobaciones: allowlist de tipos de nodo AST, allowlist de llamadas de función, blocklist de atributos peligrosos y restricción de nodos de nombre. - Auditar el registro de herramientas. Cada
[KernelFunction],@toolo endpoint OpenAPI expuesto es alcanzable por el modelo. Tratar el registro como una API pública: superficie mínima, parámetros validados, ningún helper expuesto por accidente. - Sandboxear al ejecutor, no al prompt. Ejecutar todo código pilotado por el modelo dentro de un contenedor o microVM sin red, sin escritura al host y sin credenciales más allá de la tarea.
- Aplicar la Regla de dos. Para cada sesión de agente, decidir cuáles dos de las tres propiedades — {entrada no confiable, dato sensible, acción externa} — se aceptan, e imponer el corte a nivel arquitectónico.
- Registrar las llamadas a herramientas con sus argumentos completos. Hacer posible la detección posterior; la salida cruda del modelo no es suficiente.
Estado
| Framework | CVE | CVSS | Divulgación | Parcheado en |
|---|---|---|---|---|
| Semantic Kernel (.NET) | CVE-2026-25592 | 10.0 | 2026-05-07 | 1.71.0 |
| Semantic Kernel (Python) | CVE-2026-26030 | 9.8 | 2026-05-07 | 1.39.4 |
| PraisonAI | CVE-2026-44338 | 9.x | 2026-04 | última versión |
| Flowise MCP adapter | CVE-2026-40933 | 9.x | 2026-04 | última versión |
Si despliega un agente en producción, la pregunta ya no es si la inyección de prompt alcanzará su capa de herramientas, sino sobre qué sink aterrizará. Corte los sinks.