Retour au Centre de connaissances
Empreinte

Fingerprinting CSS : comment les styles vous suivent

Comment les media queries CSS comme color-gamut et prefers-color-scheme créent des signaux d'empreinte, et comment garder cohérentes les valeurs CSS et JavaScript.

BotBrowser Team

Documentation

Vous préférez la doc produit maintenue ?

Cet article a une page équivalente dans le centre de documentation. Utilisez les docs pour le flux canonique, les flags à jour et la référence durable.

On décrit généralement CSS comme un langage de mise en forme, pas comme une surface de suivi. Pourtant, les media queries permettent à une feuille de style d'interroger le navigateur sur l'écran, les réglages de la personne et les périphériques de saisie disponibles, et les réponses diffèrent d'un groupe d'utilisateurs à l'autre. Des fonctionnalités comme prefers-color-scheme, prefers-reduced-motion, color-gamut, resolution, pointer et hover révèlent chacune un petit élément de la configuration de l'appareil. Une feuille de style peut lire ces éléments sans une seule ligne de JavaScript, ce qui explique pourquoi les outils de confidentialité centrés sur les scripts la négligent parfois.

Voir la vidéo

Cette vidéo en anglais montre comment une feuille de style peut signaler au serveur le réglage du mode sombre d'une personne sans exécuter de script, puis compare la réponse de la feuille de style à ce que lit un script dans une page de laboratoire locale et dans Chrome officiel sur deux machines. Elle n'utilise aucun profil BotBrowser et n'établit ni identité, ni anonymat, ni accès, ni la décision d'un site distant. L'audio est en anglais.

La question utile n'est pas de savoir si une seule fonctionnalité identifie une personne. Ce n'est pas le cas. La question est de savoir si les valeurs qu'une page voit par CSS correspondent à celles qu'elle voit par JavaScript, et si elles restent stables pour la configuration que vous souhaitez présenter. Les sections suivantes décrivent les fonctionnalités de média concernées, la manière dont le chargement conditionnel les expose sans script, les raisons pour lesquelles les protections partielles laissent des failles, la façon de vérifier la cohérence, ce que peuvent faire les auteurs de sites, et ce que BotBrowser couvre ou non.

BotBrowser peut garder les media queries CSS et les valeurs d'affichage associées alignées sur un profil chargé, avec notamment un jeu de couleurs explicite et des valeurs d'écran fournies par le profil. Il ne contrôle pas ce que la feuille de style d'un site demande ou enregistre, ne rend pas une session anonyme et ne remplace pas les réglages d'accessibilité. Cet article porte donc sur la cohérence du profil et ses limites, pas sur une promesse d'anonymat.

Résumé

Les media queries CSS exposent des valeurs de faible entropie sur l'écran, les préférences et l'entrée, et le chargement conditionnel de ressources peut les révéler sans JavaScript. Faites dériver CSS et JavaScript de la même source du profil, testez plusieurs sessions et considérez l'alignement de BotBrowser comme une aide à la cohérence, pas comme une garantie d'anonymat.

Sommaire

Une interface web adapte son animation, son contraste, ses couleurs et son thème aux réglages du navigateur, avec une commande visible pour choisir une alternative

Quelles fonctionnalités de média portent un signal

Les media queries CSS testent des conditions sur l'environnement dans lequel une page est affichée. Les fonctionnalités qui comptent le plus pour le fingerprinting se répartissent en quatre groupes.

  • Affichage. resolution, color, color-index, color-gamut et monochrome décrivent la densité de pixels, la profondeur de couleur et l'étendue des couleurs que l'écran peut afficher.
  • Préférences. prefers-color-scheme, prefers-reduced-motion, prefers-contrast, prefers-reduced-transparency et forced-colors exposent des choix faits dans les réglages du système d'exploitation ou du navigateur.
  • Fenêtre et écran. width, height, aspect-ratio et orientation décrivent la fenêtre, tandis que les plus anciens device-width et device-height décrivent l'écran.
  • Interaction. hover, any-hover, pointer et any-pointer indiquent à la page si le dispositif principal peut survoler un élément et avec quelle précision.

Chaque valeur provient d'un élément concret. Le matériel de l'écran fixe la gamme, la profondeur et la résolution. Les réglages du système d'exploitation décident du mode sombre, du contraste et des préférences de mouvement. La configuration du navigateur peut remplacer celle du système, et les modes de navigation privée peuvent modifier certaines valeurs. Le type d'appareil compte aussi : les appareils tactiles déclarent en général pointer: coarse et hover: none, alors que les ordinateurs de bureau déclarent pointer: fine et hover: hover.

Que révèle tout cela ? La spécification W3C Media Queries Level 5 reconnaît que les fonctionnalités de préférences de l'utilisateur peuvent contribuer au fingerprinting. Chaque fonctionnalité prise seule a une faible entropie, en général un booléen ou quelques valeurs, souvent de un à trois bits. Combinées, elles changent la donne. Une étude de TU Graz a rapporté que les fonctionnalités de média CSS seules distinguaient environ trois utilisateurs sur dix lorsque plus de quinze fonctionnalités étaient interrogées ensemble, et l'entropie totale a été estimée entre 10 et 15 bits dans des conditions favorables. Lisez ces chiffres comme des plages rapportées, pas comme des garanties, car ils dépendent de la population mesurée et du nombre de fonctionnalités que la page interroge.

Un calcul approximatif montre pourquoi les combinaisons comptent. Sept fonctionnalités à deux ou trois valeurs chacune autorisent déjà plusieurs centaines de combinaisons distinctes. Les combinaisons réelles sont moins nombreuses, car les fonctionnalités sont corrélées : un téléphone à pointeur tactile n'a presque jamais de survol, et un ordinateur de bureau à pointeur précis en a presque toujours. L'information effective est donc inférieure au produit brut, mais elle reste supérieure à ce que suggère une fonctionnalité isolée.

Toutes les valeurs n'ont pas le même poids. Une valeur courante, comme le mode clair sur un écran de bureau standard, place le visiteur dans un très grand groupe et apprend peu de chose au site. Une valeur rare, comme un mode forced-colors actif, une gamme rec2020 ou une demande de transparence réduite, place le visiteur dans un groupe bien plus petit. Des fonctionnalités plus récentes comme dynamic-range, prefers-reduced-data et inverted-colors ajoutent des dimensions, et chaque fonctionnalité qu'un navigateur ajoute à la plateforme est une valeur de plus qu'une feuille de style peut interroger. Pour cette raison, la combinaison inhabituelle est en général plus informative que la combinaison courante, et une combinaison incohérente est la plus informative de toutes.

Comment une feuille de style lit des valeurs sans JavaScript

Un script peut tester directement une media query avec window.matchMedia(), qui indique si une condition est remplie à cet instant. C'est la voie que surveillent la plupart des outils de confidentialité.

const dark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const dense = window.matchMedia('(min-resolution: 2dppx)').matches;
const wide = window.matchMedia('(color-gamut: p3)').matches;

La seconde voie n'a besoin d'aucun script. C'est le chargement conditionnel de ressources, où une règle à l'intérieur d'un bloc @media fait référence à une URL.

@media (prefers-color-scheme: dark) {
  .tracker {
    background-image: url('https://stats.example.com/dark');
  }
}
@media (prefers-color-scheme: light) {
  .tracker {
    background-image: url('https://stats.example.com/light');
  }
}

Le navigateur ne demande que l'image dont la condition est remplie, de sorte que le serveur apprend le jeu de couleurs du visiteur d'après l'URL reçue. En répétant le motif avec davantage de conditions, une seule feuille de style peut recueillir de nombreuses réponses binaires : sombre ou clair, dense ou standard, pointeur précis ou tactile. Comme l'information circule dans une requête ordinaire, les personnes qui bloquent entièrement JavaScript peuvent tout de même voir leur empreinte relevée en partie de cette manière.

Les conditions peuvent aussi être combinées. Une règle comme @media (prefers-color-scheme: dark) and (min-resolution: 2dppx) ne s'applique que si les deux parties sont vraies, ce qui permet à une feuille de style de demander une URL par combinaison au lieu d'une par fonctionnalité. Le nombre de requêtes reste modeste tout en séparant les visiteurs selon plusieurs fonctionnalités à la fois, et un seul écart entre deux voies peut affecter le résultat de nombreuses règles.

Deux propriétés de cette voie méritent d'être retenues. D'abord, les media queries sont réévaluées quand l'environnement change : passer au mode sombre au milieu d'une visite déclenche une nouvelle requête, et le changement devient visible dans le temps, pas seulement au chargement. Ensuite, les fonctionnalités de préférences sont normalement partagées par tous les cadres d'une page, alors que les fonctionnalités de fenêtre suivent la taille de chaque cadre, de sorte que les valeurs peuvent légitimement différer entre un document et un cadre intégré.

C'est aussi la raison pour laquelle les deux voies doivent concorder. La feuille de style et le script lisent le même environnement, et un site peut comparer ce que chacun rapporte. Si matchMedia('(prefers-color-scheme: dark)') indique une chose alors que la ressource chargée par la feuille de style en indique une autre, ou si screen.colorDepth et devicePixelRatio contredisent les fonctionnalités CSS color et resolution, l'écart est en soi un signal, quelles que soient les valeurs prises une à une.

Les media queries ne sont pas la seule partie de CSS qui reflète la plateforme. Les règles @supports révèlent quelles propriétés et valeurs le navigateur implémente, les mots-clés de couleurs système se résolvent en couleurs définies par le thème du système d'exploitation, et les mots-clés de police comme system-ui se résolvent en une police de la plateforme. Une feuille de style peut s'en servir pour apprendre quel système d'exploitation ou quelle famille de navigateurs a produit une page, et chacun de ces éléments doit rester aligné sur le reste de la configuration pour la même raison. Un profil qui décrit une plateforme alors que les couleurs système ou la police système en suivent une autre produit le même type d'écart qu'une media query qui contredit matchMedia().

Pourquoi les protections courantes laissent des failles

Plusieurs approches connues règlent une partie du problème et laissent le reste.

  • Les extensions qui enveloppent matchMedia() modifient ce que voient les scripts, mais la feuille de style continue d'évaluer les règles @media d'après l'écran et les réglages réels. Une page qui utilise le chargement conditionnel reçoit la vraie valeur par CSS et la valeur modifiée par le script, de sorte que l'extension crée elle-même l'incohérence.
  • Désactiver CSS n'est pas praticable, car la plupart des sites en dépendent pour être utilisables.
  • Les préférences standardisées, comme toujours déclarer le mode clair, aucun mouvement réduit et une gamme sRGB, réduisent la variation mais créent un groupe distinctif. Un navigateur qui déclare la valeur par défaut pour chaque préférence peut se démarquer parmi des personnes dont les réglages diffèrent.
  • Tor Browser standardise de nombreuses valeurs chez ses utilisateurs, ce qui donne un grand groupe partagé, mais ce groupe est reconnaissable comme Tor Browser.

Les modes de résistance intégrés aux navigateurs suivent un schéma voisin. Firefox propose un réglage de résistance au fingerprinting qui déclare des valeurs fixes pour plusieurs fonctionnalités de préférences, ce qui donne le même compromis que la standardisation : bien moins de variation dans le groupe, mais un groupe reconnaissable à ses valeurs fixes. Aucune de ces approches n'est mauvaise pour le public visé. Elles répondent simplement à une autre question que celle posée ici, à savoir comment garder cohérente une configuration choisie sur toutes les voies qu'une page peut emprunter.

Ce qui reste est une exigence de cohérence, pas de dissimulation. Les fonctionnalités de média CSS, matchMedia() et des valeurs associées comme screen.colorDepth et devicePixelRatio doivent toutes provenir d'une seule source, et cette source doit décrire un appareil cohérent. La politique de ratio de pixels de l'appareil explique pourquoi la densité est l'une des valeurs les plus souvent comparées, et le guide sur le fingerprinting de l'écran et de la fenêtre traite les valeurs de dimensions qui l'accompagnent.

Vérifier la cohérence d'un profil

Une vérification utile compare la même fonctionnalité par deux voies pour un même profil, puis répète la comparaison lors d'une session ultérieure.

  • Jeu de couleurs. Ouvrez une page dotée d'un thème sombre et vérifiez que le thème affiché et matchMedia('(prefers-color-scheme: dark)').matches concordent entre eux et avec la valeur que vous avez configurée.
  • Résolution. Comparez window.devicePixelRatio au résultat de matchMedia('(min-resolution: 2dppx)'). Les deux doivent décrire la même densité.
  • Profondeur de couleur et gamme. Comparez screen.colorDepth à la fonctionnalité CSS color, et contrôlez color-gamut par rapport à l'écran que représente le profil.
  • Pointeur et hover. Confirmez que pointer et hover correspondent au périphérique d'entrée principal déclaré par le profil, qui n'est pas toujours le facteur de forme : un profil de téléphone signale normalement coarse sans hover, tandis qu'un profil de bureau peut encore signaler coarse ou sans hover lorsque son entrée déclarée est un écran tactile.
  • Stabilité. Répétez les mêmes vérifications sur plusieurs sessions avec le même profil. Les valeurs doivent être identiques à chaque fois.

Testez la voie de la feuille de style aussi bien que celle du script. Une petite page locale dont les règles @media changent la couleur d'un élément visible montre ce que voit CSS, et le chargement conditionnel lit les mêmes valeurs. Si le rendu et le résultat du script divergent, cet écart est la première chose à corriger, avant tout autre réglage.

Le mode sombre modifie aussi l'apparence des pages. Si vous réalisez des captures d'écran ou comparez des mises en page entre deux exécutions, fixez explicitement le jeu de couleurs pour que les résultats restent comparables. Une valeur non définie qui suit la machine hôte peut différer entre un ordinateur portable et un serveur, et la différence apparaîtra comme un changement visuel sans rapport avec la page.

Incluez dans la revue les cadres intégrés et les styles d'impression. Un cadre évalue ses propres règles @media, donc une page de test qui intègre un second document montre si les fonctionnalités de préférences concordent entre cadres, tandis que les fonctionnalités de fenêtre suivent la taille de chaque cadre. Les styles d'impression utilisent le type de média print, qu'une page peut déclencher volontairement, si bien qu'une feuille de style contenant un bloc @media print est un autre endroit où des valeurs liées à l'affichage peuvent être lues. Considérez cela comme la même vérification répétée dans d'autres contextes, pas comme des problèmes distincts.

Lorsqu'une vérification échoue, ne changez qu'un élément à la fois. Partez d'un lancement de référence où seul le profil est chargé, relevez les valeurs des deux voies, puis ajoutez une seule option, comme le jeu de couleurs ou la source d'écran, et comparez de nouveau. Conservez dans vos notes la commande de lancement finale pour qu'une session ultérieure puisse la reproduire à l'identique. Si le jeu de couleurs ne correspond pas à ce que vous attendiez, fixez-le explicitement plutôt que de compter sur la valeur par défaut. Si une requête de fonctionnalité ou une couleur système désigne une autre plateforme que celle voulue, vérifiez d'abord que le profil chargé décrit bien la plateforme que vous comptiez utiliser, car la disponibilité des fonctionnalités suit le profil.

Une condition de réussite par paire

Paire à comparerRéussit quand
prefers-color-scheme contre matchMediaLes deux rapportent le même schéma à chaque chargement
devicePixelRatio contre min-resolutionLa coupure de la requête correspond au rapport annoncé
screen.colorDepth contre colorscreen.colorDepth vaut au moins trois fois color
pointer / hover contre l'entréeLes deux correspondent au périphérique d'entrée principal décrit par le profil

La liste précédente indique quoi regarder ; ce tableau indique quand ce regard répond à la question. Sans condition écrite, la personne qui vérifie compare deux valeurs à l'œil et retient la paire qui paraît plausible, ce qui est exactement la façon dont un désaccord survit à plusieurs sessions.

Écrivez la condition avant de lire l'une ou l'autre valeur, et notez le résultat comme vrai ou faux plutôt que comme une paire de nombres. Une ligne booléenne est ce qui rend deux sessions comparables : les mêmes quatre lignes, le même résultat attendu, et un diff qui montre quelle ligne a basculé.

Surveillez les unités. devicePixelRatio est un rapport comme 2, tandis que min-resolution accepte dppx ou dpi, donc (min-resolution: 2dppx) et (min-resolution: 192dpi) décrivent la même densité écrite de deux façons. Comparer un rapport avec une valeur en dpi produit un désaccord qui est une erreur d'unité et non un problème de profil.

Surveillez aussi le sens de la comparaison. (min-resolution: 2dppx) demande si la densité vaut au moins deux, donc un profil à rapport exactement 2 réussit et un rapport de 1.5 échoue ; c'est un résultat correct, pas un défaut. Notez la requête exacte utilisée pour qu'une session ultérieure ne lise pas une requête modifiée comme un écran modifié.

Deux lignes méritent une attention particulière, et aucune n’est une simple égalité. CSSOM View exige que screen.colorDepth vaille au moins trois fois la valeur CSS color, car la première compte des bits par pixel et la seconde des bits par composante de couleur ; l’égalité n’est ni exigée ni garantie, donc les comparer comme si elles devaient coïncider signale un défaut là où il n’y en a pas. La ligne du pointeur est l’autre : Media Queries Level 5 définit pointer et hover à partir du périphérique de pointage principal et non du facteur de forme, et autorise explicitement un écran tactile comme entrée principale sur une machine de bureau, si bien qu’un profil de bureau peut rapporter pointer: coarse ou hover: none et rester cohérent. La gestion des couleurs couvre le cas voisin où une affirmation de gamut dépasse l’écran qu’elle décrit.

Ce que peuvent faire les auteurs de sites

Les auteurs de sites ont leur propre rôle dans tout cela. Les requêtes @media existent pour que la présentation puisse s'adapter, et cet objectif mérite d'être protégé. Quelques habitudes le gardent séparé de la collecte.

  • Utilisez les fonctionnalités de média pour modifier la mise en forme, et évitez d'y lier des requêtes réseau. Un arrière-plan différent pour le mode sombre se règle en général avec une seule ressource et des propriétés personnalisées CSS, ou avec l'élément <picture>, sans URL par fonctionnalité.
  • Servez toute ressource conditionnée par un média depuis votre propre origine. Une requête vers un hôte tiers qui varie selon l'affichage ou la préférence donne à cet hôte un signal que vos visiteurs n'ont jamais accepté de partager.
  • N'enregistrez pas quelle ressource conditionnelle un visiteur a récupérée, sauf si vous en avez besoin. Si vous l'enregistrez, indiquez-le dans votre avis de confidentialité et conservez les données peu de temps.
  • Respectez la préférence que les personnes ont définie. Le mouvement réduit, le contraste et les couleurs forcées sont des réglages d'accessibilité, et l'article sur les préférences de media queries et le contrôle par l'utilisateur montre comment les respecter tout en gardant un moyen visible de choisir une apparence.

Ces habitudes coûtent peu et réduisent la quantité de données d'affichage et de préférences qui quittent la page.

Tester côté auteur est simple. Ouvrez le panneau réseau de votre navigateur, changez le jeu de couleurs ou le réglage de mouvement réduit dans le système d'exploitation, et observez quelles requêtes changent. Toute requête qui varie selon une préférence mérite un second regard : demandez-vous si la conception en a besoin, si le même résultat est possible avec une seule ressource, et si l'hôte qui la reçoit vous appartient. Refaites cette vérification quand une feuille de style ou un widget tiers est ajouté, car un composant intégré peut introduire des requêtes conditionnelles que le reste du site n'a jamais utilisées.

Les réglages d'accessibilité demandent une attention particulière des deux côtés. Le mouvement réduit, le contraste élevé et les couleurs forcées existent parce que certaines personnes ne peuvent pas utiliser confortablement une page sans eux. Une configuration de confidentialité qui les remplace pour ressembler à tout le monde peut rendre les sites plus difficiles à utiliser pour la personne devant le clavier, et un site qui les ignore pénalise directement ces personnes. Lorsque le navigateur avec lequel vous testez déclare des valeurs différentes de vos propres réglages, rappelez-vous que la différence ne vaut que pour cette session, et que vos vraies préférences restent dans le navigateur que vous utilisez au quotidien.

Ce que BotBrowser couvre et ce qu'il laisse de côté

La documentation de BotBrowser sur CSS Signal Consistency décrit les options concernées. Un lancement de base charge un profil, et le jeu de couleurs ainsi que la source de l'écran peuvent être fixés explicitement.

chrome --bot-profile="path/to/profile.enc" \
       --bot-color-scheme=dark \
       --bot-screen=profile

--bot-color-scheme accepte light ou dark. --bot-screen=profile utilise les propriétés d'écran définies par le profil, comme la profondeur de couleur et les dimensions, à la place des valeurs de l'écran de la machine hôte. Les deux réglages sont facultatifs.

Choisissez d'abord le profil, car les valeurs CSS d'une session en découlent. Un profil décrit un seul appareil, donc prenez-en un dont la plateforme et le type d'appareil correspondent au travail que vous faites, et confirmez le pointeur et le survol avec les vérifications ci-dessus. Modifier ensuite le jeu de couleurs ou la source d'écran ajuste la présentation à l'intérieur de ce profil. Cela ne transforme pas un profil de bureau en téléphone.

BotBrowser peut maintenir les valeurs de média CSS et les valeurs d'affichage associées alignées sur le profil chargé : le jeu de couleurs suit le profil et --bot-color-scheme, et les valeurs d'écran comme la profondeur de couleur et les dimensions suivent le profil, de sorte qu'une règle @media et matchMedia() déclarent les mêmes valeurs cohérentes avec le profil au lieu de celles de la machine hôte. Cela vous aide à confirmer que la voie de la feuille de style et celle du script concordent pour un profil donné, et que la réponse ne change pas d'une session à l'autre. Les limites sont tout aussi importantes. BotBrowser ne peut pas contrôler ce que la feuille de style d'un site demande ou enregistre, ne peut pas rendre une session anonyme ni impossible à relier, et ne remplace pas vos propres réglages d'accessibilité, comme le mouvement réduit ou le contraste.

Questions fréquentes

Une seule fonctionnalité CSS identifie-t-elle une personne ?

Non. Les fonctionnalités isolées apportent généralement peu d'information ; le risque vient des combinaisons et des contradictions entre CSS et JavaScript.

Faut-il standardiser toutes les préférences ?

Pas automatiquement. Des valeurs fixes réduisent la variation, mais peuvent créer un groupe reconnaissable et remplacer des réglages d'accessibilité.

Que faut-il relever pendant un test de cohérence ?

Notez le profil, les options de lancement explicites, le résultat CSS, le résultat du script et la date de session afin de reproduire la comparaison.

Conclusion pratique

Pour un contrôle reproductible, choisissez un profil cohérent, fixez le jeu de couleurs ou la source d'écran si nécessaire, comparez CSS et JavaScript sur la même page de test et répétez le contrôle lors de sessions ultérieures. Corrigez les écarts avant d'ajuster d'autres signaux d'empreinte, en gardant à l'esprit que BotBrowser aligne les valeurs mais ne contrôle pas la collecte du site et ne fournit pas l'anonymat.

Sources publiques

#Css#fingerprinting#Media-Queries#confidentialité

Cet article fait partie du guide : Qu'est-ce qu'une empreinte de navigateur ?

Faites passer BotBrowser de la recherche à la production

Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.