CVE-2026-103956 - Loom para AWS - Crítico - Omisión de autenticación - superadministrador no autenticado cuando no hay un IdP configurado
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cve-2026-103956-loom-unauth
Loom for AWS < 1.6.1 - AWS Labs
Cuando Cognito no está configurado y no hay un IdP externo activo, get_current_user entrega a cada solicitud t-admin / g-admins-super. Eso incluye solicitudes sin encabezado Authorization. Un despliegue reciente antes de configurar el IdP es un panel de administración abierto.
| ID | CVE-2026-103956 |
| CWE | CWE-306 / CWE-1188 |
| CVSS | Crítico: 10.0 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H |
| Producto | Loom for AWS |
| Afectado | < 1.6.1. Pin del laboratorio v1.6.0 (8c658d61). Corregido en v1.6.1 (ccad5665). |
| Autenticación | no autenticado |
| Licencia | GNU Affero GPL v3.0 |
| Laboratorio | solo 127.0.0.1 |
El atacante controla el plano de control del agente sin credenciales.
GET /api/auth/me sin encabezado devuelve username=local-dev, sub=local, grupos t-admin y g-admins-super. Todos los ámbitos en GROUP_SCOPES vienen con esa identidad.POST /api/mcp/servers sin autenticación devuelve 201. MCP, A2A, agentes, memorias, seguridad, configuración, credenciales y auditoría de administración están detrás de la misma dependencia.GET /api/mcp/servers/{id}/export es admin:write. En este pin devuelve oauth2_client_secret desde SQLite. El texto del CVE también menciona la reescritura de políticas de roles IAM en roles de agentes gestionados; esa ruta requiere AWS y queda fuera de este laboratorio de loopback.v1.6.1 requiere LOOM_ALLOW_UNAUTHENTICATED_LOCAL_DEV más un cliente de loopback. La misma solicitud devuelve 401 (No identity provider configured).
AWS publicó CVE-2026-103956 con GHSA-vgmj-998f-r8mp y el boletín 2026-124-AWS. Fijé awslabs/loom v1.6.0 (8c658d61) junto a v1.6.1 (ccad5665) y ejecuté el backend sobre SQLite con LOOM_COGNITO_USER_POOL_ID sin definir.
backend/app/dependencies/auth.py get_current_user verifica las variables de entorno de Cognito y una fila de IdP activo. Ambas vacías: devuelve UserInfo(sub="local", username="local-dev", groups=["t-admin", "g-admins-super"], scopes=ALL_SCOPES). El token nunca se lee.
Levanté FastAPI estándar en loopback 127.0.0.1:18180 (v1.6.0) y 18181 (v1.6.1). Sin frontend. Sin AWS. GET /api/auth/me sin autenticación en 1.6.0 devolvió 200 con esos grupos. POST /api/mcp/servers sin autenticación con oauth2_client_secret=CVE-2026-103956-WITNESS devolvió 201. GET /api/mcp/servers/1/export devolvió el secreto. En 1.6.1 el mismo /api/auth/me devolvió 401.
SUCCESS CVE-2026-103956 me-http=200 me-user=local-dev me-sub=local me-groups=t-admin,g-admins-super mcp-create=201 export-has-secret=yes list-has-witness=yes patched-me-http=401 CVE-2026-103956-WITNESS
Errores ya registrados: se omitió public.ecr.aws/docker/library/python:3.13-slim en favor de Docker Hub python:3.13-slim; el primer /health en v1.6.0 fue curl 52 mientras uvicorn estaba enlazado, luego 200; el esquema de creación de MCP coincidió en el primer POST, sin reintento 422. Una reverse shell. Teatro. El oráculo es /api/auth/me más el secreto exportado.
cd lab
./run.sh
Objetivo solo http://127.0.0.1:18180 (v1.6.0) y http://127.0.0.1:18181 (v1.6.1). run.sh clona superficialmente esas etiquetas, compila ambos backends y luego desmonta la pila. SQLite. Sin variables de entorno de Cognito. Sin LOOM_ALLOW_UNAUTHENTICATED_LOCAL_DEV en el servicio parcheado.
Actualiza a 1.6.1 o posterior. AWS recomienda 1.7.0 para los problemas hermanos de SSRF/token. El bypass de 1.6.1 es opcional y solo para loopback. Hasta entonces, completa Cognito o un IdP externo antes de que el backend sea alcanzable más allá del loopback, y mantén LOOM_ALLOW_UNAUTHENTICATED_LOCAL_DEV sin definir en cualquier cosa desplegada.
backend/app/dependencies/auth.py (get_current_user)