CVE-2026-31431 (Copy Fail) : comment Appbox l'a atténuée
Une faille sérieuse du noyau Linux, CVE-2026-31431, a été divulguée la semaine dernière. Voici comment Appbox l'a atténuée et a déployé le correctif du noyau Debian.
CVE-2026-31431 (Copy Fail) - Comment nous l'avons atténuée
La semaine dernière, une élévation locale de privilèges sérieuse dans le noyau Linux a été divulguée : CVE-2026-31431, surnommée "Copy Fail". Elle affecte un large éventail de versions du noyau dans les distributions Linux modernes, et un exploit public est apparu rapidement après la divulgation.
Je veux être transparent sur ce qui s'est passé, ce que cela signifie pour Appbox et ce que nous avons fait. Version courte : grâce à la manière dont nos conteneurs sont construits, les apps exécutées avec le remappage des namespaces utilisateur étaient déjà protégées contre une transformation en root hôte, même avant le déploiement des noyaux corrigés. Hier (4 mai 2026), nous avons également effectué une maintenance d'urgence pour mettre à niveau chaque serveur vers un noyau corrigé, donc le bug a maintenant totalement disparu de notre flotte.
Qu'est-ce que "Copy Fail" ?
CVE-2026-31431 est une faille dans l'API cryptographique AF_ALG du noyau. En se liant à un chiffrement précis (authencesn(hmac(sha256),cbc(aes))) et en abusant de la manière dont le noyau épisse des pages dans un tampon temporaire, un utilisateur local non privilégié peut écrire des blocs arbitraires de 4 octets directement dans le cache de pages de fichiers qu'il ne devrait pas avoir le droit de modifier, y compris des binaires SUID comme /usr/bin/su.
Une fois la copie de su dans le cache de pages remplacée par un petit ELF malveillant, le prochain lancement exécute le code de l'attaquant avec l'UID 0. Fin de partie pour l'hôte.
Pour les détails techniques les plus pointus (désassemblage du shellcode, traces syscall, tout le reste), l'analyse d'Andrea Veri est excellente : CVE-2026-31431: Copy Fail vs. rootless containers. Il a aussi démontré, avec eBPF et des preuves uid_map, exactement ce dont nous allons parler ensuite : les namespaces utilisateur neutralisent cet exploit.
Pourquoi les apps Appbox étaient déjà protégées
L'exploit repose sur le fait que setuid(0) donne réellement root sur l'hôte. Dans un conteneur exécuté avec les namespaces utilisateur activés, ce n'est pas ce qui se produit.
Les namespaces utilisateur mappent l'espace UID du conteneur vers une plage d'UID différente (non privilégiée) sur l'hôte. Ainsi, lorsque l'exploit réussit dans le conteneur et que setuid(0) renvoie un succès, le shell "root" obtenu est mappé vers un utilisateur hôte ordinaire non privilégié, pas vers le vrai root. Le shellcode s'exécute, l'invite devient #, mais sur l'hôte :
podman 27943 0.0 0.0 2984 2028 pts/1 S+ 22:15 0:00 sleep 100
C'est tout. Pas d'accès aux fichiers de l'hôte, pas de /etc/shadow, pas de root hôte. La frontière du namespace du conteneur empêche cela de devenir une évasion vers root sur l'hôte.
Au niveau de la plateforme, chaque Appbox dispose de son propre daemon Docker démarré avec le remappage des namespaces utilisateur activé. En pseudocode, cela ressemble plutôt à ceci :
start_docker_daemon(
userns_remap = appbox_id,
container_namespace = appbox_id
)Ce mapping s'appuie sur une plage UID/GID subordonnée dédiée sur l'hôte :
write "/etc/subuid" -> "<appbox-id>:<host-subuid-start>:65536"
write "/etc/subgid" -> "<appbox-id>:<host-subgid-start>:65536"En plus de cela, les définitions d'app peuvent toujours remplacer explicitement UsernsMode lorsqu'une app nécessite un traitement particulier :
container_config = {
userns_mode: app.userns_mode,
network_mode: app.network_mode,
...
}La manière exacte de le décrire est donc : le remappage des namespaces utilisateur fait partie du comportement par défaut de la plateforme, et les exceptions par app sont explicites. Un petit nombre d'apps ont besoin de paramètres différents parce qu'elles exposent des fonctionnalités nécessitant des capacités supplémentaires, et ces cas sont traités séparément.
En d'autres termes : pour les apps exécutées avec la configuration remappée normale, Copy Fail ne pouvait pas transformer une compromission de conteneur en root hôte.
Ce que nous voulions quand même corriger
Les namespaces utilisateur empêchent l'évasion vers l'hôte, mais ils ne font pas disparaître le bug à l'intérieur du conteneur. Un attaquant pouvait encore élever ses privilèges en "root conteneur" dans la frontière de l'app, ce qui, même contenu, reste une mauvaise situation. Le noyau lui-même était vulnérable, et nous voulions que cela disparaisse.
Dès que nous avons appris l'existence du bug, nous avons immédiatement commencé à évaluer notre exposition. Même si le remappage des namespaces utilisateur bloquait déjà le côté évasion hôte du problème pour notre configuration d'app normale, nous voulions supprimer le bug noyau sous-jacent aussi vite que possible.
Ce que nous avons fait hier
Dimanche soir, nous avons planifié une maintenance d'urgence pour le lundi 4 mai 2026, la première fenêtre pendant laquelle nous pouvions déployer une mise à niveau du noyau sur toute la flotte.
Pendant cette fenêtre :
- Chaque hôte a été mis à niveau avec les paquets officiels du noyau Debian contenant le correctif "Copy Fail".
- L'objectif était simple : supprimer entièrement le chemin vulnérable du noyau, pas seulement compter sur notre isolation existante par namespaces.
La maintenance est terminée. Chaque hôte Appbox exécute maintenant un noyau corrigé.
Ce que cela signifie pour vous
- Vous n'aviez rien à faire. Vos apps ont continué à fonctionner et les éventuels brefs accrocs pendant la fenêtre de maintenance ont été le seul effet visible côté client.
- Même avant le correctif d'hier, le remappage des namespaces utilisateur signifiait que ce bug ne pouvait pas transformer une compromission d'app normale en root hôte. C'est exactement le type de scénario pour lequel ce modèle d'isolation existe.
- À l'avenir, notre politique ne change pas : les namespaces utilisateur restent activés par défaut, et les très rares exceptions passent par une revue de sécurité supplémentaire.
Le tableau d'ensemble
C'est l'une de ces CVE où le titre ("élévation locale de privilèges, exploit public, tous les noyaux modernes affectés") semble catastrophique, et pour beaucoup d'environnements multi-tenant partagés, elle l'était vraiment. La raison pour laquelle elle ne l'a pas été pour nous est la même que celle qui nous a poussés il y a des années à prendre des décisions d'architecture qui coûtent parfois un peu en compatibilité : nous exécutons les apps avec le principe du moindre privilège intégré à la couche conteneur, pas ajouté après coup.
La défense en profondeur fonctionne vraiment. Bug dans la couche noyau ? La couche namespace l'a intercepté. Bug dans la couche namespace ? Les suppressions de capacités et seccomp arrêtent la plupart du reste. Nous ne prétendons pas qu'une couche unique est parfaite ; nous nous assurons simplement qu'il y en a toujours une suivante.
Si vous avez des questions à ce sujet, ou sur la configuration de vos apps spécifiques, contactez-nous.
Des questions ? Contactez-nous à support@appbox.co ou ouvrez un ticket sur billing.appbox.co.
