- En sistemas tipo Unix, clonar un repositorio no confiable con
git clone --recursive puede permitir ejecución remota de código mediante CVE-2025-48384, por lo que es necesario actualizar Git y el software que lo incluye
- La causa está en una diferencia en cómo se manejan los retornos de carro (
\r) al leer y reescribir la configuración de Git, lo que hace que el valor validado no coincida con el valor que se usa realmente
- Si se agrega
\r al final del path de un submódulo en .gitmodules, la ruta de checkout puede cambiar a otra ruta después de la validación
- Windows no es directamente vulnerable porque no permite caracteres de control en nombres de archivo, pero macOS es vulnerable tanto a CVE-2024-32002 como a CVE-2025-48384
- El parche cambia el comportamiento para envolver entre comillas los valores de configuración que contienen
\r, bloqueando rutas de ataque como la escritura de archivos dentro de .git y la creación de hooks de Git
Resumen de la vulnerabilidad y acciones inmediatas
- CVE-2025-48384 es una vulnerabilidad de Git que, en plataformas tipo Unix, puede derivar en ejecución remota de código al clonar un repositorio no confiable con
git clone --recursive
- Se debe actualizar a una versión corregida de Git y también actualizar el software que incluye Git, incluido GitHub Desktop
- Si se ejecuta solo
git clone desde la línea de comandos, los submódulos no se clonan automáticamente
- Como mitigación, se puede ejecutar primero
git clone sin --recursive, verificar que .gitmodules sea seguro y luego inicializar los submódulos
- GitHub Desktop clona con la opción recursiva de forma predeterminada, por lo que puede verse afectado por ese comportamiento
Retorno de carro y archivos de configuración de Git
- El retorno de carro es el carácter ASCII número 13, Carriage Return, y en cadenas de C se representa como
\r
- Unix pretendía usar solo LF, es decir
\n, como separador de líneas, pero Windows y varios protocolos de Internet usan CR+LF, es decir \r\n
- El formato de configuración estilo
.ini de Git se usa no solo en archivos de configuración de usuario, sino también en el archivo .gitmodules incluido en los repositorios
- Para soportar finales de línea DOS, el parser de configuración de Git se comporta así al leer caracteres
- Si el carácter actual es
\r, revisa el siguiente carácter
- Si el siguiente carácter es
\n, descarta \r y lo trata como salto de línea
- Si el siguiente carácter no es
\n, devuelve el siguiente carácter y retorna el propio \r
- Este procesamiento se aplica línea por línea, por lo que si una línea termina en CR, ese CR puede eliminarse independientemente del formato general del archivo
Inconsistencia entre lectura y escritura
- Git no solo lee archivos de configuración; también escribe pares
key = value en el mismo formato al guardar valores de configuración, como con git config
- El código anterior solo envolvía el valor entre comillas dobles al reescribir una configuración en estos casos
- Si el valor empezaba con un espacio en blanco
- Si el valor contenía
; o #
- Si el valor terminaba con un espacio en blanco
- En cambio, el código de lectura de configuración soporta cadenas entre comillas dobles, por lo que al volver a leer un valor escrito por
write_pair, el último \r puede desprenderse
- Por ejemplo, si en el archivo de configuración hay
key = "foo^M", después de reescribirse puede quedar como key = foo^M
- Aquí
^M es un carácter CR literal
- Cuando este comportamiento se combina con valores no confiables de
.gitmodules, el manejo de rutas de submódulos se desestabiliza
Confusión de rutas de submódulos y alcance del impacto
- En sistemas basados en Unix se pueden incluir caracteres de control en nombres de archivo, por lo que es posible poner un valor con CR en el
path de .gitmodules
- Un ejemplo tendría esta forma
[submodule "foo"]
path = "foo^M"
- Si este valor se registra en
.git/modules/foo/config mediante el código de configuración de Git, puede quedar así
[core]
workdir = ../../../foo^M
- La validación ya terminó sobre la ruta no confiable leída desde
.gitmodules
- Después, cuando se vuelve a leer la configuración y se elimina el
\r final, Git termina usando una ruta distinta de la validada
- Como resultado, durante la clonación de submódulos puede diferir la ubicación leída desde
path = ... y la ubicación que realmente se escribe y se usa
- El principio es similar a CVE-2024-32002
- CVE-2024-32002 confundía a Git usando la sensibilidad a mayúsculas y minúsculas en submódulos
- CVE-2025-48384 requiere un sistema de archivos que permita caracteres de control en nombres de archivo
- Windows no permite caracteres de control en nombres de archivo, por lo que no es directamente vulnerable a este bug específico
- macOS es vulnerable tanto a CVE-2024-32002 como a CVE-2025-48384
Parche y posibilidades de ataque
- El parche modifica
write_pair para envolver la cadena entre comillas cuando el valor contiene \r
- El cambio es simple: agrega
'\r' a la condición que antes solo revisaba ; o #
for (i = 0; value[i]; i++)
- if (value[i] == ';' || value[i] == '#')
+ if (value[i] == ';' || value[i] == '#' || value[i] == '\r')
quote = "\"";
- Con la confusión de rutas, se pueden colocar archivos maliciosos del submódulo en casi cualquier ubicación del sistema de archivos y, al haberse evadido la validación, también se pueden seguir enlaces simbólicos fuera del repositorio
- La forma de explotación más directa es escribir archivos dentro del directorio
.git y crear un script de hook de Git, de modo que cuando Git ejecute el hook se ejecute código controlado por el atacante
- Otra posibilidad es sobrescribir
.git/config
- El PoC aún no se ha publicado, pero se indicó que basta con modificar de forma casi trivial el exploit de CVE-2024-32002
- Las pruebas del commit de corrección pueden dar pistas importantes sobre el método de ataque
Problemas recurrentes con CR y lecciones
- No es la primera vez que un retorno de carro causa problemas en Git
- En enero, RyotaK descubrió un problema en el protocolo de credential helper que podía engañarse con retornos de carro
- En 2023, André Baptista y Vítor Pinho descubrieron CVE-2023-29007, un error lógico en el parseo de configuración
- Esta vulnerabilidad no es un problema propio del lenguaje C, sino más bien un error lógico que podría ocurrir en casi cualquier lenguaje
- El punto en común es que ocurre en la comunicación entre procesos, ya sea entre componentes internos de Git o entre Git y procesos externos
- Se observa una estructura similar en CRLF injection de HTTP, request smuggling y SMTP smuggling
- En el pasado, Internet dependía del principio de robustez de Postel: “sé conservador al enviar y liberal al recibir”, pero hoy puede que ya no sea el consejo más razonable
- Este tema se trata con más detalle en RFC 9413
Agradecimientos y correcciones relacionadas
- Esta vulnerabilidad se descubrió durante una auditoría de Git
- En el mismo lanzamiento también se corrigieron otros bugs de distinta gravedad
- G-Research Open Source hizo posible este trabajo
Aún no hay comentarios.