vLLM y trust-remote-code: fijar la versión, usar una clave de API y revisar el código no bastó para detener una sola petición
Si ejecutas vLLM en tu propio servidor y sirves un modelo multimodal con --trust-remote-code, probablemente confíes en tres medidas de protección. Revisaste el código del procesador antes de activar la opción. Fijaste la versión del modelo (revision) para que el código no cambiara sin que lo supieras. Configuraste --api-key para que solo pudieran enviar peticiones quienes tuvieran tu autorización. Un nuevo aviso de seguridad del proyecto vLLM describe una situación en la que, con una configuración concreta y --trust-remote-code activado, una sola petición a la ruta /tokenize puede determinar qué código Python se ejecuta en el servidor. Esa ruta no está protegida por la clave de API.
Lo que señalamos es que cada una de estas medidas se aplica dentro de la aplicación, según el campo o la ruta, y se apoyaba en un supuesto que no se sostuvo. La conclusión práctica es actualizar y, además, definir en el host quién puede acceder al servidor de inferencia y a qué destinos puede conectarse el servidor. Estas dos decisiones no dependen de cómo vLLM interprete una petición.
Qué se ha publicado
El 6 de octubre de 2026 se publicó el aviso de seguridad GHSA-h3rc-6mm3-gc2m. Según el aviso, una petición multimodal puede establecer el valor de code_revision dentro del campo mm_processor_kwargs. Cuando el procesador del modelo en Hugging Face está configurado como código dinámico (auto_map) y el administrador ha activado --trust-remote-code, ese valor se pasa a AutoProcessor.from_pretrained de Transformers. El valor determina de qué versión del repositorio se importa el código del procesador. Importar un módulo Python supone ejecutar código arbitrario en el proceso API/renderer de vLLM.
Puntos principales del aviso:
- Versiones: desde 0.7.3 hasta las anteriores a 0.31.0. La corrección se incluye en 0.31.0 y se integró mediante la pull request número 58830. El aviso indica que la vulnerabilidad se confirmó en un commit concreto con Transformers 5.15.0 y 5.16.1, y que el intervalo de versiones afectadas no se verificó mediante búsqueda binaria (bisect).
- Condiciones: un procesador dinámico mediante
auto_map;trust_remote_codeactivado; el servidor puede descargar la versión elegida en la petición, o ya la tiene en caché; el atacante puede crear o controlar una versión en el repositorio del modelo que se sirve —según el aviso, una referencia de una pull request de la comunidad en Hugging Face es un ejemplo, cuando el repositorio lo permite—; y una petición multimodal llega al flujo de procesamiento del procesador. Con la configuración predeterminada,trust_remote_code=False, el servidor no se ve afectado. - Autenticación: según el aviso, el componente de autenticación de vLLM solo protege las rutas que empiezan por
/v1,/v2,/inferencey/cohere. El campo también se acepta en una petición de tokenización de chat, por lo que/tokenizesigue abierto aunque se haya configurado--api-key, salvo que lo proteja un proxy externo. - Gravedad: quien notificó la vulnerabilidad propuso una puntuación de 9.8, pero la clasificación publicada es High, con una puntuación CVSS de 8.1 y una complejidad de ataque alta. No hay identificador CVE. Las categorías son CWE-94 y CWE-829.
- Demostración: según el aviso, la demostración se ejecutó sin conexión a la red, sin GPU, sin pesos del modelo y sin modificar un repositorio real. El aviso no describe casos de explotación real.
En el resumen de la cobertura de LinuxSecurity, se describe la actualización como una versión que incluye correcciones críticas. Sin embargo, la clasificación publicada en el propio aviso es High.
Fijar la versión fija los datos, no el código
Quien fija revision supone que está fijando todo lo que acompaña al modelo. Según el aviso, vLLM sí fijaba revision y trust_remote_code, pero pasaba el resto de los parámetros de la petición sin proteger code_revision. Transformers usa ese valor para elegir el código y lo elimina antes de cargar los datos del procesador. El resultado, tal como lo describe el aviso: el código procede de la versión controlada por el atacante, mientras que la configuración y los datos permanecen en la versión fijada por el administrador. Si revisaste el código antes de activar la opción, revisaste una versión. Con esta vulnerabilidad se ejecutaba otra.
Por tanto, --trust-remote-code no es solo un ajuste técnico que se activa para que funcione un modelo. Activarlo supone decidir que se va a ejecutar código de una fuente externa. La pregunta decisiva es quién elige ese código. En la versión vulnerable, lo determinaba la petición.
La clave de API protege prefijos, no el servidor
Es fácil suponer que configurar --api-key bloquea el acceso al servidor a quienes no tienen una clave. Según el aviso, la protección se define por prefijos de ruta, y /tokenize no está entre ellos. La guía de seguridad de vLLM también lo señala como una ruta sin protección. Por eso, en un servidor vLLM accesible por la red, no basta con preguntar si has configurado una clave. Hay que comprobar qué rutas son accesibles sin clave y qué procesa cada una.
Por eso es más importante revisar la exposición del servicio completo que la configuración de una sola ruta. Si solo pueden acceder al puerto de vLLM los servicios que lo necesitan, las consecuencias de que una ruta quede fuera del mecanismo de autenticación se reducen mucho.
La capacidad de descargar forma parte del ataque
Una de las condiciones del aviso es que el servidor pueda descargar la versión elegida en la petición, o que ya la tenga en caché. Un servidor cuyo modelo se ha preparado de antemano no tiene por qué acceder al repositorio durante la ejecución. Se puede bloquear el acceso a cualquier destino que no necesite. Conviene recordar que, si mantienes el acceso al propio Hugging Face, la versión controlada por el atacante está en el mismo repositorio. Por eso, la actualización a 0.31.0 sigue siendo la corrección.
También conviene revisar la condición relativa al repositorio. Según el aviso, una referencia de una pull request de la comunidad es un ejemplo de una versión que un atacante puede controlar en un repositorio que lo permita. En ese sentido, un repositorio público abierto a contribuciones es una fuente de código que no está por completo bajo tu control.
El punto en común
En los tres casos, la protección se aplicaba donde la aplicación interpreta la entrada: un campo que no se protegió, una ruta que no se incluyó. Estas medidas dependen de que el desarrollador haya tenido en cuenta cada campo y cada ruta. En cambio, hay dos preguntas a nivel del host que no cambian aunque se descubra un campo nuevo: quién puede acceder al puerto del servidor de inferencia y a qué destinos puede conectarse su proceso. Según el aviso, el código se ejecuta en el proceso API/renderer y afecta a la confidencialidad, la integridad y la disponibilidad.
Qué hacer en el servidor
- Actualiza a 0.31.0. Comprueba la versión del proceso que recibe las peticiones, no solo la etiqueta de la imagen que descargaste. Un contenedor que ya está en ejecución no se actualiza por sí solo.
- Comprueba si necesitas
--trust-remote-code. Si el modelo no lo requiere, desactívalo. Si lo requiere, comprueba si su procesador está configurado como código dinámico medianteauto_map. - Revisa el repositorio del modelo que sirves. ¿Permite pull requests de la comunidad? ¿Quién puede crear versiones en él?
- Limita el acceso al servidor de inferencia desde la red. No expongas vLLM directamente a Internet. Permite el acceso solo a los servicios que lo necesitan. Si hay un proxy delante, asegúrate de que también exige autenticación en
/tokenize. Compruébalo con una petición independiente a esa ruta. - Identifica el tráfico saliente del servidor de inferencia. Comprueba a qué destinos se conecta durante la ejecución y limita el acceso a los que realmente necesita.
- Comprueba qué más se está ejecutando. Es fácil pasar por alto un servidor de modelos que se montó para una prueba y sigue activo con una versión antigua y la opción activada.
Cómo ayuda nuDefend
Saber qué se está ejecutando. El comando nudefend workloads muestra las herramientas de IA que se ejecutan en el servidor, incluidos los servidores de modelos, tanto si se ejecutan directamente en el host como dentro de un contenedor. Junto a cada herramienta se muestra la información en la que se basó su identificación, como una unidad de systemd, el nombre de una imagen o un patrón en la línea de comandos. Así también puedes encontrar un servidor de modelos que se montó para una prueba y quedó olvidado.
Saber quién puede acceder. El comando nudefend expose muestra cada servicio que escucha en el servidor y quién puede acceder a él, desde el punto de vista del propio servidor. La vista también incluye los servicios publicados desde un contenedor. Si un servicio que antes solo era accesible desde dentro pasa a ser accesible desde fuera, nuDefend detecta el cambio y avisa. Si el servidor de inferencia está expuesto sin que esa fuera tu intención, puedes bloquear su puerto desde el panel o desde la línea de comandos. Antes del bloqueo, una vista previa muestra exactamente qué se bloqueará. Cada bloqueo queda registrado y se puede deshacer con un clic. Más información en la página sobre exposición.
Controlar a dónde se conecta. nuDefend registra a qué destinos se conecta cada herramienta de IA del servidor, el volumen de tráfico hacia cada destino y cuándo se detectó por primera vez. Cuando se identifica el destino, se muestran su nombre y su tipo de actividad, por ejemplo, una fuente de descarga de software y modelos. Con esa información puedes limitar una herramienta concreta a los destinos que hayas autorizado. Cada intento de conexión a otro destino se bloquea antes de que el tráfico salga del servidor, y el resto del servidor sigue funcionando con normalidad. nuDefend también limita las direcciones que la herramienta puede resolver, y cada consulta bloqueada se muestra junto al nombre de la herramienta. Más información en la página sobre tráfico saliente.
Una capa básica. El tráfico hacia direcciones IP y dominios conocidos como maliciosos, así como el que procede de ellos, se bloquea en el cortafuegos del kernel. El bloqueo se basa en listas de amenazas firmadas que se actualizan cada 30 minutos. El panel muestra un contador del tráfico saliente bloqueado. Un valor superior a cero puede ser una señal temprana de que algo en el servidor ha intentado contactar con una fuente maliciosa.
En resumen
La vulnerabilidad en vLLM muestra que tres medidas de protección razonables —fijar la versión, usar una clave de API y revisar el código— se aplicaban dentro de la aplicación y se eludieron mediante un solo campo y una sola ruta. Actualiza a 0.31.0 y desactiva --trust-remote-code si no lo necesitas. Además de actualizar, define en el host quién puede acceder al servidor de inferencia y a qué destinos puede conectarse el servidor. Estas decisiones siguen vigentes aunque se descubra otro campo.
nuDefend muestra a qué destinos se conecta tu servidor de modelos y permite limitar una herramienta concreta a los destinos que hayas autorizado. Cada intento de conexión a otro destino se bloquea antes de que el tráfico salga del servidor.