Recursos · CVE-2026-60004, Gitea, Perímetro externo, Descubrimiento de activos
Gitea autoalojado en el perímetro: comprobar si un viejo host de código se convirtió en punto de entrada
CVE-2026-60004 está en el catálogo KEV de CISA y Gitea publicó un aviso. La comprobación externa es concreta: encontrar las instancias de Gitea que responden desde internet, establecer sus versiones reales y compararlas con los rangos afectados.
CISA incorporó CVE-2026-60004 a su catálogo de Vulnerabilidades Explotadas Conocidas (KEV) y Gitea publicó el aviso GHSA-rcr6-4jqh-j84m. Para el perímetro externo la tarea que se desprende es concreta: encontrar las instancias de Gitea accesibles desde internet, establecer sus versiones reales y compararlas con los rangos indicados en el aviso.
La entrada de CVE-2026-60004 en el catálogo KEV cambia la prioridad del trabajo. Ya no se trata de «actualizar en algún momento el viejo servidor de Git», sino de una comprobación específica de un activo externo frente a una lista de versiones afectadas. No reprodujimos la explotación ni vamos a deducir un método de ataque a partir de un solo identificador de CVE. Para decidir sobre un host concreto bastan dos hechos confirmados: Gitea responde desde fuera y la versión instalada entra en el rango de versiones afectadas del aviso.
Por qué no funciona buscar en la lista corporativa de repositorios
La pregunta habitual a quien lleva el desarrollo suena así: «¿dónde está nuestro Git?». Las respuestas mencionan el GitHub o el GitLab corporativos y, a veces, un Gitea vigente. Eso es una lista de plataformas en uso, no una lista de activos externos.
Un Gitea autoalojado hay que buscarlo de forma más amplia. Puede haber quedado en un subdominio antiguo o en una IP de la nube después de que cambiara el proceso de desarrollo. Una instancia aparte pudo pertenecer a un equipo que ya no mantiene proyectos allí. Por eso, la ausencia de Gitea en el esquema actual de desarrollo no dice nada sobre un registro DNS, una dirección pública y un proceso en ejecución.
En la práctica se ve así: el servicio conocido ya está migrado, mientras que el host antiguo no participa ni en las copias de seguridad, ni en la actualización, ni en el inventario habitual. Y, sin embargo, el activo externo sigue respondiendo. Revisar solo la lista acordada de servidores lo dejará fuera por definición, porque los sistemas olvidados son justamente lo que esa lista no contiene.
La comprobación debe empezar, entonces, por los activos externos de la organización y no por el nombre de la plataforma aprobada. Primero se reúnen dominios, subdominios y direcciones IP públicas; después se identifican los candidatos a Gitea entre los servicios que responden. Solo tras confirmar el producto tiene sentido pasar a la versión y al CVE. El orden inverso, buscar el CVE únicamente en servidores ya conocidos, mantiene el punto ciego.
Qué es exactamente lo que hay que descubrir
En la primera pasada no buscamos «un Gitea vulnerable». Buscamos un host de código externo que necesita un responsable y una comprobación de versión. Esa distinción importa.
Que una URL responda no confirma el producto. El título de la página, el código de estado HTTP y las cabeceras genéricas tampoco deben convertirse en la única prueba: no permiten decidir de forma fiable sobre la versión afectada. El escaneo externo aporta un candidato, y ese candidato hay que vincularlo después con un despliegue: una máquina virtual, un contenedor, un clúster u otro objeto gestionado.
Para cada candidato llevamos una ficha breve:
- la URL externa;
- los resultados de la resolución A, AAAA y CNAME;
- la dirección IP pública;
- el producto confirmado;
- la versión real, o el identificador del artefacto desplegado;
- el responsable;
- la fuente desde la que se aplicará la actualización;
- la correspondencia con los rangos de GHSA-rcr6-4jqh-j84m;
- el estado de accesibilidad externa después de la corrección.
«Responsable desconocido» y «versión desconocida» no son motivo para cerrar un hallazgo. Describen una comprobación inconclusa. Para CVE-2026-60004, la prioridad no puede asignarse por la antigüedad de un subdominio ni por el aspecto de la interfaz: hay que establecer la versión y compararla con el aviso original.
Dónde aparecen las instancias autónomas
Empezamos por las zonas que la organización posee ahora o poseyó antes. Eso implica revisar más allá de los nombres obvios relacionados con Git. El conjunto inicial debe incluir dominios antiguos, subdominios que siguen vivos, direcciones públicas de recursos en la nube y direcciones cedidas a equipos de desarrollo concretos.
Para un nombre ya conocido, la comprobación básica se ve así:
host=gitea.old.example.com
dig +short A "$host"
dig +short AAAA "$host"
dig +short CNAME "$host"
curl -kI --connect-timeout 5 "https://$host/"
Aquí curl comprueba la accesibilidad HTTP(S) y nada más. No usamos las cabeceras que devuelve como prueba de que estamos ante Gitea. Si responde un proxy intermedio, una sola respuesta externa no establece ni el producto que hay detrás ni su versión.
Para una IP pública hacemos la misma comprobación de transporte, pero no tomamos la ausencia de una respuesta adecuada en esa dirección como prueba de que el servicio no existe. Un host virtual puede requerir un nombre concreto. Por eso hay que conservar el vínculo entre dominio y dirección IP, en lugar de revisar ambas listas por separado.
Aparte, cotejamos los candidatos con la configuración de los proxies y balanceadores externos. El objetivo es llegar desde el nombre público hasta el despliegue que lo atiende. Mientras ese vínculo no exista, tenemos una dirección externa descubierta pero ninguna versión confirmada.
No confundir el descubrimiento con la verificación del CVE
Este trabajo tiene cuatro resultados distintos:
- Se ha encontrado una URL o una dirección IP externa.
- Se ha confirmado que detrás funciona Gitea.
- Se ha establecido la versión exacta del despliegue.
- Se ha comparado la versión con las versiones afectadas de GHSA-rcr6-4jqh-j84m.
Saltar del primer punto directamente al cuarto no funciona. La sola presencia de Gitea no demuestra que CVE-2026-60004 le afecte. Y la ausencia de la versión en la respuesta externa tampoco demuestra lo contrario.
La versión conviene tomarla del lado del despliegue. Si Gitea se ejecuta en un contenedor, primero registramos la imagen:
docker inspect --format '{{.Config.Image}}' <container>
Para un despliegue en Kubernetes, revisamos las imágenes en uso:
kubectl -n <namespace> get deploy <deployment> \
-o jsonpath='{..image}{"\n"}'
Para un servicio en una máquina virtual, miramos la configuración real de arranque:
systemctl cat gitea
Estos comandos no sustituyen la confirmación de la versión. La etiqueta de la imagen puede no contenerla, y la configuración del servicio puede indicar solo la ruta del ejecutable. En ese caso la comprobación continúa sobre el propio artefacto y los datos del despliegue. «Parece una versión antigua» no sirve para tomar una decisión.
Después abrimos el aviso de Gitea y comparamos la versión instalada con los rangos que allí figuran. Los números no deben arrastrarse desde una tarea antigua, un hilo de correo o una captura de pantalla: la fuente de trabajo es el texto actual del aviso.
Por qué aquí importa priorizar por explotabilidad
Una lista de instancias externas de Gitea puede contener despliegues afectados y no afectados. Ordenar simplemente por «el servicio es accesible desde internet» no responde a qué host revisar primero.
CVE-2026-60004 está presente en el catálogo KEV. Es una señal de prioridad independiente, y se aplica después de establecer la versión, no en su lugar. La cadena se ve así:
activo externo
-> Gitea confirmado
-> versión instalada
-> la versión cae dentro de un rango de GHSA-rcr6-4jqh-j84m
-> CVE-2026-60004 figura en el KEV
Es el último par de condiciones lo que separa una comprobación urgente concreta de una lista general de servicios obsoletos. Si la versión no entra en el rango del aviso, la presencia del CVE en el KEV no convierte a esa instancia en afectada. Si la versión se desconoce, el resultado queda incompleto.
El registro de CISA puede extraerse del JSON publicado sin buscar a mano en todo el archivo:
curl -fsSL \
https://www.cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json |
jq '.vulnerabilities[] | select(.cveID == "CVE-2026-60004")'
Guardamos los campos del registro junto con la tarea, incluidas la acción requerida y la fecha límite del catálogo. Así no se parafrasea el KEV ni se sustituye la fuente original por una redacción interna.
Dónde termina la comprobación externa
El escaneo externo responde si un activo es accesible y si puede vincularse con un servicio concreto. No siempre muestra la versión instalada y no confirma que la corrección se haya aplicado dentro del sistema.
Por eso el hallazgo debe llegar al responsable del despliegue con un conjunto preciso de datos: URL, dirección IP, hora de la comprobación, confirmación del producto y motivo de la prioridad. La respuesta «eso ya no lo usamos» no cierra un activo externo. Lo cierra o bien la retirada confirmada de la accesibilidad externa, o bien la comprobación de la versión junto con la acción que exige el aviso.
Tras el cambio repetimos la comprobación desde fuera. Si se decidió retirar el servicio, la URL y la IP no deberían quedar en estado de «presuntamente apagado». Si el despliegue se conservó, hay que establecer de nuevo la versión real y volver a compararla con el aviso. No damos un activo por corregido solo porque el ticket esté cerrado.
Una comprobación que puede hacer hoy
Tome la lista de plataformas Git corporativas y déjela a un lado por un momento. Reúna por separado los dominios antiguos, los subdominios activos y las IP públicas en la nube asociadas a equipos de desarrollo. Para cada dirección que responda, confirme el producto, localice el despliegue que la atiende y registre la versión exacta.
Después abra GHSA-rcr6-4jqh-j84m, compare las versiones encontradas con las versiones afectadas y revise CVE-2026-60004 por separado en el JSON del catálogo KEV. El resultado no debería ser una lista de URL, sino una tabla con una fila por activo y estas columnas: activo, responsable, versión, correspondencia con el aviso, accesibilidad externa, acción.
Una comprobación así no puede quedarse en algo puntual. Una pasada única confirma el estado solo en el momento en que se ejecutó, y un Gitea olvidado aparece en el radar precisamente porque quedó fuera del proceso actual. El descubrimiento continuo de activos externos devuelve esos hosts al inventario, que es para lo que está hecho SeguriScan, la plataforma de IntruForce, y la priorización basada en el KEV dirige la verificación manual hacia las versiones afectadas por CVE-2026-60004. Hoy basta con empezar por un dominio antiguo y una lista de IP en la nube, y no cerrar el trabajo hasta que cada Gitea encontrado tenga un responsable y una versión confirmada.