sistema: OPERATIVO
← volver a todos los hacks
INFRASTRUCTURE CRITICAL

BadHost (CVE-2026-48710): un solo carácter en el encabezado Host elude la autenticación en Starlette, vLLM y FastMCP

X41 D-Sec divulgó el 22 de mayo de 2026 un bypass de autorización crítico en Starlette < 1.0.1. Un único / ? o # en el encabezado HTTP Host desincroniza la ruta enrutada respecto a la ruta que ve el middleware, rompiendo la autorización basada en path en vLLM, LiteLLM, FastMCP y miles de agentes de IA construidos sobre FastAPI.

2026-05-27 // 8 min affects: starlette, fastapi, vllm, litellm, fastmcp, mcp-servers, text-generation-inference

¿De qué se trata?

El 22 de mayo de 2026, la firma alemana de seguridad X41 D-Sec divulgó públicamente CVE-2026-48710, apodada BadHost: un bypass de autorización no autenticado en el framework ASGI de Python Starlette, el núcleo de enrutamiento de FastAPI. La vulnerabilidad fue descubierta el 27 de enero de 2026 durante una auditoría del servidor de inferencia vLLM financiada por OSTIF, reportada a los mantenedores de Starlette el 4 de febrero, y parcheada el 21 de mayo de 2026 con Starlette 1.0.1 — un día antes de la divulgación pública.

Starlette se descarga aproximadamente 325 millones de veces por semana. A través de FastAPI sustenta una porción muy significativa del stack moderno de infraestructura de IA: vLLM, LiteLLM, Text Generation Inference, proxys de API compatibles con OpenAI, servidores MCP (incluido FastMCP), planos de control de agentes y dashboards de model serving. Todas las versiones desde 0.8.3 hasta 1.0.0 están afectadas.

El bug es minúsculo, el radio de impacto es enorme, y la ventana entre el parche y la divulgación fue prácticamente nula.

Cómo funciona

Starlette reconstruye request.url concatenando el encabezado HTTP Host con la ruta de la petición y re-parseando el resultado como una URL. El valor de Host no se valida contra la gramática RFC 9112 / RFC 3986 antes de la reconstrucción. Cualquier byte que el cliente envíe en Host: fluye directamente al parser de URL.

Si un atacante inyecta /, ? o # en el encabezado Host, las fronteras entre autoridad, ruta, query y fragmento se desplazan durante el re-parseo. La ruta que ve el router (tomada del scope ASGI, derivada de la línea de petición HTTP) y la ruta que ve el middleware (request.url.path) divergen. Cualquier decisión de autorización basada en path tomada en el middleware se aplica entonces a una cadena distinta de aquella sobre la que el router despacha.

# Esquema conceptual de la desincronización, basado en la
# divulgación pública del 22 de mayo de 2026. No se reproduce
# aquí ningún payload contra un sistema en producción.

Cable:    GET /admin HTTP/1.1
          Host: foo?

Scope ASGI (la verdad):
  scope["path"]            = "/admin"     # el router despacha aquí

Reconstrucción Starlette:
  request.url              = "http://foo?/admin"
  request.url.path         = "/"          # el middleware ve esto

Middleware:
  if request.url.path.startswith("/admin"):  # False
      require_auth()
  # auth saltada

Router:
  dispatch("/admin")                         # el handler se ejecuta

El efecto neto: una petición que normalmente devolvería 403 Forbidden en una ruta protegida devuelve 200 OK cuando se añade un único carácter ilegítimo al encabezado Host, mientras el handler protegido se ejecuta de todos modos.

El patrón es genérico. No importa si el middleware es una biblioteca de terceros o un BaseHTTPMiddleware hecho a mano; lo que importa es si lee request.url.path (envenenado) o scope["path"] (la verdad) al tomar una decisión de seguridad.

Por qué importa

Tres propiedades hacen que BadHost merezca atención particular en un contexto de seguridad de IA.

Primero, la cascada. Starlette no es una dependencia de nicho. FastAPI se asienta encima de él, y FastAPI es el framework de facto para desplegar servidores de modelos en Python y planos de control de agentes en 2025-2026. X41 y OSTIF citan explícitamente vLLM, LiteLLM, los proxys compatibles con OpenAI y los servidores MCP entre los proyectos afectados. Quien opere un endpoint de inferencia autoalojado, una gateway LLM interna o un servidor FastMCP detrás de una ACL basada en rutas debe asumir vulnerabilidad hasta haber parcheado y auditado.

Segundo, los servidores MCP están particularmente expuestos. La especificación del Model Context Protocol exige endpoints de descubrimiento OAuth no autenticados; esas rutas son alcanzables de forma fiable sin credenciales y conviven con rutas administrativas que se supone que están autenticadas. Esa disposición es un escenario de manual para un bypass de autorización que pivote de una ruta pública a una protegida mediante confusión del middleware.

Tercero, el calendario de divulgación. La vulnerabilidad se reportó a upstream a principios de febrero. Se propuso un parche a principios de marzo. La corrección solo se publicó el 21 de mayo, y X41 difundió todos los detalles al día siguiente — el margen práctico para los operadores se midió en horas, no en días o semanas como es costumbre. Para librerías tan ampliamente embebidas esto es excepcionalmente corto, y los defensores deben asumir que el escaneo y la explotación oportunista ya están en marcha.

Defensas

La ruta de mitigación es corta y concreta.

Actualizar Starlette a 1.0.1 o superior. Es el paso mínimo y resuelve la causa raíz del problema de parseo. FastAPI, vLLM, LiteLLM, FastMCP y la mayoría de frameworks de agentes dependen transitivamente de Starlette; conviene fijar la dependencia y reconstruir contenedores. El parche valida el encabezado Host contra la gramática RFC 9112 / 3986 y cae a scope["server"] ante valores malformados.

Mover las decisiones de seguridad de request.url.path a scope["path"] en cualquier middleware personalizado. La ruta del scope ASGI proviene de la línea de petición HTTP y no puede ser envenenada vía inyección en Host. Es la corrección arquitectónicamente correcta y debería sobrevivir a cualquier CVE individual: nunca confiar en un valor derivado de un encabezado controlado por el cliente para una decisión de autorización.

Auditar de inmediato sus propios middlewares, incluida cualquier subclase de BaseHTTPMiddleware y middleware ASGI crudo en su stack. X41 ha publicado un escáner remoto gratuito en badhost.org, además de reglas Semgrep y consultas CodeQL en GitHub para detección estática de patrones vulnerables. Aplíquelos a cada servicio FastAPI interno, servidor de modelos y host MCP.

Añadir un guardia en el reverse proxy. Configurar NGINX, Envoy, Traefik o el ingress para rechazar peticiones cuyo encabezado Host contenga /, ?, #, espacios o cualquier byte fuera de la gramática de autoridad RFC 9112. Es una medida útil de cinturón y tirantes contra la próxima variante de esta clase de bugs.

Tratar los servidores MCP / FastMCP como superficie de ataque de producción. Si su host MCP convive con endpoints administrativos, aíselos en un plano de red separado, exija autenticación por certificado cliente o mTLS en las rutas administrativas, y no se base solo en prefijos de ruta para la autorización. Los endpoints obligatorios de descubrimiento no autenticado de la spec MCP hacen frágiles por diseño las ACL basadas en path.

Re-evaluar la clase completa. BadHost es un bug de reconstrucción de URL a partir de encabezados. La misma familia de problemas ha golpeado a numerosos frameworks web a lo largo de los años (Django ALLOWED_HOSTS, Rack, Express). Cualquier punto de su stack que reconstruya una URL a partir de encabezados de petición y luego tome una decisión de confianza sobre ella es candidato a revisión.

Estado

ElementoReferenciaFechaNotas
DescubrimientoX41 D-Sec, auditoría de vLLM financiada por OSTIF2026-01-27Hallado en auditoría externa
Reporte upstreamMantenedores de Starlette notificados2026-02-04Con PoC funcional
Parche propuestoPull request abierta2026-03-01~3 meses hasta la release
Versión corregidaStarlette 1.0.12026-05-21Valida Host contra RFC 9112/3986
Divulgación públicaAviso X41 D-Sec + badhost.org2026-05-22CVE-2026-48710 publicada
Versiones afectadasStarlette 0.8.3 → 1.0.0 inclusiveTodas las builds de FastAPI sobre ellas
Ecosistema afectadoFastAPI, vLLM, LiteLLM, Text Generation Inference, FastMCP, servidores MCPMás miles de frameworks de agentes
Escáner / reglasbadhost.org, repositorio GitHub x41sec/poc2026-05-22Semgrep + CodeQL

La lección es de las que se reaprenden periódicamente: cuando un stack de IA hereda un bug de framework, la IA no añade defensas — solo multiplica el número de despliegues expuestos en Internet. Parchear rápido, mover el middleware a scope["path"], y dejar de confiar en Host para cualquier cosa que controle un acceso.

Sources