FlawOpen

flawopen.com/Teardowns/cve-2026-105752-vllm-harmony-cache-salt-omission

● CVE-2026-105752 · CVSS 3.1 · Baja
Investigación · FlawOpen

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]

💡 Explicación en Lenguaje Sencillo (ELI5)

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

Paso 1

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]

Paso 2

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]

Paso 3

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]

Paso 4

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]

Paso 5

El renderizador conserva el salt en cada turno

La refactorización integrada conserva cache_salt durante el renderizado Harmony y lo pasa a cada nueva entrada del motor; actualice a 0.30.0+.[1], [3], [7]

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)

IMPLEMENTACIÓN VULNERABLE
# 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)
PARCHE SEGURO Y ROBUSTO
# 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

Fuentes