CVE-2026-103956 - Loom pour AWS - Critique - Contournement d'authentification - super-admin non authentifié lorsqu'aucun IdP n'est configuré
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · cve-2026-103956-loom-unauth
Loom for AWS < 1.6.1 - AWS Labs
Lorsque Cognito n'est pas configuré et qu'aucun IdP externe n'est actif, get_current_user attribue à chaque requête t-admin / g-admins-super. Cela inclut les requêtes sans en-tête Authorization. Un déploiement frais avant la configuration de l'IdP constitue un panneau d'administration ouvert.
| ID | CVE-2026-103956 |
| CWE | CWE-306 / CWE-1188 |
| CVSS | Critique : 10.0 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H |
| Produit | Loom for AWS |
| Affecté | < 1.6.1. Version du labo v1.6.0 (8c658d61). Corrigé dans v1.6.1 (ccad5665). |
| Auth | non authentifié |
| Licence | GNU Affero GPL v3.0 |
| Labo | 127.0.0.1 uniquement |
L'attaquant contrôle le plan de contrôle de l'agent sans aucun identifiant.
GET /api/auth/me sans en-tête renvoie username=local-dev, sub=local, groupes t-admin et g-admins-super. Toutes les portées de GROUP_SCOPES accompagnent cette identité.POST /api/mcp/servers non authentifié renvoie 201. MCP, A2A, agents, mémoires, sécurité, paramètres, identifiants et audit d'administration reposent sur la même dépendance.GET /api/mcp/servers/{id}/export est admin:write. Sur cette version, il renvoie oauth2_client_secret depuis SQLite. Le texte du CVE mentionne également la réécriture de politiques de rôles IAM sur les rôles d'agents gérés ; ce chemin nécessite AWS et sort du cadre de ce labo en loopback.v1.6.1 exige LOOM_ALLOW_UNAUTHENTICATED_LOCAL_DEV ainsi qu'un client loopback. La même requête renvoie 401 (No identity provider configured).
AWS a publié CVE-2026-103956 avec GHSA-vgmj-998f-r8mp et le bulletin 2026-124-AWS. J'ai épinglé awslabs/loom v1.6.0 (8c658d61) à côté de v1.6.1 (ccad5665) et exécuté le backend sur SQLite avec LOOM_COGNITO_USER_POOL_ID non défini.
backend/app/dependencies/auth.py get_current_user vérifie les variables d'environnement Cognito et une ligne IdP active. Les deux vides : il renvoie UserInfo(sub="local", username="local-dev", groups=["t-admin", "g-admins-super"], scopes=ALL_SCOPES). Le jeton n'est jamais lu.
J'ai déployé un FastAPI standard sur le loopback 127.0.0.1:18180 (v1.6.0) et 18181 (v1.6.1). Pas de frontend. Pas d'AWS. GET /api/auth/me non authentifié sur 1.6.0 a renvoyé 200 avec ces groupes. POST /api/mcp/servers non authentifié avec oauth2_client_secret=CVE-2026-103956-WITNESS a renvoyé 201. GET /api/mcp/servers/1/export a restitué le secret. Sur 1.6.1, le même /api/auth/me a renvoyé 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
Fausses pistes déjà consignées : public.ecr.aws/docker/library/python:3.13-slim a été écarté au profit de Docker Hub python:3.13-slim ; le premier /health sur v1.6.0 a renvoyé curl 52 pendant qu'uvicorn était lié, puis 200 ; le schéma de création MCP a correspondu dès le premier POST, aucun nouvel essai sur 422. Un reverse shell. Du théâtre. L'oracle est /api/auth/me plus le secret exporté.
cd lab
./run.sh
Cible uniquement http://127.0.0.1:18180 (v1.6.0) et http://127.0.0.1:18181 (v1.6.1). run.sh clone superficiellement ces tags, construit les deux backends, puis démonte la pile. SQLite. Aucune variable d'environnement Cognito. Pas de LOOM_ALLOW_UNAUTHENTICATED_LOCAL_DEV sur le service corrigé.
Mettre à niveau vers 1.6.1 ou une version ultérieure. AWS recommande 1.7.0 pour les problèmes SSRF/jeton associés. Le contournement de la 1.6.1 est opt-in et limité au loopback. En attendant, terminez la configuration de Cognito ou d'un IdP externe avant que le backend ne soit accessible au-delà du loopback, et laissez LOOM_ALLOW_UNAUTHENTICATED_LOCAL_DEV non défini sur tout déploiement.
backend/app/dependencies/auth.py (get_current_user)