
Gitea anterior a 1.27.1 permite la ejecución remota de código a través de la API diffpatch mediante la instalación de hooks de Git.
[!WARNING] Este repositorio está destinado exclusivamente a la investigación de seguridad autorizada y a pruebas de laboratorio controladas. No ejecute la prueba de concepto contra sistemas que no posea o para los que no tenga permiso explícito de evaluación.
CVE-2026-60004 es una vulnerabilidad crítica de ejecución remota de código en la API diffpatch de Gitea. Un usuario autenticado con permiso para crear o escribir en un repositorio puede enviar un parche manipulado que provoca que se materialice un hook de Git ejecutable dentro de un repositorio bare temporal. Cuando se activa el hook, los comandos controlados por el atacante se ejecutan con los privilegios de la cuenta de servicio de Gitea.
Si el registro público está habilitado, un atacante no autenticado podría crear una cuenta y alcanzar el endpoint autenticado vulnerable.
| Atributo | Detalles |
|---|
| Identificador | CVE-2026-60004 |
| Aviso | GHSA-rcr6-4jqh-j84m |
| Gravedad | Crítica — CVSS 3.1: 9.8 |
| Debilidad | CWE-94: Control inadecuado de la generación de código |
| Versiones afectadas | Gitea 1.17.0 hasta 1.27.0 |
| Versión corregida | Gitea 1.27.1 |
| Acceso requerido | Acceso de escritura al repositorio |
| Contexto de ejecución | Cuenta del sistema operativo de Gitea |
| Fecha CISA KEV | 2026-08-25 |
| Archivo | Descripción |
|---|---|
gitea_diffpatch_rce.py | Prueba de concepto que solo usa la biblioteca estándar, la cual se autentica, crea un repositorio privado, envía el parche manipulado y recupera la salida del comando. |
payload.patch | Parche de ejemplo que crea un hook ejecutable hooks/post-index-change. |
poc.png | Captura de pantalla tomada durante la validación en laboratorio. |
README.md | Notas de investigación originales. |
La prueba de concepto se validó en el siguiente entorno aislado:
| Componente | Configuración |
|---|---|
| Gitea | 1.27.0 |
| Git | 2.47.2 |
| Despliegue | Contenedor Docker llamado gitea-lab |
| Dirección del servicio | 192.168.184.128:3000 |
| Identidad observada | uid=1000(git) gid=1000(git) |
La explotación exitosa produjo una salida de comando similar a:
uid=1000(git) gid=1000(git) groups=1000(git)
Linux 6.12.20-amd64 x86_64
/data/gitea/tmp/local-repo/upload.git630501597
[exit-status=0]

El script solo usa la biblioteca estándar de Python y no requiere paquetes adicionales.
python3 gitea_diffpatch_rce.py <base_url> <username> <password> "<command>"
Ejemplo para una instancia de laboratorio local:
python3 gitea_diffpatch_rce.py \
http://127.0.0.1:3000 \
pocuser \
'P@ssw0rd!' \
'id; uname -a'
El script primero intenta el registro web y luego se autentica con las credenciales proporcionadas. Esto permite que el mismo comando funcione tanto con una cuenta nueva en una instancia con registro abierto como con una cuenta existente.
La cadena de explotación consta de cuatro etapas:
Envío de parche controlado por el atacante
POST /api/v1/repos/{owner}/{repo}/diffpatch aplica el contenido del parche proporcionado
usando git apply --index --recount --cached --binary --ignore-whitespace --whitespace=fix -3 dentro de un clon temporal.
Colocación de la ruta del hook
El repositorio temporal se crea como un clon bare compartido. En un repositorio
bare, la raíz del repositorio también es $GIT_DIR; en consecuencia, la ruta del parche
hooks/post-index-change se resuelve dentro del directorio de hooks activo de Git.
Materialización del hook ejecutable
El mismo parche se envía dos veces. La segunda aplicación produce un
conflicto add/add, lo que provoca que el fallback de tres vías materialice la ruta en
disco con modo 100755, a pesar del uso de --cached. Una actualización posterior del índice
invoca post-index-change, ejecutando el código shell inyectado como la
cuenta de servicio de Gitea.
Recuperación de salida nativa de Git
El hook identifica el repositorio de origen a través de
objects/info/alternates, almacena la salida del comando como un blob de Git, crea un
árbol y un commit, y actualiza refs/heads/output-leak. La prueba de concepto
luego recupera el resultado a través de la API de archivos raw de Gitea. Esta técnica
no requiere una conexión saliente directa desde el objetivo.
La explotación exitosa otorga ejecución de comandos con los privilegios de la cuenta de servicio de Gitea. Dependiendo de la configuración del despliegue, un atacante podría acceder a:
app.ini y credenciales de la base de datosSECRET_KEY, INTERNAL_TOKEN y secretos relacionados con LFSSe confirmó que la cuenta de laboratorio tenía acceso de lectura a app.ini.
Los defensores deben investigar los siguientes artefactos y patrones de solicitudes:
/api/v1/repos/*/*/diffpatch en rápida sucesiónoutput-leakpoc <[email protected]>hooks/post-index-change en repositorios
bare o directorios de clones temporales/data/gitea/tmp/local-repo/upload.git*Estos indicadores describen la prueba de concepto incluida y no son exhaustivos; un exploit modificado podría usar rutas, refs, identidades o canales de salida diferentes.
/api/v1/.../diffpatch.
Valide la regla contra integraciones legítimas antes del despliegue.DISABLE_REGISTRATION=true si
no es operativamente necesario. Esto reduce la accesibilidad no autenticada pero
no protege contra usuarios existentes con acceso de escritura a repositorios.Para el contenedor de laboratorio usado en esta investigación, la eliminación se puede realizar con:
docker rm -f gitea-lab
Este material se proporciona para ayudar a los defensores a reproducir, comprender, detectar y remediar la vulnerabilidad. Los operadores deben probar solo en entornos aislados y seguir los requisitos de autorización y divulgación de su organización.