L’userinfo dans une URL peut-il masquer votre destination API ?
L’userinfo dans une URL peut déguiser une destination API. Découvrez comment analyser, rejeter, afficher et tester l’userinfo en toute sécurité avant qu’un agent envoie des requêtes.

Un agent qui accepte une URL arbitraire peut être dirigé vers une destination que son opérateur n’avait pas prévue. L’userinfo dans une URL facilite cette erreur, car il place un nom d’hôte familier avant un signe @, tandis que la véritable destination se trouve après. Si votre écran d’approbation, votre liste d’autorisation ou votre vue d’audit traite toute la chaîne comme une étiquette qui ressemble à un hôte, une requête peut sembler approuvée tout en partant vers un autre serveur.
Traitez l’userinfo comme une entrée interdite pour les actions API sortantes, sauf si vous avez une raison de compatibilité limitée et documentée de le prendre en charge. Analysez l’URL une seule fois à la frontière, rejetez un champ userinfo non vide avant que des identifiants n’entrent dans la requête, puis fondez toutes les décisions ultérieures sur les champs analysés. Ce n’est pas une astuce exotique liée aux URL. C’est une syntaxe ordinaire confrontée à une interface de contrôle qui demande aux personnes de lire trop de ponctuation trop vite.
Le nom d’hôte se trouve après le dernier signe arobase
Dans une URL HTTP absolue, l’autorité se situe entre // et le caractère /, ? ou # suivant. La RFC 3986 décrit cette autorité comme un userinfo facultatif, puis @, puis l’hôte, puis un port facultatif. L’hôte n’est donc pas le premier texte qui apparaît après //.
Considérez cette requête :
https://[email protected]/v1/charges
Une personne qui parcourt le début peut voir api.example.com et s’arrêter là. Un analyseur d’URL conforme la sépare ainsi :
scheme: https
userinfo: api.example.com
host: collector.invalid
port: 443
path: /v1/charges
La connexion TCP et la vérification du nom d’hôte TLS utilisent collector.invalid. La chaîne avant @ n’identifie pas le serveur distant. C’est l’userinfo, une ancienne partie de la grammaire des URL autrefois utilisée pour les noms et les mots de passe.
Le même problème apparaît sous une forme plus familière :
https://billing.example.com:[email protected]/invoices
Tout ce qui précède @ reste de l’userinfo, y compris les deux-points et le texte qui les suit. L’hôte distant reste evil.invalid. Une personne qui vérifie ne peut pas déduire la destination de manière fiable à partir de la première sous-chaîne qui ressemble à un nom d’hôte dans une URL brute.
N’essayez pas de résoudre ce problème en apprenant aux personnes qui vérifient à repérer ce caractère. Cette erreur survient pendant l’examen d’un incident, en fin de journée et lorsqu’un agent produit de nombreuses demandes d’action. Un contrôle qui dépend d’une lecture visuelle parfaite est un contrôle fragile.
La norme URL utilisée par les navigateurs et de nombreux environnements d’exécution aboutit au même résultat pratique pour les schémas spéciaux comme HTTPS : les champs de nom d’utilisateur et de mot de passe analysés sont distincts du nom d’hôte. Le comportement exact d’un analyseur peut varier face à une entrée mal formée ou à des échappements, ce qui donne une raison supplémentaire d’analyser avec l’environnement d’exécution qui enverra la requête. Ne validez pas avec une bibliothèque puis n’exécutez pas avec une autre qui accepte un ensemble différent de chaînes.
Une règle utile est simple : seul un nom d’hôte analysé peut décider où une requête est autorisée à aller. Le texte brut de l’URL sert de preuve, pas d’autorité.
L’userinfo crée un problème de vérification avant de créer un problème réseau
Le client réseau sait généralement où il va. L’échec se produit plus tôt, lorsqu’une personne ou un contrôle approuve une mauvaise représentation de cette destination.
Un flux d’agent typique comporte plusieurs endroits où le texte brut peut passer : l’argument d’appel d’outil, une carte d’approbation, un journal de session, un message d’erreur et une notification. Si l’une de ces vues indique Calling api.example.com parce qu’elle extrait le texte avant @, elle donne une information fausse à l’opérateur. Si une autre vue consigne la chaîne entière mais la tronque après une largeur fixe, l’hôte réel peut disparaître complètement.
C’est important même lorsque l’agent ne possède aucun identifiant pour la cible. Une requête sortante peut transporter des données utilisateur, un corps de requête signé, un jeton bearer choisi par une règle trop large ou simplement atteindre une adresse interne qui ne devrait jamais recevoir de trafic d’agent. Les identifiants attirent l’attention parce qu’ils sont concrets. L’intégrité de la destination exige la même rigueur.
On confond souvent la sécurité de l’affichage d’une URL et la sécurité de son transport. Échapper @ dans une vue HTML peut rendre une page moins trompeuse, mais cela ne détermine pas où se connecte un client HTTP. À l’inverse, un analyseur peut exécuter correctement l’appel réseau alors qu’une vue d’approbation mal conçue encourage toujours une personne à approuver le mauvais hôte. Il vous faut à la fois une décision de transport correcte et un affichage honnête.
Ne remplacez pas @ par un caractère anodin dans la requête stockée pour continuer ensuite. Cela masque l’entrée à l’origine du refus et complique l’enquête ultérieure. Conservez la chaîne d’origine comme entrée brute, marquez la requête comme rejetée et consignez la raison analysée sans écrire d’identifiants intégrés dans un journal lisible.
L’affichage devrait commencer par un champ de destination distinct, tel que Host: collector.invalid, puis présenter l’URL d’origine en dessous. Cet ordre transforme une énigme de ponctuation en information directe. Il donne aussi à la personne qui vérifie un champ stable à comparer avec l’identifiant demandé ou l’intégration prévue.
Rejeter l’userinfo est plus sûr que le corriger
Pour une passerelle d’actions d’agent, le comportement par défaut le plus sûr consiste à rejeter toute URL HTTP sortante dont le champ de nom d’utilisateur ou de mot de passe analysé n’est pas vide. La plupart des intégrations API envoient déjà les identifiants dans les en-têtes de requête ou utilisent un injecteur d’identifiants. Prendre en charge l’userinfo dans l’URL accroît la surface d’attaque sans répondre à un besoin API courant.
L’ordre de validation compte. Analysez d’abord la chaîne d’origine. Rejetez les URL mal formées, les schémas non pris en charge et l’userinfo avant les listes d’autorisation d’hôtes, les demandes d’approbation, les redirections, la résolution DNS ou la sélection d’identifiants. Cette séquence évite d’afficher une requête comme admissible si vous allez ensuite en écarter une partie.
Ce pseudocode exprime la règle :
u = parse_absolute_url(raw_url)
if u.scheme not in {"https", "http"}:
deny("unsupported scheme")
if u.username != "" or u.password != "":
deny("URL userinfo is not accepted")
host = normalize_hostname(u.hostname)
if host == "":
deny("missing hostname")
if not destination_is_allowed(u.scheme, host, u.port):
deny("destination is not allowed")
send(u)
L’analyseur doit renvoyer des champs structurés. Découper sur @, supprimer un préfixe ou rechercher une sous-chaîne de nom d’hôte échoue face à des variantes ordinaires. Une autorité peut contenir plusieurs @ dans l’entrée brute. Un analyseur décide quel délimiteur est syntaxique et si les caractères précédents font partie de l’userinfo. Il gère aussi les littéraux IPv6 entre crochets, les ports explicites, l’encodage en pourcentage et les composants vides avec plus de cohérence qu’une logique de chaîne écrite à la main.
Rejeter l’userinfo donne à l’appelant une correction claire : utilisez https://api.example.com/path, puis fournissez l’authentification HTTP par le canal d’identifiants prévu. Cela ne laisse pas l’appelant se demander si vous avez silencieusement transformé https://name@host en https://host.
Un cas de compatibilité mérite d’être reconnu. Certaines anciennes URL intègrent une authentification Basic sous la forme https://name:secret@host/path. Si une migration doit gérer ces URL, faites-le dans un parcours d’importation unique qui extrait les identifiants vers un stockage protégé, confirme l’hôte analysé et supprime la chaîne source de l’enregistrement d’importation lorsque la politique le permet. Ne laissez pas l’API d’action à l’exécution continuer à les accepter indéfiniment. Le code de compatibilité temporaire a tendance à devenir une surface d’attaque permanente.
Les listes d’autorisation d’hôtes doivent utiliser des libellés analysés, pas des chaînes rassurantes
Une liste d’autorisation de destinations doit comparer des noms d’hôte analysés et normalisés, et non lancer une recherche de sous-chaîne dans l’URL brute. La règle raw_url.includes("api.example.com") accepte à la fois https://[email protected] et https://api.example.com.evil.invalid. Aucune de ces requêtes ne va vers api.example.com.
La correspondance exacte d’hôte est la règle la moins surprenante. Si une intégration a besoin uniquement de api.example.com, autorisez ce nom et rejetez tous les autres noms d’hôte. Si elle a réellement besoin de sous-domaines, comparez les libellés DNS : autorisez example.com et les noms qui se terminent par .example.com, mais rejetez badexample.com et example.com.evil.invalid.
Une implémentation claire ressemble à ceci :
function allowedHost(host, root) {
const h = host.toLowerCase().replace(/\.$/, "")
const r = root.toLowerCase().replace(/\.$/, "")
return h === r || h.endsWith("." + r)
}
Ce code suppose que l’analyseur d’URL a déjà fourni un nom d’hôte et que l’appelant a déjà rejeté l’userinfo. Il ne doit pas recevoir une URL complète. Séparer ces responsabilités empêche un appelant ultérieur de transmettre une chaîne d’autorité contenant un port, un nom d’utilisateur ou un signe @.
Les domaines internationalisés demandent aussi une décision. Les navigateurs sérialisent souvent les noms d’hôte en ASCII avec un traitement IDNA, tandis qu’une personne peut voir du texte Unicode. Utilisez pour la comparaison la même forme canonique que votre client de requêtes et affichez à la fois l’hôte canonique et une forme lisible lorsqu’ils diffèrent. N’affirmez pas que deux chaînes identifient le même domaine parce qu’elles se ressemblent dans une police proportionnelle.
Les adresses IP méritent leur propre règle. Une liste d’autorisation de noms d’hôte ne rend pas automatiquement un littéral IP sûr, et la résolution DNS après l’approbation peut modifier l’adresse atteinte par un nom d’hôte. Si votre modèle de menace inclut l’accès à des services locaux, décidez explicitement si les adresses privées, de bouclage, locales au lien et les adresses IPv6 locales sont autorisées. Rejeter l’userinfo est nécessaire, mais cela ne résout pas à lui seul la falsification de requête côté serveur.
Les ports ont aussi leur importance. https://api.example.com:8443 peut être un point de terminaison partenaire valide ou un service d’administration inattendu. Consignez le port effectif et incluez-le dans les décisions d’approbation lorsque l’intégration restreint un port particulier. Une étiquette d’hôte ne décrit pas à elle seule la destination réseau complète.
Les redirections doivent franchir la même barrière
Une URL initiale autorisée ne rend pas toutes les cibles de redirection autorisées. Les redirections HTTP sont de nouvelles instructions de destination fournies par le serveur distant, et une passerelle d’agent doit analyser et autoriser chacune d’elles avant de la suivre.
Supposons qu’un agent demande https://api.example.com/export. Cet hôte renvoie une réponse 302 avec cet emplacement :
https://[email protected]/download?id=42
Un client qui suit automatiquement les redirections se connectera ensuite à receiver.invalid. Si la passerelle n’a approuvé que la première URL, sa liste d’autorisation et son écran d’approbation ne décrivent plus l’action réseau effectuée.
Traitez les redirections comme une boucle avec une limite choisie pour votre client. Pour chaque valeur d’emplacement, résolvez une référence relative par rapport à l’URL courante approuvée, analysez l’URL absolue obtenue, appliquez les mêmes règles de schéma, d’userinfo, d’hôte, de port et d’adresse, puis décidez si vous poursuivez. Consignez à la fois la réponse source et la destination de redirection analysée.
Ne transférez pas les identifiants entre hôtes par défaut. Les bibliothèques clientes HTTP diffèrent quant à la conservation d’un en-tête Authorization après une redirection vers un autre hôte, et les en-têtes personnalisés peuvent encore se comporter différemment. Le comportement le plus sûr pour une passerelle associe un identifiant à une destination approuvée précise et construit une nouvelle requête sortante seulement après que la destination de redirection a passé l’autorisation. Une redirection d’un hôte appartenant à un fournisseur vers un autre peut être attendue, mais elle doit relever d’une règle explicite plutôt que d’un hasard des réglages par défaut de la bibliothèque.
La gestion des méthodes exige aussi de l’attention. Une réponse 303 transforme couramment une requête ultérieure en GET, tandis que 307 et 308 conservent la méthode et le corps. Si un agent publie un corps sensible, une redirection qui préserve la méthode peut l’envoyer ailleurs. Consignez la méthode utilisée à chaque étape et affichez la destination finale dans le résultat de l’action.
Un client peut aussi être configuré pour ne pas suivre les redirections. C’est un choix judicieux pour des outils API limités. Renvoyez la réponse de redirection à l’agent et exigez qu’il demande explicitement la destination suivante. Cela crée un nouvel événement d’approbation, mais donne à l’opérateur un moment clair pour évaluer un changement d’hôte. Pour une prise en charge HTTP étendue, les redirections automatiques ne sont acceptables que si chaque étape franchit la même barrière.
Les identifiants doivent être sélectionnés après la validation de la destination
L’ordre dangereux se décrit facilement : choisir un identifiant parce que l’URL brute contient le nom d’un service connu, analyser ensuite l’URL, puis envoyer la requête. Une astuce avec @ peut transformer le texte familier en userinfo pendant que le secret sélectionné voyage vers un hôte contrôlé par un attaquant.
L’ordre sûr est tout aussi simple. Analysez et validez d’abord l’URL. Autorisez ensuite son schéma, son hôte, son port et tout état de redirection. Cherchez seulement alors un identifiant lié à cette destination approuvée et injectez-le dans la requête sortante. Gardez ce secret hors des arguments d’outils, de la mémoire de l’agent et des valeurs renvoyées.
Cela résout aussi une erreur de configuration moins spectaculaire mais fréquente. Un identifiant associé à api.example.com ne doit pas partir automatiquement vers uploads.example.com, même si les deux noms relèvent du même domaine parent. Des hôtes différents ont souvent des propriétaires, une terminaison TLS, une journalisation ou des niveaux d’autorisation différents. Commencez par une liaison exacte à l’hôte. Élargissez la correspondance uniquement lorsque l’intégration explique pourquoi elle en a besoin.
L’injection d’en-têtes est préférable à l’userinfo dans une URL, car elle sépare la destination de l’authentification. Un enregistrement de requête peut indiquer qu’un en-tête d’autorisation a été injecté sans stocker sa valeur. L’agent reçoit la réponse dont il a besoin pour poursuivre son travail, pas un secret réutilisable.
Sallyport applique cette séparation en conservant les identifiants API et SSH dans son coffre chiffré et en exécutant l’action sortante sans exposer ces identifiants à l’agent. Pour toute passerelle suivant ce modèle, rejeter l’userinfo avant la recherche d’identifiants comble l’écart entre la destination voulue par l’opérateur et l’hôte qui reçoit la requête.
Ne faites pas non plus confiance à un en-tête de requête fourni par l’agent pour identifier sa destination. L’en-tête Host, l’autorité HTTP/2, l’hôte de l’URL, la configuration du proxy et le nom du serveur TLS peuvent interagir selon le client. Une passerelle doit posséder les réglages de connexion et les déduire de l’URL analysée et validée. Si vous autorisez des en-têtes personnalisés, traitez-les comme du contenu de requête, pas comme une permission de modifier le routage.
Les cartes d’approbation doivent afficher d’abord la destination analysée
Une carte d’approbation doit répondre à trois questions concrètes sans demander à son lecteur de reconstituer une URL : quel processus a fait la demande, quelle opération va être exécutée et quel hôte la recevra. Placez le nom d’hôte et le port analysés sur une ligne de destination dédiée. Placez la méthode HTTP et le chemin à proximité. Affichez l’URL d’origine comme élément de preuve, pas comme seul signal de destination.
Pour la requête d’apparence mal formée utilisée plus haut, une carte utile indiquerait :
Process: signed agent process
Action: POST /v1/charges
Host: collector.invalid:443
Result: blocked because URL userinfo is present
Input: https://[email protected]/v1/charges
Elle ne doit pas afficher api.example.com comme un badge dérivé du côté gauche de l’autorité. Elle ne doit pas non plus indiquer seulement External HTTP request, car cela ne donne à personne de base utile pour décider.
L’approbation par session et l’approbation par appel répondent à des problèmes humains différents. Une approbation de session indique qu’un processus en cours particulier peut utiliser une passerelle pendant toute sa durée de vie. Une approbation par appel indique qu’un identifiant ou une action particulièrement sensible exige une nouvelle décision humaine. Aucune ne remplace une validation d’URL élémentaire. Un processus de confiance peut tout de même être manipulé par un commentaire de ticket non fiable, un champ de métadonnées de package ou un fichier de configuration généré.
L’échelle de décision de Sallyport maintient un coffre verrouillé comme arrêt absolu, puis utilise l’autorisation de session et une confirmation facultative par secret. Cette structure fonctionne au mieux lorsque les destinations mal formées échouent avant d’atteindre une carte d’approbation, car un opérateur ne devrait pas avoir à décider si un caractère de ponctuation dans une URL a modifié le point de terminaison.
Soyez précis dans les messages de refus. Userinfo is not allowed in outbound URLs indique à un développeur d’agent ce qu’il doit corriger. Invalid request entraîne des tentatives répétées, des échappements improvisés et une pression pour assouplir la validation. Évitez de répéter un mot de passe si l’analyseur en a extrait un. Le message peut nommer le composant interdit sans reproduire son contenu.
Les tests doivent utiliser des entrées trompeuses, pas seulement des URL valides
Une suite de tests de validation a besoin d’exemples conçus pour tromper les lecteurs humains et les vérifications naïves de chaînes. Le passage de https://api.example.com/v1 ne prouve presque rien sur la frontière où un agent peut envoyer du texte arbitraire.
Commencez par des cas comme ceux-ci et vérifiez l’hôte analysé, la décision et la raison :
ALLOW https://api.example.com/v1 host=api.example.com
DENY https://[email protected]/v1 reason=userinfo
DENY https://name:[email protected]/v1 reason=userinfo
DENY https://api.example.com.evil.invalid/v1 reason=host
DENY https://api.example.com:444/v1 reason=port
DENY https://[::1]/v1 reason=address
Ajoutez un scénario de redirection. Faites en sorte qu’un serveur de test autorisé émette une redirection dont l’emplacement contient un userinfo, puis vérifiez que le client consigne une deuxième étape bloquée sans envoyer de requête au serveur de destination. Cela détecte l’erreur fréquente où la validation de l’URL initiale vit dans un chemin de code et la gestion des redirections dans un rappel de bibliothèque.
Testez délibérément l’encodage en pourcentage, sans supposer que chaque @ encodé est équivalent. Dans de nombreux analyseurs, %40 dans un chemin reste une donnée de chemin, alors qu’un véritable @ dans l’autorité agit comme délimiteur. Envoyez la chaîne brute exacte à l’analyseur utilisé en production et vérifiez ses champs. L’invariant important n’est pas une règle de décodage maison. C’est qu’un champ userinfo analysé non vide ne puisse jamais atteindre l’émetteur.
Testez également le rendu des journaux et des approbations. Un contrôle de sécurité peut produire le bon refus tout en créant une mauvaise trace opérationnelle si l’affichage tronque l’hôte réel ou expose le texte du mot de passe analysé. Les tests de capture d’écran des lignes de destination sont utiles, car des régressions visuelles arrivent souvent avec des changements de conception qui semblent inoffensifs.
Enfin, testez la chaîne d’audit et le parcours de révocation autour d’un appel refusé. Un refus doit être suffisamment visible pour l’enquête, sans jamais inclure de secrets injectés. L’enregistrement utile contient l’entrée brute sous des contrôles d’accès adaptés, le schéma et l’hôte analysés, la raison de la décision, l’identité du processus appelant et le fait qu’aucune action sortante n’a eu lieu.
La syntaxe d’URL n’est pas un langage de politique
Certaines équipes répondent aux cas limites d’URL en ajoutant une pile grandissante d’exceptions : autoriser un nom d’utilisateur pour ce fournisseur, accepter un port spécial pour cet environnement, faire confiance à une redirection seulement lorsqu’un en-tête semble correct et corriger un comparateur de chaînes à chaque incident. Cette approche paraît souple parce qu’elle évite de refuser une demande étrange. Elle crée aussi des règles que personne ne peut examiner de manière fiable.
Gardez une règle courte. Les requêtes sortantes ont une destination analysée. L’userinfo est rejeté. Le schéma, l’hôte, le port et la classe d’adresse autorisés sont explicites. Les redirections repassent par les mêmes contrôles. Les identifiants sont sélectionnés seulement après validation de la destination. Chaque décision produit un enregistrement qui énonce clairement l’hôte analysé.
Cette règle rejettera quelques anciennes URL qu’un navigateur pourrait accepter. C’est bien ainsi. Un agent autonome n’a pas besoin de toutes les possibilités historiques d’une barre d’adresse de navigateur. Il a besoin d’une interface limitée qui rend difficile toute confusion entre l’action, la destination et l’identifiant.
Si vous devez modifier cette interface, rendez l’exception visible sous la forme d’une capacité nommée, avec des tests et une décision d’expiration. Ne l’enfouissez pas dans le code de nettoyage d’URL. La première entrée hostile révélera la différence entre un texte qui ressemble à un hôte et l’hôte que votre client contacte réellement.
FAQ
Un signe @ dans une URL peut-il changer l’hôte de destination ?
Oui. Dans une URL telle que https://[email protected]/path, l’hôte de destination est evil.example, et non api.example.com. Le texte avant @ est l’userinfo. L’accepter dans des URL fournies par un agent ouvre donc la voie à des erreurs faciles lors de la vérification humaine.
L’userinfo dans une URL est-il une syntaxe valide ?
C’est une syntaxe d’URL valide, même si de nombreux clients API n’ont aucune raison de l’accepter. La RFC 3986 autorise un userinfo facultatif dans une autorité, mais ce n’est pas une raison pour le laisser franchir la frontière d’action d’un agent.
Une passerelle API doit-elle rejeter les URL contenant un userinfo ?
Rejetez-le dès la frontière, sauf si vous avez un besoin de compatibilité très précisément défini. Ne le supprimez pas silencieusement avant de continuer, car cela modifie la requête fournie par l’appelant et laisse une trace trompeuse.
Est-ce que user:[email protected] envoie le trafic vers user ?
Non. https://user:[email protected]/v1 a pour nom d’hôte api.example.com ; user:pass est l’userinfo. Un analyseur expose ces champs séparément, et les contrôles de sécurité doivent utiliser le nom d’hôte analysé plutôt que la chaîne brute.
Dois-je placer des identifiants Basic dans une URL ?
L’authentification Basic doit aller dans un en-tête HTTP Authorization, pas dans une URL. Les identifiants présents dans une URL se retrouvent bien plus facilement dans les journaux, l’historique, les commandes copiées et les messages d’erreur que les en-têtes.
Les redirections compliquent-elles la validation de l’userinfo dans une URL ?
Chaque cible de redirection doit subir les mêmes contrôles d’analyse et d’autorisation que l’URL d’origine. Vérifier uniquement la première URL permet à un point de terminaison public autorisé de rediriger un agent vers un hôte non approuvé.
api.example.com.evil.example est-il identique à api.example.com ?
Non. api.example.com.evil.example est un sous-domaine de evil.example, tandis que [email protected] cible réellement api.example.com. Analysez d’abord l’hôte, puis comparez les libellés de domaine selon votre règle de liste d’autorisation explicite.
Comment valider une URL d’API sortante ?
Évitez les expressions régulières sur l’URL entière. Utilisez un analyseur conforme aux normes, rejetez explicitement l’userinfo, exigez HTTPS lorsque c’est pertinent, normalisez le nom d’hôte analysé et comparez-le aux hôtes ou suffixes de domaine autorisés.
Que doit enregistrer un journal d’audit pour une requête HTTP d’agent ?
Un bon journal d’audit conserve l’entrée brute pour l’enquête et stocke séparément les champs analysés : schéma, nom d’hôte, port, chemin, cible de redirection et décision. Affichez le nom d’hôte analysé de façon visible afin que la personne qui vérifie n’ait pas à décoder mentalement la ponctuation.
Comment tester un outil d’agent contre des destinations URL déguisées ?
La correction tient généralement à une petite règle de validation, mais elle doit s’appliquer avant les approbations et l’injection d’identifiants. Ajoutez des cas de test pour @, les délimiteurs encodés en pourcentage, plusieurs caractères @, les redirections, les hôtes en casse mixte et les points finaux, afin qu’une future refactorisation ne rouvre pas la faille.