flawopen.com/AI Security/semantic-kernel-inmemory-vector-filter-cve-2026-26030
Semantic Kernel CVE-2026-26030: inyección en filtros
Filtros vectoriales influidos por prompts eludían las comprobaciones AST y llegaban a eval de Python. Actualice a 1.39.4 o posterior.[1], [4]
Imagina a una bibliotecaria que recibe una tarjeta con una regla de búsqueda, comprueba algunas palabras conocidas y luego pide al ordenador que ejecute la tarjeta como un pequeño programa. Quien pueda influir en la tarjeta puede aprovechar fallos de esa comprobación. CVE-2026-26030 permitía que un filtro influido por el modelo pasara de buscar datos a ejecutar código dentro del proceso de la aplicación.[4]
Conceptos Clave y Términos
InMemoryVectorStore- Almacén vectorial dentro del proceso de Semantic Kernel; la búsqueda puede filtrar registros antes de devolver resultados.[4]
Expresión de filtro- Predicado que decide si un registro puede aparecer en una búsqueda vectorial. En la ruta Python afectada, los filtros de texto se analizaban y evaluaban como expresiones Python.[4]
Árbol de sintaxis abstracta (AST)- Representación estructurada del código analizado. Una validación incompleta puede dejar vías hacia la introspección de objetos Python.[2], [4]
Inyección de prompts- Texto no confiable influye en el modelo para que realice una acción imprevista. El riesgo depende de que la aplicación exponga el filtro vulnerable a entradas del modelo.[4]
Mapeos de marcos
- Referencia CWE para la debilidad descrita en esta guía: CWE-94
Flujo de Ataque Paso a Paso
Contenido no confiable influye en el filtro elegido por el modelo
El ataque requiere una vía de inyección de prompts que influya en la entrada del agente y un Search Plugin con el filtro predeterminado de InMemoryVectorStore. Un filtro generado por el modelo no es confiable solo por llegar mediante una llamada tipada.[4]
El filtro se convierte en código Python
Antes de la corrección, el filtro se analizaba como AST y se evaluaba sin builtins, pero las comprobaciones no restringían suficientemente el recorrido del modelo de objetos. La versión 1.39.4 conserva ast.Subscript para acceder a campos de registros y combina la lista de nodos permitidos con el bloqueo de atributos peligrosos, nombres aislados limitados a los parámetros lambda y una lista de llamadas permitidas. El código upstream no rechaza los subíndices por sí solos; eval sin builtins no es un sandbox.[2], [4]
La ejecución alcanza el proceso de la aplicación
Si la expresión elude la validación durante la búsqueda, la lógica influida por el atacante puede ejecutarse en el proceso Python del agente. El alcance depende de los permisos, entorno, credenciales y red de ese proceso.[4]
Corrija el límite del analizador e investigue la exposición
Actualice semantic-kernel a 1.39.4 o posterior. El parche comprueba atributos peligrosos y limita los nombres simples al parámetro lambda; el análisis también documenta listas permitidas AST y de funciones. Investigue anomalías de procesos, red y credenciales durante el periodo afectado.[1], [2], [3], [4]
Código Fuente: Vulnerable vs. Seguro
El panel vulnerable muestra un patrón representativo, no código literal del producto: un valor controlado por el modelo se interpola en sintaxis Python antes de eval. El panel corregido destaca las comprobaciones upstream de 1.39.4. La lista AST configurada incluye ast.Subscript para acceder a campos de registros; el parche la combina con el bloqueo de atributos peligrosos, nombres aislados limitados a lambda y llamadas permitidas. Quitar builtins no convierte eval en un sandbox. Actualice el paquete; no copie este fragmento como validador independiente.[2], [6], [4]
# Patrón representativo anterior al arreglo: el texto del modelo cambia la expresión.
filter_text = f"lambda x: x.city == '{model_selected_city}'"
tree = ast.parse(filter_text, mode="eval")
code = compile(tree, filename="<filter>", mode="eval")
filter_fn = eval(code, {"__builtins__": {}}, {}) # nosec
def validate_filter(self, tree):
# Comprobaciones upstream de 1.39.4; mensajes de excepción abreviados.
# Los filtros de nivel superior deben ser expresiones lambda.
if not (isinstance(tree, ast.Expression) and isinstance(tree.body, ast.Lambda)):
raise VectorStoreOperationException("Filter must be a lambda expression")
lambda_param_names = {arg.arg for arg in tree.body.args.args}
for node in ast.walk(tree):
if type(node) not in self.allowed_filter_ast_nodes:
raise VectorStoreOperationException("AST node type is not allowed")
if isinstance(node, ast.Attribute) and node.attr in self.blocked_filter_attributes:
raise VectorStoreOperationException("Dangerous attribute is not allowed")
if isinstance(node, ast.Name) and node.id not in lambda_param_names:
raise VectorStoreOperationException("Only lambda parameter names are allowed")
if isinstance(node, ast.Call):
if isinstance(node.func, ast.Name):
func_name = node.func.id
elif isinstance(node.func, ast.Attribute):
func_name = node.func.attr
else:
func_name = None
if func_name and func_name not in self.allowed_filter_functions:
raise VectorStoreOperationException("Function is not allowed")
code = compile(tree, filename="<filter>", mode="eval")
func = eval(code, {"__builtins__": {}}, {}) # nosec
Lista de Verificación de Seguridad para Ingeniería
- ✓Localice los entornos Python desplegados con semantic-kernel y registre la versión, incluidos contenedores, notebooks, workers e imágenes de CI.[4]
- ✓Actualice las instalaciones afectadas a 1.39.4 o posterior, regenere los archivos de bloqueo y reconstruya imágenes con dependencias corregidas.[1], [3]
- ✓Hasta actualizar, desactive en producción el filtro de InMemoryVectorStore; el proveedor recomienda evitar este almacén en producción como medida temporal.[1]
- ✓En cada PR que añada o cambie un filtro de búsqueda vectorial, incluya pruebas que demuestren que el texto del usuario, el contenido recuperado y los argumentos del modelo no pueden cambiar la estructura analizada del filtro; rechace las formas no admitidas.[4]
- ✓Añada una prueba que rechace atributos AST bloqueados y nombres fuera del parámetro lambda, sin payloads ejecutables.[2]
- ✓Represente los filtros elegidos por el modelo como datos tipados con listas explícitas de campos y operadores permitidos; añada pruebas que rechacen cadenas de expresiones y campos u operadores desconocidos.
- ✓Ejecute agentes con acceso mínimo a archivos, red y credenciales para limitar futuras vulnerabilidades.[4]
- ✓Añada una prueba de regresión de detección en el host del agente que genere eventos representativos de procesos hijos y conexiones salientes y compruebe que la regla de telemetría desplegada alerta sobre ambos.[4]