
Informe de CVE-2026-22874: lista de permitidos SSRF incompleta en webhook/migración de Gitea (transición IPv6 y metadatos en la nube). Corregido en Gitea 1.26.3.
Informe técnico y referencias para CVE-2026-22874 (GHSA-2r5c-gw76-rh3w): una lista de permitidos SSRF incompleta en la entrega de webhooks y la migración de repositorios de Gitea, corregida en Gitea 1.26.3.
Informé de forma independiente esta clase de SSRF a los mantenedores de Gitea y se me acredita como colaborador (other) en el aviso publicado; el reportero principal del aviso es J. Leitschuh. Este repositorio es un informe defensivo y educativo del aviso público: el problema está solucionado.
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N)<= 1.26.2 — Corregido: 1.26.3La lista de permitidos SSRF predeterminada de Gitea (, utilizada tanto para la entrega de webhooks como para las migraciones de repositorios) se basaba en de la biblioteca estándar de Go, que solo reconoce RFC 1918 (, , ) y RFC 4193 (). Varios rangos de direcciones comúnmente utilizados para servicios de metadatos en la nube, redes internas y mecanismos de transición IPv6 no son "privados" según esa definición y, por lo tanto, pasaron el filtro "externo", permitiendo que un usuario autenticado hiciera que el servidor emitiera solicitudes HTTP a esos destinos.
MatchBuiltinExternalnet.IP.IsPrivate()10/8172.16/12192.168/16fc00::/7Debido a que la entrega de webhooks registra el estado de la respuesta, los encabezados y hasta ~1 MiB del cuerpo y lo muestra en la interfaz de usuario del historial de webhooks, el SSRF no es ciego: el atacante puede leer lo que devuelve el servicio interno objetivo.
net.IP.IsPrivate()| Rango | Significado |
|---|---|
100.64.0.0/10 | RFC 6598 NAT de operador |
168.63.129.16/32 | Azure WireServer / punto final de metadatos de instancia |
64:ff9b::/96 | RFC 6052 NAT64 (puede incrustar 169.254.169.254, p. ej., AWS IMDS) |
2001::/32 | RFC 4380 Teredo |
2002::/16 | RFC 3056 6to4 |
Las formas IPv4-mapeadas IPv6 de lo anterior se ven afectadas de la misma manera.
Por lo tanto, un usuario autenticado que pueda crear o modificar un webhook (o iniciar una migración) puede alcanzar puntos finales de metadatos en la nube — por ejemplo, AWS IMDS a través de una asignación NAT64, o Azure WireServer en 168.63.129.16 — y servicios solo internos, y luego leer la respuesta a través de la vista del historial de webhooks.
La política predeterminada es MatchBuiltinExternal en la comprobación HostMatchList de Gitea, que permitía cualquier dirección global-unicast no IsPrivate():
case MatchBuiltinExternal:
if ip.IsGlobalUnicast() && !ip.IsPrivate() {
return true
}
net.IP.IsPrivate() no es un límite de seguridad para "externo": no tiene en cuenta el NAT de operador, los puntos finales de metadatos en la nube ni los rangos de transición IPv6 que pueden enrutarse a destinos internos o de metadatos.
Corregido en Gitea 1.26.3 ampliando el filtro integrado para bloquear los rangos adicionales anteriores. Los operadores deben actualizar a 1.26.3 o posterior. Como defensa en profundidad: