Saltar al contenido
CVE-2026-95832 ·
Crítica · 25 de septiembre de 2026

Nombres de campos desconocidos reflejados en el código de escape de control de color de kitty permiten la ejecución de comandos en la shell del usuario

S0
Secur0 CNA
CVE-2026-95832

Descripción

Neutralización incorrecta de elementos especiales en una salida utilizada por un componente posterior (CWE-74) en color_control() (kitty/window.py), en el manejador del código de escape de control de color, en kitty desde 0.47.3 y anterior a 0.49.0, que permite a un programa que escribe en el terminal ejecutar un comando arbitrario en la shell del usuario, porque la función responde a una consulta sobre un nombre de campo no reconocido colocando ese nombre de campo en la respuesta, que write_escape_code_to_child() (kitty/screen.c) escribe después en el maestro del pseudoterminal sin neutralizarla para la shell que la lee. Esto da lugar a la ejecución de un comando elegido por el atacante con los privilegios del usuario que ejecuta el terminal.

Escribir en el maestro del pseudoterminal no se distingue de que el usuario teclee, por lo que el texto reflejado acaba en la línea de comandos de la shell. El reflejo es la vulnerabilidad.

Se trata de una corrección incompleta. La inyección de comandos a través de este manejador se abordó en 0.47.3 mediante el commit 424fe999, que reduce la carga a ASCII imprimible, y ese cambio es la corrección de CVE-2026-54057. Su comentario recoge que la restricción existe porque el valor se devuelve como eco. La restricción sí excluye los caracteres de control, y los separadores de registro y de campo ; y = se consumen como delimitadores, pero sobrevive cualquier otro carácter imprimible, lo que basta para componer un comando de shell.

El salto de línea que envía la orden debe entonces provenir de otro sitio, y no es escaso: handle_remote_ssh() escribe los bytes que produce get_ssh_data() (kittens/ssh/utils.py) directamente en el maestro del pseudoterminal, y los primeros de esos bytes comienzan por un salto de línea, emitido antes de comprobar cualquier credencial incluida en la solicitud. Ese manejador es alcanzable sin autenticación en todas las versiones, incluida v0.49.0.

La respuesta se enmarca como una secuencia OSC y transporta el número del código de escape, el nombre del campo y el valor literal ?, por lo que el atacante elige una subcadena de la línea y no la línea completa.

No interviene corrupción de memoria ni hay nada que preparar o adivinar.

La única acción requerida de la víctima es que el texto del atacante se muestre en una ventana cuyo proceso hijo sea una shell en un indicador de órdenes. Leer un fichero descargado, seguir un registro que contiene cadenas influidas por el atacante, un banner de inicio de sesión SSH, la salida de un comando ejecutado contra un servidor controlado por el atacante, o un nombre de fichero manipulado mostrado en un listado de directorio, son todos suficientes.

Tipo de vulnerabilidad (CWE)

  • CWE-74: Neutralización incorrecta de elementos especiales en una salida utilizada por un componente posterior ('Injection')

Versiones afectadas

kitty desde 0.47.3 y anterior a 0.49.0. La restricción a ASCII imprimible a la que se refiere este registro está presente por primera vez en v0.47.3. Están afectadas todas las versiones desde v0.47.3 hasta v0.48.2, ambas incluidas, a saber v0.47.3, v0.47.4, v0.48.0, v0.48.1 y v0.48.2. Las versiones anteriores a v0.47.3 reflejan el nombre de campo sin restricción de caracteres y están cubiertas por CVE-2026-54057. Estado por defecto: no afectado.

Puntuación (CVSS 4.0)

Crítica (9.3)

CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H

El vector de ataque es Local porque kitty lee un pseudoterminal y no un socket de red; la llegada por SSH es entrega, no el vector hacia el componente vulnerable. La interacción del usuario es Pasiva porque a la víctima le basta con que el texto se muestre. El comando se ejecuta con los privilegios del usuario, por lo que el impacto recae tanto sobre el terminal como sobre el sistema subsiguiente.

Existe un exploit funcional para esta vulnerabilidad.

Solución

Actualizar a kitty 0.49.0 o posterior.

Parche

Commit 03fbdad8, que informa de un campo no reconocido como unknown=<nombre de campo codificado en base64> en lugar de colocar el nombre del campo en la respuesta, confinando el texto reflejado a un conjunto de caracteres con el que no puede construirse un comando de shell. Además restringe los números de color y los índices de color de fondo transparente a cadenas de dígitos canónicas, de modo que valores como un número con relleno se tratan como campos desconocidos en lugar de reflejarse con ese relleno, y evita una excepción no controlada ante un índice no numérico. Este commit es la corrección: elimina el reflejo, que es el único control que el atacante tiene sobre el texto.

El commit 57bb144d, en la misma versión, sustituye una comprobación de sólo dígitos en handle_remote_echo() que admitía un salto de línea final, porque el $ de Python también coincide justo antes de uno. Esa comprobación se introdujo a su vez en v0.48.2 como corrección de CVE-2026-72913, y el manejador filtraba su carga a ASCII imprimible en todas las versiones anteriores, por lo que este commit cierra una regresión de un problema distinto y no es la corrección de éste. En el registro se cita como referencia relacionada y no como parche.

Créditos

  • Gabriel Machado Tavares - descubridor
  • Cristian Fernández Cornejo - analista
  • Xoán M. Otero Jorge - analista
  • Secur0 CNA - coordinador
  • Kovid Goyal - desarrollador de la corrección Origen del descubrimiento: Externo

Registro oficial: CVE-2026-95832

Registros relacionados

  • CVE-2026-54057 - la inyección de comandos anterior en este manejador, corregida en 0.47.3 mediante la restricción a la que se refiere este registro
  • CVE-2026-72913 - el problema del código de escape kitty-echo cuya corrección repara el commit 57bb144d

Avisos relacionados

  • CVE-2026-95834 - Severidad media
  • CVE-2026-95835 - Severidad media