FlawOpen

flawopen.com/Teardowns/cve-2026-102422-shell-quote-comment-line-terminator-injection

● CVE-2026-102422 · CVSS 8.1 · Alta
Investigación · FlawOpen

CVE-2026-102422: inyección mediante tokens de comentario en shell-quote

Antes de shell-quote 1.11.0, un token de comentario seguido de una cadena con un terminador de línea podía cambiar el significado de la salida citada al entregarla a un shell POSIX. La condición requiere tokens influidos por un atacante, una llamada a quote() y ejecutar su salida mediante un shell; actualice a 1.11.0 o posterior.

💡 Explicación en Lenguaje Sencillo (ELI5)

Un comentario en una etiqueta puede ocultar todo lo que sigue hasta el final de la línea. Si la parte siguiente contiene un salto de línea, el comentario termina antes y el resto vuelve a quedar visible. Este fallo permitía que un token posterior hiciera eso en la salida citada para el shell.

Conceptos Clave y Términos

shell-quote
Paquete JavaScript que analiza y cita tokens de estilo shell; su salida sigue destinada a sintaxis de shell, no a un formato universal de texto seguro.
Token de comentario
Token que representa la sintaxis de comentario del shell y cuyo efecto puede continuar hasta un terminador de línea.
Terminador de línea
Límite de línea como CR, LF, U+2028 o U+2029 que el shell puede interpretar como fin del comentario.
CWE-78
Neutralización incorrecta de elementos especiales usados en un comando del sistema operativo.

Mapeos de marcos

  • Referencia CWE para la debilidad descrita en esta guía: CWE-78

Análisis de Causa Raíz

La ruta afectada de quote() rechazaba terminadores dentro del propio token de comentario, pero no recordaba que ya había emitido un comentario. Por eso una cadena posterior podía contener un terminador. Si tokens influidos por un atacante llegan a quote() y la salida se ejecuta mediante un shell POSIX, el límite de línea cierra el comentario y el shell interpreta el texto siguiente como sintaxis. La corrección registra el estado de comentario y rechaza terminadores en todas las cadenas posteriores. Esto es distinto de CVE-2026-9277, cuya corrección rechazaba terminadores dentro del token de comentario. Los mantenedores asignan gravedad Alta y CVSS 3.1 8,1; Ubuntu publica una evaluación separada CVSS 4.0 9,2 Crítica. Son versiones distintas de CVSS y no deben mezclarse.

Flujo de Ataque Paso a Paso

Paso 1

Los tokens llegan a la función de cita

La aplicación crea tokens con un comentario y una cadena posterior; el atacante debe poder influir en esa secuencia.

Paso 2

La función emite sintaxis de comentario

Antes de 1.11.0, quote() validaba el comentario, pero no recordaba que después habría cadenas.

Paso 3

Un token posterior contiene un límite de línea

CR, LF, U+2028 o U+2029 puede terminar el comentario del shell.

Paso 4

El programa ejecuta la salida con un shell

La interpretación documentada afecta a los llamadores que pasan la salida a un shell POSIX.

Paso 5

La actualización rechaza la secuencia

La versión 1.11.0 registra que hubo un comentario y lanza un error si una cadena posterior contiene un terminador.

Código Fuente: Vulnerable vs. Seguro

El fragmento vulnerable comprueba los terminadores de línea del token de comentario, pero no conserva el estado para las cadenas posteriores. El cambio upstream registra que se emitió un comentario y rechaza una cadena posterior que contenga un terminador. Este fragmento ilustra el límite entre análisis y cita; no es un exploit ni un comando de shell.

Fragmento de origen: quote.js — focused upstream diff hunks

IMPLEMENTACIÓN VULNERABLE
// quote.js antes del commit 6002b2e — fragmento centrado en el token de comentario
if ('comment' in s && typeof s.comment === 'string') {
  if (LINE_TERMINATORS.test(s.comment)) {
    throw new TypeError('`comment` must not contain line terminators');
  }
  return '#' + s.comment;
}
PARCHE SEGURO Y ROBUSTO
// quote.js después del commit 6002b2e — fragmento exacto de la nueva protección y el estado del comentario
var sawComment = false;
return xs.map(function (s) {
  if (sawComment && typeof s === 'string' && LINE_TERMINATORS.test(s)) {
    throw new TypeError('a token after a `comment` must not contain line terminators');
  }
  if ('comment' in s && typeof s.comment === 'string') {
    if (LINE_TERMINATORS.test(s.comment)) {
      throw new TypeError('`comment` must not contain line terminators');
    }
    sawComment = true;
    return '#' + s.comment;
  }
});

Lista de Verificación de Seguridad para Ingeniería

Fuentes