# Incidente: el ingress del túnel rompió específicamente a Cosign, no al resto del pipeline (2026-08) | | | |---|---| | **Ventana del incidente** | 2026-08-15, primer intento de firmar una imagen con Cosign en `build.yaml` | | **Servicio afectado** | Cadena Cloudflare Tunnel → NPM (Nginx Proxy Manager) → Gitea, específicamente el endpoint del registry de contenedores | | **Impacto** | `cosign sign` fallaba siempre, en cada intento — el resto del pipeline (Gitleaks, Trivy, Semgrep, build, push de la imagen) funcionaba normal contra el mismo registry | ## Síntoma Todos los pasos anteriores del pipeline pasaban, incluido `docker push` de la imagen al registry de Gitea. El paso de Cosign, inmediatamente después, fallaba siempre con: ```text Error: signing [gitea.cruzcloud.net/***/ecommerce-frontend:v1.0.102]: accessing entity: invalid realm in www-authenticate: realm scheme "http" not allowed for a secure registry; use https ``` Lo llamativo: **`docker push` a ese mismo registry, un paso antes, funcionaba sin problema.** Si el registry estuviera mal configurado en general, se esperaría que fallara también el push, no solo la firma. ## Diagnóstico El mensaje da la pista exacta: al autenticar contra el registry, Cosign recibe un header `WWW-Authenticate` cuyo campo `realm` apunta a una URL con esquema `http://` en vez de `https://`. Cosign rechaza explícitamente seguir un realm `http` contra lo que él considera "un registry seguro" (un dominio público, no `localhost`) — es una protección intencional del lado de Cosign, no un bug. `docker push`/`docker login` son más permisivos con esto (o cachean la sesión de otra forma) y no chocan con el mismo problema, por eso solo Cosign lo mostraba. ## Causa raíz El realm que arma Gitea en su respuesta `WWW-Authenticate` depende de que Gitea sepa correctamente que la petición le llegó por HTTPS (típicamente vía el header `X-Forwarded-Proto` o el Server Name que ve en la conexión TLS que termina antes de llegar a él). La cadena real acá es **Cloudflare Tunnel → NPM → Gitea** — si el proxy host de NPM para `gitea.cruzcloud.net` no tiene el *Origin Server Name* (SNI hacia el origen) configurado correctamente, Gitea puede terminar creyendo que la conexión entrante fue por HTTP plano, y arma el realm con ese esquema equivocado. ## Fix aplicado Corrección de la regla de ingress de `cloudflared`/NPM para `gitea.cruzcloud.net`: HTTPS hacia el origen con el *Origin Server Name* correcto. El fix fue enteramente de infraestructura — no hubo ningún cambio en este repo más allá de un commit vacío para volver a disparar el pipeline y confirmar el fix contra credenciales reales. ## La misma causa raíz de fondo, dos síntomas distintos Este incidente **no es el mismo bug** que el [504 Gateway Timeout intermitente del túnel](incidente-504-gitea-tunnel.md) ya documentado — ese fue inestabilidad de QUIC/UDP en `cloudflared`, resuelto forzando `TUNNEL_TRANSPORT_PROTOCOL=http2`. Pero **ambos viven en la misma capa**: la cadena de ingress Cloudflare Tunnel → NPM → Gitea, mal configurada de dos formas distintas, descubiertas en momentos distintos: - Una regla de **transporte** (QUIC vs HTTP/2) causando 504s intermitentes en *cualquier* petición HTTP a los dominios detrás del túnel. - Una regla de **SNI/origin server name** causando que Gitea generara un realm HTTP incorrecto, rompiendo específicamente a un cliente (Cosign) que valida ese detalle de forma estricta. La lección compartida: en una cadena de proxies con TLS terminando en varios saltos, un solo campo de configuración mal puesto en cualquiera de los saltos puede manifestarse como fallas completamente distintas según qué tan estricto sea el cliente al otro lado — la mayoría de las herramientas HTTP normales ni lo notan, pero una herramienta de seguridad como Cosign, que valida explícitamente el esquema del realm, sí. ## Validación Confirmado en una corrida real posterior al fix: `cosign sign` y `cosign verify` completaron sin error contra el registry real, con credenciales reales, de punta a punta. !!! note "Nota relacionada, no parte de este incidente" El mismo log de este fallo mostró, además del error de realm, el warning esperado de Cosign sobre firmar por tag en vez de por digest — ver [limitaciones conocidas de Cosign](../devsecops/cosign.md#limitaciones-conocidas-y-mejoras-futuras).