Script de détection pour CVE-2026-31431 (Copy Fail) qui vérifie la version du noyau, la présence de correctifs, les configurations du noyau, la disponibilité des sockets AF_ALG, les binaires setuid et les mesures d'atténuation afin de déterminer le statut de vulnérabilité sur les systèmes Linux.
Détection uniquement. Un PoC fonctionnel existe déjà sur copy.fail/#exploit. Ce script est destiné aux administrateurs système et aux équipes de sécurité pour déterminer où ils sont vulnérables — ou encore vulnérables après l'application des correctifs.
Le 29 avril 2026, une vulnérabilité appelée Copy Fail (CVE-2026-31431) a été divulguée publiquement par l'équipe Xint Code Research. Il s'agit d'un bug logique présent discrètement dans le noyau Linux depuis environ 2017 — près d'une décennie — qui permet à tout utilisateur local non privilégié d'obtenir les droits root.
Pas « obtenir root dans des conditions spécifiques avec un peu de chance et un bon vent arrière ». Juste... obtenir root. De manière fiable. Sur pratiquement toutes les principales distributions Linux.
Elle affecte Ubuntu, Amazon Linux, RHEL, SUSE, et tout autre système exécutant un noyau grand public des ~8 dernières années. Même script, pas de recompilation, pas d'ajustements par distribution nécessaires.
Oui, c'est aussi grave que ça en a l'air.
Le noyau Linux dispose d'un sous-système cryptographique accessible aux utilisateurs non privilégiés via les sockets AF_ALG. Il existe un mécanisme appelé splice() qui peut alimenter directement ce sous-système avec des données de fichiers sans les copier — ce qui signifie que la copie en cache mémoire du noyau d'un fichier (le « page cache ») se retrouve à l'intérieur d'une opération cryptographique.
Un algorithme spécifique — authencesn, utilisé pour les numéros de séquence étendus IPsec — présente une particularité : il utilise le tampon de sortie comme espace de travail et écrit 4 octets légèrement au-delà de l'endroit prévu. Normalement inoffensif. Mais lorsque des pages du page cache d'un binaire setuid comme /usr/bin/su se retrouvent chaînées dans ce tampon de sortie (grâce à une « optimisation » de 2017 dans algif_aead.c), ces 4 octets atterrissent directement dans la copie en cache du noyau du binaire.
L'opération échoue avec une erreur. Le noyau ne marque jamais cette page comme sale. Le fichier sur disque est intact. Les outils d'intégrité des fichiers qui vérifient les sommes de contrôle sur disque ne voient rien d'anormal.
Mais c'est le page cache qui est exécuté. Et su est setuid root.
L'analyse technique complète est disponible sur xint.io et vaut vraiment la peine d'être lue.
Sept issues de la version originale plus six nouvelles vérifications ajoutées pour combler les lacunes de détection :
| # | Vérification | Ce qu'elle recherche |
|---|---|---|
| 1 | Version du noyau | Ce noyau est-il dans la plage affectée (4.10–6.14) ? |
| 2 | Présence du correctif | Le commit de correction est-il réellement dans votre noyau en cours d'exécution ? |
| 3 | Module algif_aead | Le module vulnérable est-il chargé ou chargeable ? |
| 4 | CONFIG_CRYPTO_AUTHENC (nouveau) | CONFIG_CRYPTO_AUTHENC est-il intégré (=y) ou en module (=m) ? Cette seule option compile à la fois authenc et authencesn. Intégré signifie que la mitigation par blacklist modprobe ne fait rien. |
| 5 | CONFIG_CRYPTO_USER_API_AEAD (nouveau) | L'interface utilisateur AEAD AF_ALG est-elle même compilée ? Si non, tout le chemin d'exploitation est fermé à la compilation. |
| 6 | Socket AF_ALG | Un utilisateur non privilégié peut-il en ouvrir un maintenant ? |
| 7 | os.splice Python | Le chemin d'exploitation en Python pur est-il disponible ? |
| 8 | Binaires setuid | Liste étendue des cibles setuid-root lisibles présentes sur le système. |
| 9 | Mitigations | AppArmor, SELinux, seccomp — qu'est-ce qui est en place ? |
| 10 | Espaces de noms utilisateur (nouveau) | Les espaces de noms utilisateur non privilégiés sont-ils activés ? (Ne bloque pas Copy Fail directement, mais affecte la surface d'élévation de privilèges locale plus large.) |
| 11 | Transparent hugepages (nouveau) | Statut THP — peut affecter l'alignement du page cache et la fiabilité de l'exploitation. |
| 12 | Détection d'environnement (nouveau) | Contexte Docker/conteneur/VM — les conteneurs partagent le noyau hôte ; c'est l'hôte qui doit être corrigé. |
| 13 | Avertissement utilisateur root (nouveau) | Avertit si exécuté en tant que root, car plusieurs vérifications donnent des faux positifs pour root indépendamment des restrictions non privilégiées. |
Le script Bash couvre la même logique de détection principale mais omet trois éléments spécifiques à Python :
| # | Vérification | Notes |
|---|---|---|
| 1 | Version du noyau | |
| 2 | Présence du correctif | |
| 3 | Module algif_aead | |
| 4 | Socket AF_ALG | Utilise Python comme assistant si disponible ; sinon, déduction à partir de la configuration du noyau |
| 5 | Binaires setuid | Liste étendue, identique à la version Python |
| 6 | Mitigations | AppArmor, SELinux, seccomp |
| 7 | CONFIG_CRYPTO_AUTHENC | |
| 8 | Espaces de noms utilisateur | |
| 9 | Transparent hugepages | |
| 10 | Détection d'environnement |
Absents du script shell (par rapport à Python) :
| Vérification manquante | Raison |
|---|---|
| CONFIG_CRYPTO_USER_API_AEAD | Pas encore implémenté — prévu |
| Disponibilité de os.splice Python | Non applicable à un script shell |
| Avertissement utilisateur root | Pas encore implémenté — prévu |
Aucun des deux scripts ne corrigera ni n'exploitera quoi que ce soit. Ils vous disent la vérité sur votre système afin que vous puissiez agir en conséquence.
# Clonez ou téléchargez le script, puis :
python3 cve-2026-31431-detect.py
C'est tout. Rapport codé par couleurs avec un résumé à la fin.
Le script se termine avec un code non nul en cas de résultats vulnérables, ce qui le rend adapté à une utilisation en pipeline :
| Code | Signification |
|---|---|
0 | Aucune condition vulnérable trouvée |
1 | Une ou plusieurs conditions vulnérables trouvées |
# Exemple : faire échouer une étape CI si l'hôte est vulnérable
python3 cve-2026-31431-detect.py
rc=$?
if [ $rc -eq 1 ]; then
echo "VULNÉRABLE — bloquer le déploiement"
elif [ $rc -ne 0 ]; then
echo "ERREUR — le script n'a pas pu se terminer (code de sortie $rc)"
fi
CVE-2026-31431 'Copy Fail' — Détection de vulnérabilité
Corruption du page cache authencesn / élévation de privilèges locale
Exécution avec uid=1001, euid=1001
=== Version du noyau ===
[VULNÉRABLE] Version du noyau
Raison : Le noyau est dans la plage vulnérable (4.10 – 6.14)
Détail : Version : 6.12.0-124.45.1.el10_1 — le statut du correctif doit être confirmé
=== CONFIG_CRYPTO_AUTHENC (Configuration du noyau) ===
[VULNÉRABLE] CONFIG_CRYPTO_AUTHENC
Raison : Compilé en module (=m) : chargement automatique sur bind() AF_ALG ; la blacklist modprobe est la mitigation correcte
=== CONFIG_CRYPTO_USER_API_AEAD (Configuration du noyau) ===
[VULNÉRABLE] CONFIG_CRYPTO_USER_API_AEAD
Raison : L'interface AEAD AF_ALG est un module chargeable — les utilisateurs non privilégiés peuvent accéder au sous-système cryptographique via les sockets AF_ALG
...
LE SYSTÈME EST PROBABLEMENT VULNÉRABLE À CVE-2026-31431
Actions recommandées :
1. Appliquez la mise à jour du noyau de votre distribution pour CVE-2026-31431
2. En attendant le correctif, mettez le module en blacklist :
echo 'install algif_aead /bin/false' > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null
REMARQUE : cela n'est efficace que lorsque CONFIG_CRYPTO_AUTHENC=m (module).
Si CONFIG_CRYPTO_AUTHENC=y (intégré), le correctif est la seule solution.
Un script Bash compagnon (cve-2026-31431-detect.sh) est disponible pour les environnements où Python n'est pas présent ou où les outils natifs shell sont préférés. Il effectue 10 des 13 vérifications — voir le tableau de comparaison des vérifications ci-dessus pour les détails des différences.
# Exécution de base
bash cve-2026-31431-detect.sh
# Sortie JSON — adaptée à l'ingestion SIEM, aux faits Ansible, à l'agrégation de journaux
bash cve-2026-31431-detect.sh --json > scan-results.json
# Mode silencieux — n'affiche que le résumé (utile dans les journaux CI)
bash cve-2026-31431-detect.sh --quiet
# Désactiver la couleur ANSI (pour les fichiers journaux)
bash cve-2026-31431-detect.sh --no-colour
Le script shell utilise les mêmes codes de sortie (0 = OK, 1 = vulnérable) et produit une sortie JSON équivalente pour la consommation en pipeline. Lorsque Python 3 est disponible sur le système, le script shell l'utilise pour effectuer le test de socket AF_ALG en direct ; sinon, il se rabat sur la déduction à partir de la configuration du noyau.
La vraie solution est de corriger votre noyau. Consultez les avis de sécurité de votre distribution.
| Distribution | Où chercher |
|---|---|
| Ubuntu | ubuntu.com/security/CVE-2026-31431 |
| RHEL / Amazon Linux | dnf update kernel |
| SUSE | zypper update kernel-default |
| Debian | apt update && apt upgrade |
Si la vérification CONFIG_CRYPTO_AUTHENC indique =m (compilé en module, pas intégré), vous pouvez le mettre en blacklist :
echo 'install algif_aead /bin/false' > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null
Important : cette mitigation n'a aucun effet si
CONFIG_CRYPTO_AUTHENC=y(intégré). Dans ce cas, corriger le noyau est la seule solution. La vérification CONFIG_CRYPTO_AUTHENC dans le script vous indique dans quelle situation vous vous trouvez. Notez queCONFIG_CRYPTO_AUTHENCest la bonne clé de configuration du noyau — elle compile à la fois les modulesauthencetauthencesnà partir d'une seule option.
Cela peut affecter IPsec si vous l'utilisez — vérifiez avant de déployer à grande échelle.
Le correctif en amont est ce commit — il annule l'optimisation AEAD en place de 2017 dans algif_aead.c, séparant les scatterlists source et destination afin que les pages du page cache ne puissent plus se retrouver dans la destination inscriptible.
Si vous exécutez ce script dans un conteneur Docker, un pod Kubernetes ou tout autre environnement conteneurisé, le script vous avertira : les conteneurs partagent le noyau hôte. La vulnérabilité réside dans le noyau, pas dans l'image du conteneur. Vous devez évaluer et corriger l'hôte.
# GitHub Actions
# L'étape échouera naturellement et bloquera le pipeline lorsque le script se terminera avec le code 1.
# Aucune configuration supplémentaire nécessaire — les codes de sortie non nuls font échouer les étapes par défaut.
- name: Vérifier CVE-2026-31431
run: |
python3 cve-2026-31431-detect.py
rc=$?
if [ $rc -eq 1 ]; then
echo "VULNÉRABLE — pipeline bloqué"
exit 1
elif [ $rc -ne 0 ]; then
echo "ERREUR — le script de détection n'a pas pu se terminer (code de sortie $rc)"
exit $rc
fi
# Ansible
# Utilise playbook_dir pour garantir que le chemin du script se résout correctement.
# failed_when vérifie tout code de sortie non nul (vulnérabilité OU erreur de script).
- name: Vérifier CVE-2026-31431
script: "{{ playbook_dir }}/cve-2026-31431-detect.py"
register: cve_check
failed_when: cve_check.rc != 0
# Vérification Nagios / supervision (script shell — prend en charge les codes de sortie nativement)
bash cve-2026-31431-detect.sh --quiet
# code de sortie 0 = OK, code de sortie 1 = CRITIQUE (vulnérable)
# Sortie JSON pour SIEM / agrégation de journaux (script shell)
bash cve-2026-31431-detect.sh --json --quiet > /var/log/cve-2026-31431-$(hostname)-$(date +%Y%m%d).json
| Date | Événement |
|---|---|
| 2026-03-23 | Signalé à l'équipe de sécurité du noyau Linux |
| 2026-03-24 | Accusé de réception |
| 2026-03-25 | Correctifs proposés et examinés |
| 2026-04-01 | Correctif validé dans le noyau principal |
| 2026-04-22 | CVE-2026-31431 attribuée |
| 2026-04-29 | Divulgation publique |
Crédit à Taeyang Lee chez Theori pour l'idée de recherche originale, et à l'équipe Xint Code Research pour l'analyse complète de divulgation.
Vous avez trouvé un faux positif ? Une distribution manquée ? Une configuration du noyau qui devrait être vérifiée ? Les PR sont les bienvenues. L'objectif est un signal précis, pas seulement du texte rouge effrayant.
Cet outil est fourni tel quel à des fins de sécurité défensive. Pointez-le sur des systèmes que vous êtes autorisé à évaluer. Ne faites pas n'importe quoi.