CVE-2026-26030: la inyección de prompts se convierte en RCE en Microsoft Semantic Kernel
El AI Red Team de Microsoft mostró dos fallos de Semantic Kernel que convierten un solo prompt inyectado en ejecución de código en el host. La lección: todo parámetro de herramienta que el modelo pueda influir es una entrada controlada por el atacante. Corregido el 7 de mayo de 2026.
¿Qué es esto?
El 7 de mayo de 2026, el equipo de investigación de seguridad de Microsoft Defender (Uri Oren, Amit Eliahu, Dor Edry) publicó «When prompts become shells», documentando dos vulnerabilidades críticas en Microsoft Semantic Kernel — el framework de agentes de código abierto de la empresa, con más de 27 000 estrellas en GitHub y el mismo linaje que Copilot Studio. Los fallos, CVE-2026-26030 (SDK de Python) y CVE-2026-25592 (SDK de .NET), permiten convertir una inyección de prompts ordinaria en ejecución remota de código en el host que aloja el agente. La entrada del NVD califica CVE-2026-26030 con CVSS 9.8. Ambos se divulgaron de forma responsable al MSRC y se corrigieron el mismo día de la publicación.
La enseñanza es estructural, no accidental: en cuanto un modelo se conecta a herramientas, la frontera entre «problema de contenido» y «primitiva de ejecución» desaparece. El modelo hace exactamente aquello para lo que fue diseñado: traducir lenguaje en llamadas a herramientas. La vulnerabilidad está en cómo el framework confía en los parámetros analizados.
Cómo funciona
CVE-2026-26030 — el sink eval() (Python). El Vector Store en memoria por defecto de Semantic Kernel construye su filtro como una lambda de Python y la ejecuta mediante eval(). Para un agente de búsqueda de hoteles, una consulta como «Busca hoteles en París» se convierte en lambda x: x.city == 'Paris'. El valor city está controlado por el modelo y sin sanear — un sink de inyección clásico. Cerrando la comilla y añadiendo Python, un atacante puede salir de la cadena. El framework lo había previsto con una lista de bloqueo basada en AST que rechazaba nombres como eval, exec, open e __import__ y eliminaba __builtins__. Microsoft demostró que la lista era eludible: una carga envuelta en una lambda válida superaba la comprobación estructural y, en lugar de nombres bloqueados, recorría la jerarquía de clases de Python (vía tuple, __class__, __subclasses__, BuiltinImporter) para alcanzar os.system — ninguno de ellos en la lista. Aquí no se reproduce ninguna carga funcional; la lección se sostiene sin ella.
CVE-2026-25592 — la herramienta sobreexpuesta (.NET). El SessionsPythonPlugin ejecuta el código generado por el modelo dentro de un entorno aislado de Azure Container Apps. Pero DownloadFileAsync — una función del lado del host — quedó anotada por error con [KernelFunction], lo que la exponía al modelo como una herramienta invocable. Su parámetro localFilePath, que decide dónde escribe File.WriteAllBytes() en el host, quedaba así controlado por el modelo, sin validación de rutas. Encadenando «escribir la carga en el sandbox» con «descargarla a la carpeta de Inicio del host» se obtiene un escape del sandbox hacia RCE completa en el siguiente inicio de sesión. Microsoft asocia la cadena a MITRE ATLAS AML.T0051 (LLM Prompt Injection) en cascada hacia AML.T0016 (Obtain Capabilities).
Por qué importa
Ambos fallos comparten el mismo error de arquitectura: confiar en una entrada enrutada por el modelo lo suficientemente lejos como para que alcance una primitiva de evaluación de código o de sistema de archivos. Cuando la recuperación alimenta los argumentos de las herramientas y esos argumentos alimentan un intérprete, la frontera entre contenido recuperado y código ejecutable se disuelve — y el saneamiento de entrada clásico, situado fuera del runtime del agente, nunca ve la carga.
El radio de impacto es amplio. Semantic Kernel ejecuta aplicaciones RAG en producción sobre Azure, escenarios de Microsoft 365 Copilot y una larga cola de automatizaciones internas en sectores regulados. Para CVE-2026-26030, el único requisito es que un campo influido por el atacante llegue al índice — un solo documento envenenado en un corpus compartido puede alcanzar a todos los agentes posteriores que lo consulten. Como dice Microsoft sin rodeos: tu LLM no es una frontera de seguridad; las herramientas que expones definen el alcance del atacante.
Defensas
- Parchea ya. Actualiza el paquete de Python
semantic-kernela 1.39.4+ y el SDK de .NET a 1.71.0+. No hace falta reescribir el agente — las correcciones eliminan la capacidad del modelo de activar estas funciones de forma autónoma. - Prefiere listas de permitidos a listas de bloqueo en los sinks de evaluación. La corrección de Semantic Kernel sustituyó la frágil lista de bloqueo por una lista de permitidos de tipos de nodo AST, una lista de llamadas permitidas, una lista de bloqueo de atributos de recorrido de jerarquía (
__class__,__subclasses__) y una restricción de nombres. En lenguajes dinámicos, vetar tokens peligrosos es estructuralmente perdedor; solo permitir explícitamente las construcciones seguras se sostiene. - Trata todo parámetro de herramienta influido por el modelo como entrada no confiable. Valida y canoniza las rutas de archivo (
Path.GetFullPath()más una lista de directorios permitidos), parametriza las consultas y nunca interpoles la salida del modelo en códigoeval/exec/de plantilla. - No expongas funciones peligrosas como herramientas. Audita qué funciones llevan una anotación
[KernelFunction]/ esquema de herramienta. Las funciones del lado del host de archivos, procesos y red solo deberían poder invocarse desde tu código, nunca desde el modelo — véase el envenenamiento de descripciones de herramientas como superficie no probada. - Defiende también en la capa del host. Como la barrera del modelo puede eludirse, correlaciona las señales del nivel del modelo con la telemetría de endpoint: un proceso host de agente que lanza
cmd.exe/powershell.exeo deposita archivos en la carpeta de Inicio es una señal fuerte de post-explotación. Microsoft publicó consultas de búsqueda avanzada para exactamente esto. - Aplica el mínimo privilegio al agente. La regla de dos de los agentes y el mínimo privilegio por herramienta limitan lo que una inyección exitosa puede alcanzar.
Estado
| Elemento | Detalle |
|---|---|
| CVE | CVE-2026-26030 (Python), CVE-2026-25592 (.NET) |
| Componente | Semantic Kernel — filtro del Vector Store en memoria; SessionsPythonPlugin |
| Clase | Inyección de prompts → sink eval() RCE; herramienta sobreexpuesta → escritura de archivo en host / escape de sandbox |
| CVSS | 9.8 (CVE-2026-26030, NVD) |
| Afectado | Python semantic-kernel < 1.39.4; SDK de .NET < 1.71.0 |
| Corregido en | Python 1.39.4; .NET 1.71.0 |
| Divulgación | Coordinada vía MSRC; corregido el día de la publicación (7 de mayo de 2026) |
| En estado salvaje | PoC reproducible por Microsoft; ninguna campaña confirmada en la divulgación |
Esto no es realmente «un bug de Semantic Kernel». Es la reescritura, en la era de los agentes, de una vieja lección de seguridad web: una entrada no confiable nunca debe alcanzar una operación de alto riesgo sin mediación. En los años 2000 esa entrada iba a consultas SQL y llamadas de shell; hoy llega en lenguaje natural, se analiza en argumentos de herramientas y aterriza en un intérprete. Microsoft ha anunciado que las próximas entregas de esta serie de investigación cubrirán fallos de ejecución estructuralmente idénticos en otros frameworks de uso extendido — así que trátalo como una clase, no como un caso aislado, y asume que todo framework que mapea la salida de un modelo a herramientas del sistema comparte la misma forma.