flawopen.com/Teardowns/cve-2026-105752-vllm-harmony-cache-salt-omission
CVE-2026-105752: omisión de cache_salt en vLLM
Una continuación de herramienta GPT-OSS en Responses de vLLM podía omitir cache_salt y usar un espacio de caché de prefijos sin sal. Actualice a vLLM 0.30.0 o posterior y conserve salts por inquilino en cada continuación.[1], [5]
Imagine los documentos de cada cliente en taquillas con etiquetas de color privadas. La primera solicitud lleva la etiqueta correcta, pero una herramienta la pierde al devolver los documentos para el paso siguiente. Un estante compartido puede indicar mediante un acierto de caché si unas páginas supuestas ya están allí; no entrega las páginas.[1]
Conceptos Clave y Términos
Prefix caching- Reutiliza bloques clave/valor del modelo para prefijos iguales.[6]
cache_salt- Valor mezclado en el hash del primer bloque para separar cachés con salts distintos.[6]
Harmony continuation- Entrada siguiente del modelo tras una respuesta Harmony, también después de una herramienta.[1]
Membership oracle- Señal de presencia de un prefijo supuesto sin revelar el contenido.[1]
CWE-524- Uso de una caché con información sensible; clasificación principal del aviso.[1]
Mapeos de marcos
- Referencia CWE para la debilidad descrita en esta guía: CWE-524
Análisis de Causa Raíz
El aviso de vLLM describe GPT-OSS Harmony en POST /v1/responses. La entrada inicial pasaba request.cache_salt a tokens_input; tras una herramienta integrada o MCP, la continuación usaba tokens_input(token_ids) sin el salt. El helper solo guarda el salt cuando se proporciona. Así, con caché automática de prefijos en un despliegue compartido, la continuación usaba el espacio sin salt. El aviso enumera versiones anteriores a 0.30.0, confirma el comportamiento en 0.25.1 y señala que no se ha establecido el límite inferior. El resultado es una señal de pertenencia a la caché mediante cached_tokens_per_turn, no la divulgación directa de texto arbitrario del prompt. CWE-200 también figura como impacto; aquí CWE-524 es la única debilidad principal.[1], [3], [4]
Flujo de Ataque Paso a Paso
Un servicio compartido cumple los requisitos previos
Se requieren versión afectada, GPT-OSS Harmony Responses, caché de prefijos y una herramienta; la víctima establece cache_salt y alcanza la continuación.[1]
La primera entrada del motor lleva el salt
La llamada inicial de tokens_input incluye request.cache_salt y sitúa el primer prefijo en el espacio con salt del solicitante.[1]
La continuación de la herramienta pierde el salt
Tras el resultado de la herramienta, la continuación llama tokens_input(token_ids) sin el salt original; el prefijo puede entrar en el espacio compartido sin salt.[1]
Un recuento de caché puede revelar pertenencia
Un inquilino que reconstruya el prefijo posterior a la herramienta puede consultar cached_tokens_per_turn para inferir pertenencia, no recuperar texto arbitrario del prompt.[1]
Código Fuente: Vulnerable vs. Seguro
El aviso de vLLM describe GPT-OSS Harmony en POST /v1/responses. La entrada inicial pasaba request.cache_salt a tokens_input; tras una herramienta integrada o MCP, la continuación usaba tokens_input(token_ids) sin el salt. El helper solo guarda el salt cuando se proporciona. Así, con caché automática de prefijos en un despliegue compartido, la continuación usaba el espacio sin salt. El aviso enumera versiones anteriores a 0.30.0, confirma el comportamiento en 0.25.1 y señala que no se ha establecido el límite inferior. El resultado es una señal de pertenencia a la caché mediante cached_tokens_per_turn, no la divulgación directa de texto arbitrario del prompt. CWE-200 también figura como impacto; aquí CWE-524 es la única debilidad principal. Upstream excerpts, not a literal line-by-line diff.[1], [3], [4], [7]
Fragmento de origen: renderer Harmony de Responses de vLLM (fragmentos de revisiones distintas)
# La ruta de la solicitud inicial usaba salt, pero la continuación de la herramienta no.
engine_input = tokens_input(token_ids, cache_salt=request.cache_salt)
# Después del resultado de una herramienta, la continuación reconstruía la entrada así:
engine_input = tokens_input(token_ids)
# Conserva el salt de la solicitud en el contexto de renderizado de Harmony.
cache_salt = cast(str | None, engine_input.get("cache_salt"))
engine_input = self.online_renderer.render_responses_harmony_messages(
context.messages,
cache_salt=cache_salt,
tok_params=tok_params,
)
# El renderizador proporciona el salt cada vez que crea la entrada del motor.
engine_input = tokens_input(prompt["prompt_token_ids"], cache_salt=cache_salt)
Lista de Verificación de Seguridad para Ingeniería
- ✓Actualice a vLLM 0.30.0 o posterior y verifique las versiones en ejecución.[1], [5]
- ✓Genere cache_salt impredecible en la pasarela de confianza y envíelo en cada solicitud y continuación.[6], [1]
- ✓Pruebe que cada continuación Harmony tras herramientas conserva el salt y separa inquilinos.[7]
- ✓Para un aislamiento estricto, separe inquilinos por proceso o despliegue.[6]
- ✓Revise las funciones compartidas y limite el acceso a métricas cached_tokens_per_turn.[1]
- ✓Describa el riesgo como inferencia de prefijo, no como divulgación arbitraria del prompt.[1]