Sécurité Python : pourquoi str.lower() provoquait une vulnérabilité dans la gestion des noms de domaine
L'utilisation directe de la méthode str.lower() dans la bibliothèque standard de Python créait une divergence par rapport à la spécification des noms de domaine internationalisés. En appliquant les règles Unicode récentes plutôt que la version 3.2.0 requise par la norme IDNA 2003, la fonction générait un encodage erroné, classé sous la faille CVE-2026-17084.
Fil « Risques de sécurité de str.lower() en Python »

Un conflit entre versions du standard Unicode
Les standards réseau historiques comme le système DNS (Domain Name System, le système de résolution des noms de domaine) ne prennent nativement en charge que les caractères ASCII (American Standard Code for Information Interchange, le jeu de caractères restreint à l'alphabet latin). Pour autoriser des noms de domaine utilisant d'autres alphabets, la norme IDNA 2003 (Internationalizing Domain Names in Applications, le standard de gestion des noms de domaine internationalisés) s'appuie sur la spécification StringPrep (RFC 3454, le document décrivant la préparation des chaînes Unicode). Cette dernière impose d'appliquer le case folding (la conversion insensible à la casse) en utilisant strictement la version 3.2.0 du standard Unicode (le répertoire universel de codage des caractères).
Dans le module stringprep de la bibliothèque standard de Python, la conversion des caractères reposait en partie sur un appel à la méthode système str.lower(). Or, str.lower() utilise la version globale d'Unicode embarquée avec le runtime Python en cours d'exécution — par exemple Unicode 17.0.0, vérifiable via unicodedata.unidata_version. Au fil des évolutions d'Unicode, les règles de conversion en minuscules de certains codepoints (les identifiants numériques uniques attribués à chaque caractère) ont changé. L'usage d'une version récente au lieu de unicodedata.ucd_3_2_0 provoquait donc un écart direct avec la norme de 2003.
Impact concret et exemple d'encodage
Cette non-conformité entraînait une faille de sécurité : deux systèmes interprétant la même chaîne Unicode pouvaient obtenir deux noms de domaine distincts, ouvrant la voie à des attaques par usurpation d'identité ou mauvaise résolution réseau. Le problème se manifeste clairement avec la lettre cherokee U+13A0 ("Ꭰ") lors de l'encodage au format Punycode (la représentation ASCII de chaînes Unicode) :
# Résultat conforme à la norme RFC 3454 (Unicode 3.2.0)
>>> "ᎠᎠ".encode("idna")
'xn--58da'
# Résultat erroné obtenu avec les règles d'Unicode 17.0.0
>>> "ᎠᎠ".encode("idna")
'xn--kz9aa'
Correctif et bonnes pratiques
Identifiée sous la référence CVE-2026-17084, cette vulnérabilité a été corrigée en ajoutant des exceptions explicites dans l'implémentation de Python. L'objectif est de forcer str.lower() à reproduire exactement le comportement d'Unicode 3.2.0 lors du traitement StringPrep.
Pour les applications modernes, la recommandation officielle reste d'éviter la méthode native .encode('idna') basée sur le standard obsolète IDNA 2003. Il est préférable d'utiliser le paquet externe idna publié sur PyPI (Python Package Index, le dépôt officiel des paquets Python), qui implémente la norme moderne IDNA 2008 (RFC 5890).