Volver a todas las publicaciones
Publicado el · por Renaud Deraison

La pasarela aceptaba cualquier token

El 2 de septiembre, CISA añadió siete fallos explotados al catálogo KEV. Tres son infraestructura de IA, el primer lote en el que la IA supone casi la mitad. Lea la entrada de LiteLLM: su endpoint MCP admitía una petición no autenticada que llevara cualquier token Bearer, porque una validación de clave fallida caía en un objeto de autenticación vacío, y quien llamaba podía entonces listar e invocar todas las herramientas cableadas a la pasarela. Bromure Agentic Coding guarda la misma autoridad detrás de un hipervisor y un vsock, sin puerto a la escucha, sin cabecera que falsificar y sin rama de reserva.

Montó la pasarela para que ningún portátil guardara por sí solo todas las claves. Funcionó, y ella guardaba todas las claves. Después su puerta de entrada aceptó un token Bearer que alguien se inventó.

El 2 de septiembre, CISA añadió siete vulnerabilidades al catálogo de Known Exploited Vulnerabilities. Dos fallos de SonicWall SMA1000, una inyección SQL en Sangoma Switchvox, una elusión de autenticación en JFrog Artifactory, una inyección de comandos del sistema en Kestra, un fallo de contrabando HTTP en Starlette y un fallo de autenticación indebida en el LiteLLM de BerriAI.

Tres de esas siete son infraestructura de IA y ML. Forkast lo llamó el primer lote KEV en el que los componentes de IA suponen casi la mitad de las adiciones, esa clase de hito que se gana un titular y luego se archiva. Mire qué infraestructura de IA es y el lote merece algo más que el archivo. Las tres están en medio: son los componentes que despliega para que sus agentes y los recursos que tocan dejen de hablarse directamente. Empiece por la entrada de LiteLLM.

La rama de reserva

LiteLLM es una pasarela de IA: un proxy que se sitúa entre sus agentes y los proveedores de modelos, guarda las claves de proveedor para que nadie más tenga que hacerlo, aplica presupuestos y límites de tasa, escribe los registros y ahora se abre en abanico hacia servidores Model Context Protocol, de modo que los agentes de un equipo compartan un único endpoint MCP en lugar de que cada desarrollador cablee el suyo.

CVE-2026-59822, publicada el 8 de julio y con un CVSS de 8.8 en el aviso de GitHub, vive en ese endpoint MCP. Una frase del aviso lleva toda la historia:

la ruta de reserva podía sustituir una validación fallida de clave LiteLLM por un objeto UserAPIKeyAuth() vacío.

El endpoint MCP Streamable HTTP admitía passthrough OAuth2, para que un token destinado a un servidor MCP aguas arriba pudiera atravesar la pasarela en vez de validarse contra el almacén de claves propio de LiteLLM. Es una funcionalidad razonable, y necesita una rama: probar primero la clave LiteLLM y tomar la ruta de passthrough cuando lo que llegó no es una clave.

A esa rama se llega fallando. Envíe una cabecera Authorization que contenga cualquier cadena, la validación de clave la rechaza porque la cadena no es una clave, y el manejador construye un UserAPIKeyAuth() vacío y sigue adelante con él. Su petición sostiene ahora una sesión MCP autenticada que no pertenece a nadie. Desde ahí enumera todas las herramientas MCP con las que se configuró la pasarela y las llama: aplicaciones internas, bases de datos, consolas de nube, sistemas de desarrollo, lo que el equipo hubiera conectado. El fallo afecta a todas las versiones anteriores a la 1.84.0. El plazo de remediación de CISA para las agencias federales es el 16 de septiembre, y el consejo de LiteLLM para quien no pueda actualizar hoy es bloquear /mcp/ en el proxy inverso que tenga delante.

CVE-2026-59822 — la rama a la que llega el fallopetición sin autenticarPOST /mcp/Authorization: Bearer anything-at-allvalidar la clave LiteLLMla cadena no es una clavela validación fallarespaldo de passthrough OAuth2sustituye por un objeto de auth vacío y sigueUserAPIKeyAuth()sesión MCP autenticada que no pertenece a nadielistar todas las herramientas configuradas · llamar a cualquiera · nunca se presentó una claveaplicaciones internasdetrás de la pasarelabases de datoslo que estuviera conectadoservicios en la nubecon todo su alcancesistemas de desarrollocódigo, CI, tickets
El manejador MCP probaba primero la clave LiteLLM y, cuando fallaba, tomaba la ruta de passthrough OAuth2, que construía un UserAPIKeyAuth() vacío y continuaba. Una petición con un token Bearer inventado llegaba adonde habría llegado una clave válida: a una sesión MCP autenticada, con toda la lista de herramientas de la pasarela detrás.

Los otros tres se rompieron en la misma función

Lea el resto del lote y obtiene algo más útil que el titular de IA contra no-IA.

Starlette, CVE-2026-48710, apodada BadHost. Starlette es el kit ASGI que hay bajo FastAPI, sobre el que está construida buena parte de los servicios de IA en Python, LiteLLM incluido. Una cabecera Host manipulada inyecta una ruta en la parte de host de la petición, lo que desplaza la forma en que se reconstruye la URL, lo que significa que un middleware de autenticación basado en rutas evalúa una ruta mientras la aplicación sirve otra. La entrada de CISA declara el resultado: elusión de autenticación, cuando la autenticación depende de la ruta de la URL reconstruida. Lleva un CVSS de 6.5, la puntuación más baja del lote y la que menos dice sobre la consecuencia. LiteLLM publicó su propia corrección acompañante para la misma forma en la 1.84.0, describiéndola como “una cabecera Host manipulada podía hacer que la puerta de autenticación del proxy evaluara una ruta distinta de la que servía”, y dijo a los operadores cuyo proxy había estado expuesto que rotaran sus claves y auditaran los registros de administración.

JFrog Artifactory, CVE-2026-82329, CVSS 9.8. Autenticación indebida en la configuración por defecto: una clave de unión “fantasma” que permite a un atacante no autenticado falsificar tokens de administrador. watchTowr documentó explotación real el 1 de septiembre, cuatro días después de la divulgación, con atacantes acuñando credenciales de administrador y enumerando usuarios. Este es el repositorio de artefactos, el host que responde a npm install y pip install para toda la organización.

Kestra, CVE-2026-49869. Inyección de comandos del sistema alcanzable por un atacante remoto no autenticado, que puede crear y ejecutar flujos de trabajo arbitrarios sin credencial alguna. El orquestador hace lo que hace un orquestador, en nombre de alguien que nunca inició sesión.

Cuatro productos, cuatro bases de código distintas y la misma función rota en cada una: la que decide si esta petición tiene derecho a estar aquí. Un objeto de autenticación vacío. Una ruta reconstruida. Una clave de unión por defecto. En el caso de Kestra, ninguna comprobación en la ruta que ejecuta cosas.

Lo que los atacantes hicieron después fue aburrido, y el aburrimiento delata el trabajo a escala. The Hacker News reunió el comportamiento observado: shells inversas, mineros XMRig, enumeración de credenciales y robo de claves de API y de credenciales de proveedores de LLM. Microsoft lo resumió:

Los objetivos observados fueron constantes. En todos los casos, la telemetría mostró recolección de credenciales, mecanismos de acceso duradero y monetización de recursos, aunque la ruta de ejecución variara según el producto.

Un lote, una función, cuatro formas de equivocarseCOMPONENTELA COMPROBACIÓN QUE DECIDÍALO QUE DEJÓ PASARLiteLLM · pasarela de IACVE-2026-59822 · 8.8validar la clave de API de LiteLLMen el endpoint MCPcualquier token Bearerel fallo caía en un objeto de auth vacíoStarlette · kit ASGICVE-2026-48710 · 6.5middleware de auth por rutasobre la URL reconstruidauna ruta que nunca custodióuna cabecera Host manipulada desplazó la reconstrucciónJFrog Artifactory · registroCVE-2026-82329 · 9.8validación de la clave de uniónen la configuración por defectotokens de administrador falsificadosexplotada cuatro días después de la divulgaciónKestra · orquestadorCVE-2026-49869ninguna, en la ruta que ejecutacrear y ejecutar flujos de trabajocomandos arbitrarios, sin autenticarsin necesidad de credenciales
Cuatro entradas de un mismo lote KEV, cuatro bases de código, una función. Cada producto se rompió en el punto en que decide si una petición pertenece ahí, y tres de las cuatro son componentes que se despliegan para centralizar el acceso en lugar de dejar que cada desarrollador guarde el suyo.

La pasarela era la idea correcta, y esta es su factura

La pasarela de IA es una de las mejores ideas de los últimos dos años, y la mayoría de los equipos llegó a ella por razones sólidas.

Antes de la pasarela, el agente de código de cada desarrollador guardaba una clave de proveedor en una variable de entorno, cada desarrollador cableaba sus propios servidores MCP con sus propios tokens, y nadie podía responder qué había gastado o tocado todo aquello. Poner una pasarela en medio arregla todo eso de golpe. Un solo lugar guarda las claves de proveedor y la configuración MCP, y escribe el registro. Rotar una clave se convierte en una única operación, y cortarle el acceso a quien se marcha, también. La industria convergió aquí por buenos motivos.

La factura es que ha construido un servicio de red cuyo propósito entero es guardar la autoridad de todos, y que decide quién es usted con una función. Las funciones tienen ramas, y una de ellas atiende el caso en que lo primero que intentó no funcionó.

LiteLLM no inventó esa forma. Toda pasarela tiene una puerta de entrada, toda puerta de entrada tiene una función de autenticación, y una función de autenticación que admite dos esquemas de credencial tiene una ruta que toma cuando el primero falla. El alcance que hay detrás de esa puerta es deliberado: concentrarlo es el producto. Así que, cuando una pasarela se mete en problemas, todo lo que guarda ya está en la sala.

La conclusión habitual ante un incidente así es “volvamos a las claves por desarrollador”, que es peor en cualquier medida que se tome. Siga centralizando. La pregunta que merece discusión es dónde se sitúa la cosa centralizada, y si tiene que atender peticiones de desconocidos para hacer su trabajo.

Dónde coloca Bromure el mismo trabajo

Bromure Agentic Coding ejecuta cada agente de código en una VM Linux virtualizada por hardware en su propio Mac, y cada control de seguridad se sitúa en el lado del anfitrión de esa frontera. Los controles son la misma lista que ofrece una pasarela: guardar las credenciales, mediar los servidores MCP, clasificar lo que el agente hace con su infraestructura, llevar el registro. Nada en ninguna red puede alcanzar el componente que los aplica.

No hay puerta de entrada. El HTTPS del invitado nunca sale por la red. Se tuneliza sobre un socket virtio, el puerto vsock 8443, hasta el proxy del anfitrión, y el manual es tajante sobre la topología: la VM no tiene ninguna otra ruta hacia la red. El proxy no mantiene ningún puerto a la escucha que su LAN, su red corporativa o internet puedan direccionar. Nunca pregunta quién llama, porque una sola cosa está al otro extremo de ese socket y el hipervisor decide qué es esa cosa. Ninguna cabecera Authorization, ningún almacén de claves, ninguna negociación de esquema y, por tanto, ninguna rama que tomar cuando el primer esquema falla.

El token bearer de MCP es falso antes incluso de llegar al agente. Para los servidores MCP con transporte HTTP configurados en un espacio de trabajo, el token bearer real permanece cifrado en el Mac. La configuración del agente recibe un sustituto brm-mcp_…. El panel de ajustes etiqueta ese campo como Nunca enviado a la VM — sustituido por el proxy, y el proxy del anfitrión coloca el valor real en el cable, acotado por coincidencia exacta o de subdominio al host de ese servidor y a ningún otro. El proxy también responde 404 a las rutas de descubrimiento OAuth y OIDC del servidor, de modo que Claude Code trate el servidor como preautenticado en vez de intentar un flujo de navegador que la VM nunca podría completar. El respaldo de LiteLLM se apoyaba en esa misma superficie de passthrough. Aquí el espacio de trabajo no guarda credencial alguna que se le pueda caer.

Cada operación recibe su propia decisión. Una pasarela zanja la cuestión en la puerta: pásela, y todo lo que hay detrás es suyo. Los Guardrails de Bromure clasifican las llamadas del agente dentro del proxy, a través de Kubernetes, AWS, forjas git, registros de contenedores y bases de datos, y aplican una política de escritura por servicio. Los espacios de trabajo nuevos vienen con Preguntar antes de escribir, de modo que las lecturas fluyen y cada mutación se detiene en un diálogo del lado del anfitrión que muestra la operación literal: el SQL exacto, o MÉTODO /ruta. Solo lectura bloquea toda mutación. Preguntar antes de usar controla la credencial misma, con concesiones medidas en minutos. Una sesión falsificada sigue sin poder abrirse paso con un kubectl delete a través de nada, porque la segunda decisión ocurre en su Mac y no le debe nada a cómo fue la primera.

Denegar por defecto responde a la alcanzabilidad, en ambos sentidos. El cortafuegos de salida del espacio de trabajo es una tabla de reglas ordenada con un valor por defecto para el tráfico no coincidente. Póngalo en Denegar y la VM alcanza los hosts que usted listó y nada más, en cualquier protocolo. Dos componentes fuera del invitado lo aplican: el conmutador virtual empareja cada flujo por IP de destino y por nombre de host captado del DNS, y el proxy vuelve a emparejar por el nombre de servidor TLS. Las ediciones llegan a las sesiones en marcha sin reiniciar. En el otro sentido, el modo NAT mantiene las VM fuera de su LAN física, y nada del exterior abre una conexión hacia ellas a menos que usted publique un servicio a propósito. Los escáneres que barrieron aquellas pasarelas expuestas no obtienen respuesta alguna de un Mac.

Lo que devuelve una pasarela comprometida es entrada no confiable. Esta parte sobrevive a la CVE. Una vez que una pasarela pertenece a otra persona, la salida del modelo, los resultados de herramientas y las cadenas de error llegan todos de un atacante, por el cable de mayor privilegio de la pila: aquel sobre el que el agente está construido para actuar. El detector de código fuente de Bromure puntúa los tramos tool_result en el tráfico de IA saliente del agente con un modelo PromptGuard local, en el dispositivo, antes de que el modelo actúe sobre ellos, y puede registrar, preguntar o bloquear; un bloqueo devuelve HTTP 451 y el modelo nunca ve el contenido.

El tramo de exfiltración falla en cerrado. Cada credencial de un espacio de trabajo es una falsificación determinista con un único destino legítimo. El proxy examina cada petición saliente en busca de una falsificación que vaya adonde no fue acuñada; cuando encuentra una, rechaza la petición sin reenviar un solo byte, pausa la VM y levanta una alerta, registrada como una fila roja de Credential brokering en la Security Timeline. Como solo la falsificación estuvo al alcance, la credencial real no necesita rotarse.

la autoridad en medioun servicio, alcanzable por todo lo que sepa enrutaragente · equipo Aagente · equipo Bun desconocidotoken inventadopasarela de IAescuchando en :443la función de auth lee una cabeceraguarda todas las claves de APIguarda todo el cableado MCPuna rama lo decide todoproveedores de modelos · bases · nube · apps internasalcanzados con la autoridad de la pasarela, no la de quien llamalo que necesita un atacanteuna ruta hasta el puerto y una rama mala en la comprobaciónla autoridad en el bordeun Mac, un hipervisor, nada a la escuchaVM del espacio de trabajo · aquí corre el agentebrm-mcp_… · sk-ant-api03-brm-… · ghp_…solo sustitutos — ningún secreto real en el invitadovsock 8443 — la única salidaproxy del anfitrión · en su Macsin puerto a la escucha · sin cabecera · sin rama de reservacoloca la credencial real, acotada a un solo hostcortafuegos de salida · política de escritura · escaneouna fila de traza por petición, en su máquinalo que necesita un atacanteuna ruta que no existe, hacia un puerto que no está abierto
A la izquierda: la autoridad en medio. Un servicio de red guarda todas las claves y todo el cableado MCP, y una sola función de autenticación se interpone entre él y cualquiera que sepa enrutar hasta él. A la derecha: la autoridad en el borde. Los mismos controles corren en su Mac detrás de un hipervisor, alcanzados por un socket virtio sin puerto a la escucha. La VM guarda solo falsificaciones, y el proxy resuelve cada operación después de que la petición haya salido del invitado.

Si hoy opera una pasarela

Actualice LiteLLM a 1.84.0 o posterior; si no puede, bloquee /mcp/ en el proxy inverso que tenga delante. Después siga el propio consejo de LiteLLM sobre la corrección de la cabecera Host y trate un proxy expuesto como un almacén de claves expuesto: rote las claves de proveedor que guardaba, audite los registros de administración. Las agencias federales tienen hasta el 16 de septiembre con la CVE-2026-59822, una fecha razonable para tomar prestada.

La regla que encoge la pregunta

En el panel Guardrails del espacio de trabajo, ponga Tráfico no coincidente en Denegar y liste lo que el trabajo necesita: allow web api.github.com, allow web registry.npmjs.org, default deny. Un espacio de trabajo que no tiene permiso para alcanzar una pasarela interna no puede usarse para atravesar una, y guardar empuja la política a las sesiones vivas sin reiniciar.

Guarde el secreto, no lo compruebe

Una línea de las propias notas de arquitectura de Bromure merece una relectura tras una semana como esta:

Saltarse la frontera no le da nada a un atacante, porque la frontera no es el lugar donde los secretos se comprueban: es el único lugar donde los secretos existen.

Una pasarela es un lugar donde las credenciales se comprueban: llega una petición, una función la inspecciona, y el veredicto de esa función es lo único que se interpone entre quien llama y las claves. Las comprobaciones tienen casos límite y rutas de reserva. Las comprobaciones se ganan una CVE, una entrada KEV y un plazo federal, y luego se ganan otra dos meses después en una rama distinta de la misma función.

Una frontera de cable es un lugar donde las credenciales están. Nada llega para ser inspeccionado, así que ningún veredicto puede salir mal. El token real descansa cifrado en un Mac, el espacio de trabajo guarda un sustituto brm- que no vale nada en ningún sitio, y la sustitución ocurre en un socket en el que solo un hipervisor puede escribir.

Hemos escrito variaciones de esto tres veces en seis semanas: un proxy de salida que confió en un nombre de host que el agente podía escribir, un guardián de comandos que leía bash de forma distinta a bash y tres agentes de código cuyas elusiones terminaban todas en una credencial real dentro de un proceso. Cada vez, el componente que falló estaba haciendo un trabajo honesto de evaluar algo, y esa es la constante. La evaluación es una primitiva más débil que la ausencia, y seguimos entregándole a la evaluación el trabajo que la ausencia hace gratis.

Centralizar la autoridad de sus agentes fue la decisión correcta. Ponga la cosa centralizada donde nadie pueda enviarle una petición. Instale Bromure Agentic Coding y dele a cada agente una frontera sin puerta de entrada.