← Blog

Gitea CVE-2026-20896: la imagen Docker que dejaba entrar a cualquiera como admin

Un fallo crítico (CVSS 9.8) en las imágenes Docker de Gitea permitía suplantar a cualquier usuario, incluido el administrador, con una simple cabecera HTTP. Ya hay sondeos activos en internet contra ~6.200 instancias. Te contamos qué es, si te afecta y qué tienes que hacer hoy.

Un valor por defecto que no debería estar ahí

Si tienes tu propio Gitea corriendo en Docker para alojar el código de tu empresa —cada vez más pymes lo hacen para no depender de GitHub—, este te toca de cerca. La imagen oficial de Gitea venía con una configuración por defecto que, resumida, significaba esto: cualquier cliente de internet podía decirle al servidor «soy el administrador» y el servidor se lo creía.

Se le ha asignado CVE-2026-20896, con una puntuación CVSS de 9.8 sobre 10. Está parcheado desde la versión 1.26.3, pero lo que ha encendido las alarmas esta semana es otra cosa: Sysdig ha detectado los primeros sondeos reales contra servidores Gitea expuestos en internet. Todavía en fase de reconocimiento, pero ya con nombre y apellidos.

En una frase

Gitea permite autenticar usuarios a través de un proxy inverso: el proxy valida al usuario y le pasa a Gitea una cabecera X-WEBAUTH-USER con el nombre de la cuenta. El problema es que la imagen Docker venía configurada con REVERSE_PROXY_TRUSTED_PROXIES=*, es decir, confiaba en esa cabecera viniera de donde viniera.

Traducido: si tenías activada la autenticación por proxy inverso, un atacante podía mandar directamente una petición con X-WEBAUTH-USER: admin y entrar como el administrador sin contraseña, sin token, sin nada.

A quién afecta

  • Versiones: imágenes Docker de Gitea hasta la 1.26.2 incluida. A partir de 1.26.3 el comodín * se ha quitado y la autenticación por proxy pasa a ser opt-in explícito.
  • Condición clave: te afecta si despliegas Gitea con la imagen Docker y tienes activada la autenticación por proxy inverso (ENABLE_REVERSE_PROXY_AUTHENTICATION). Si no usas ese modo de login, el vector directo no aplica —pero aun así conviene actualizar y revisar la config, porque el valor * no debería estar nunca.
  • Superficie: hay unas 6.200 instancias de Gitea expuestas directamente a internet. No todas con el reverse-proxy auth activo, pero suficientes para que valga la pena escanear a lo bruto. Y eso es exactamente lo que está pasando.

Qué se ve ya en la práctica: Sysdig rastreó el primer intento a un nodo de salida de ProtonVPN (159.26.98[.]241). De momento es reconocimiento automatizado —escaneo de puertos HTTP(S), fingerprinting de Gitea e intentos de bypass con la cabecera—, sin explotación completa todavía. Los detectaron pronto. Pero cuando un fallo de 9.8 empieza a sondearse, la ventana para actualizar tranquilo se cierra rápido.

Un apunte honesto sobre las fechas

Que no te vendan humo con esto: el fallo se corrigió en la 1.26.3 a finales de junio y el aviso se hizo público a principios de julio. Lo nuevo de esta semana no es la vulnerabilidad, es que ya se está sondeando activamente. Es una diferencia importante: si actualizaste en junio, estás cubierto y esto es solo un recordatorio de verificar. Si tu Gitea lleva meses sin tocarse, es urgente.

Cómo funciona el fallo

La autenticación por proxy inverso es una función legítima y útil: montas un proxy delante (nginx, Traefik, Authelia…), el proxy valida al usuario contra tu SSO, y le dice a Gitea «este que viene es juan» mediante la cabecera X-WEBAUTH-USER. Gitea confía en el proxy y no vuelve a pedir contraseña.

Todo el modelo se sostiene sobre una premisa: esa cabecera solo puede ponerla tu proxy de confianza. Para eso existe REVERSE_PROXY_TRUSTED_PROXIES, que debería contener la IP (o rango) de tu proxy y nada más.

La imagen Docker la traía como *. Con el comodín, Gitea aceptaba la cabecera de cualquier IP de origen. El atacante ni siquiera necesita pasar por tu proxy: habla directamente con Gitea y se inventa la cabecera. X-WEBAUTH-USER: admin y dentro.

Qué tienes que hacer hoy

Sin rodeos. Esto es lo que hemos revisado estos días en las máquinas de clientes que corren Gitea.

1. Comprobar tu versión

docker exec <nombre_contenedor_gitea> gitea --version

Si estás por debajo de 1.26.3, sigue leyendo.

2. Actualizar la imagen

Edita tu docker-compose.yml para fijar la versión parcheada (o 1-latest si prefieres seguir la rama 1.x) y recrea el contenedor:

# docker-compose.yml -> image: gitea/gitea:1.26.3
docker compose pull
docker compose up -d

Verifica después con el mismo gitea --version que ya estás en la 1.26.3 o superior.

3. Revisar tu configuración de proxy de confianza

Actualizar la imagen quita el default peligroso, pero comprueba que tu app.ini no lo haya fijado a * por tu cuenta. Busca en la sección [security]:

[security]
REVERSE_PROXY_TRUSTED_PROXIES = 127.0.0.1, 172.18.0.0/16   ; SOLO la IP/rango de tu proxy real

Si lo tenías como *, cámbialo por la IP concreta de tu proxy inverso. Si no usas autenticación por proxy, asegúrate de que ENABLE_REVERSE_PROXY_AUTHENTICATION está a false.

4. Blindaje en el proxy inverso (aunque ya hayas actualizado)

Este es el cinturón y tirantes que aplicamos siempre: que sea tu propio proxy quien borre o reescriba la cabecera en toda petición entrante, de modo que un cliente jamás pueda inyectarla. En nginx:

location / {
    # El cliente NO decide quién es: limpiamos la cabecera y la pone (si toca) el proxy
    proxy_set_header X-WEBAUTH-USER "";
    proxy_pass http://127.0.0.1:3000;
}

Si usas la autenticación por proxy de verdad, esa línea la sobreescribe tu módulo de auth con el usuario ya validado. Si no la usas, la dejas vacía y cierras el vector de raíz. Barato y definitivo.

5. Auditar accesos previos

Si tu Gitea estuvo expuesto con la config vulnerable, asume que pudo tocarse. Revisa:

  • El log de Gitea (gitea.log o la salida del contenedor) buscando logins por reverse-proxy de usuarios o IPs que no cuadran.
  • Acciones administrativas inesperadas: usuarios nuevos, tokens de acceso creados, claves SSH o deploy keys añadidas, webhooks nuevos.
  • Si encuentras algo raro, asume compromiso: rota tokens, claves de despliegue y secretos de CI/CD que vivieran en esos repos.

Lo que hacemos nosotros

En Atenea Systems, cuando montamos un Gitea (o cualquier servicio self-hosted detrás de proxy), partimos de dos reglas que habrían neutralizado este fallo antes de que existiera:

  1. Nada de comodines en listas de confianza. TRUSTED_PROXIES, allow, X-Forwarded-*… siempre con IPs o rangos concretos. El * es cómodo el día del despliegue y una bomba de relojería el resto del año.
  2. El proxy limpia las cabeceras sensibles en la entrada. El cliente no dicta identidad. Esa cabecera la pone quien tiene que ponerla, nunca quien llega de fuera.

Con esas dos costumbres, la imagen podía venir como viniera: el atacante que manda X-WEBAUTH-USER: admin se topa con un proxy que se la borra antes de que Gitea la vea.

La lección de siempre

Los defaults de una imagen no son tu configuración de seguridad. Un docker pull cómodo puede traerte un comodín que no pusiste tú y que te deja la puerta abierta. Merece la pena, al montar cualquier servicio, dedicar diez minutos a leer qué trae por defecto en materia de confianza y autenticación —especialmente cabeceras y proxies.

Si tienes un Gitea (u otro self-hosted) montado hace tiempo y no recuerdas la última vez que revisaste su config, es justo el momento. Si quieres que le echemos un ojo nosotros, hablamos.

Referencias

¿Hablamos de tu caso?

Cuéntanos qué necesitas y te respondemos en menos de 24 horas con una propuesta clara.

Pedir presupuesto