Retour au Centre de connaissances
Empreinte

Les groupes de signaux de CreepJS et leur combinaison

Une sonde sur CreepJS : neuf motifs indépendants forment une chaîne de décision ordonnée, et un seul ne se détecte qu’en comparant deux groupes.

BotBrowser Team

Documentation

Vous voulez la documentation structurée pour Empreinte ?

Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.

BotBrowser permet de rejouer un fixture de même origine autorisé sous un profil déclaré et de garder une trace bornée de ce que chaque groupe de sondage a rapporté, mais il ne peut pas faire concorder un groupe avec un autre qui décrit une surface différente, ne peut pas masquer un groupe qui a été bloqué plutôt que répondu, ni changer l’ordre dans lequel une chaîne de décision nomme ses raisons. Cette revue lit CreepJS depuis son code public, reproduit sa décision à neuf motifs et consigne quels motifs un seul groupe peut activer, lequel exige que deux groupes se contredisent avant de se déclencher, pourquoi l’ordre des neuf décide de la raison rapportée, et ce que les deux motifs de serveur peuvent apporter depuis l’intérieur d’une page.

Résumé

  • CreepJS exécute plus de vingt groupes de sondage et les réduit à une chaîne de décision de neuf bits, dans un ordre fixe, avec un résumé par groupe.
  • Un profil propre n’active aucun bit : la sonde imprime clean -> botHash=000000000 set=0 badBot=none.
  • Quatre motifs sont activés par un seul groupe : une portée de Worker qui a menti, une version de fonctionnalités qui ne correspond pas, un Function.prototype.toString remplacé, et une portée de Worker bloquée.
  • La portée bloquée est le signal individuel le moins coûteux, parce qu’il se déclenche même quand rien n’a menti : worker-blocked -> botHash=000000100.
  • Un motif exige deux groupes : une plateforme de polices qui contredit le système qu’affirme l’agent utilisateur du Worker.
  • Cette contradiction entre groupes n’a pas de bit propre ; elle alimente le motif de mensonge extrême, donc font-vs-ua-feeds-extreme -> botHash=000010000 badBot=extremeLieCount.
  • L’ordre des neuf décide de la raison rapportée : avec quatre bits actifs la sonde imprime botHash=110100100 badBot=liedWorkerScope, et inverser l’ordre d’entrée ne change rien.
  • Deux motifs sont calculés sur un serveur, donc depuis une page ils valent toujours zéro : server-bits -> positions=6,8 always=00.

Sommaire

Le premier panneau montre un profil propre produisant neuf bits à zéro. Le deuxième montre quatre motifs d’un seul groupe activant un bit à des positions différentes. Le troisième montre une plateforme de polices qui contredit l’agent utilisateur du Worker, ce qui active le bit de mensonge extrême plutôt qu’un bit propre. Le quatrième montre quatre bits actifs à la fois avec la raison rapportée prise au plus à gauche, et les deux positions de serveur toujours à zéro.

Ce que sont les neuf bits et d’où ils viennent

CreepJS n’émet pas un score. Il exécute un ensemble de groupes de sondage indépendants, condense la sortie de chaque groupe en un résumé propre, puis réduit neuf motifs précis à une chaîne de décision ordonnée. Les neuf viennent de groupes différents, et c’est tout le dispositif :

clean -> botHash=000000000 set=0 badBot=none

Neuf zéros pour un navigateur qui n’a rien déclenché. Chaque position nomme un motif pris à un endroit différent de la page : le rapport de la portée de Worker elle-même, la version de plateforme qu’implique une mesure de polices, si Function.prototype.toString se comporte encore comme un natif, si une liste de fonctionnalités correspondait à la version déclarée, un nombre extrême de mensonges individuels, un excès d’empreintes lâches, si la portée de Worker a été bloquée, un score de mélange à la foule, et un motif de serveur.

Une inadéquation de plateforme entre deux groupes est le cas que pourquoi un seul signal bizarre ne condamne pas note autrement qu’une seule surface mince. Les résumés par groupe et la chaîne de décision répondent à des questions différentes. Un résumé dit « ces deux exécutions du groupe canvas ont produit les mêmes octets », ce qui est une affirmation de stabilité sur une surface. La chaîne dit « ces neuf conditions nommées étaient vraies », ce qui est une affirmation sur la page entière. Un profil peut avoir un résumé canvas parfaitement stable et activer quand même un bit, parce que le bit vient d’un autre groupe.

Cette séparation mérite d’être retenue en lisant n’importe quel rapport d’empreintes. Un résumé de groupe stable est souvent pris pour un bon résultat, et ce n’est pas la même affirmation. La stabilité signifie que le groupe est reproductible ; elle ne dit rien sur la concordance de sa sortie avec celle d’un autre groupe.

Quels groupes activent un bit seuls

Quatre des neuf motifs sont activés par un groupe sans aucune comparaison. La sonde exécute chacun contre une base propre :

worker-scope-lied -> botHash=100000000 set=1 badBot=liedWorkerScope
features-version-lied -> botHash=000100000 set=1 badBot=outsideFeaturesVersion
proxy-toString -> botHash=001000000 set=1 badBot=functionToStringHasProxy
worker-blocked -> botHash=000000100 set=1 badBot=workerScopeIsBlocked

Chaque ligne active exactement un bit, et chaque bit est à une position différente, donc la chaîne elle-même enregistre quel groupe a parlé. Une portée de Worker qui a rapporté quelque chose d’incohérent active la première position. Une liste de fonctionnalités qui ne correspondait pas à la version déclarée active la quatrième. Un Function.prototype.toString qui ne se comporte plus comme un natif active la troisième. Une portée de Worker qui n’a pas pu être créée active la septième.

Un Worker qui rapporte une valeur différente de la page principale est l’un des rares signaux qu’aucun client légitime ne produit, et intégrité des API entre realms le consigne en détail. Le cas de la portée bloquée mérite une pause, parce qu’il se déclenche sans aucun mensonge. Rien n’a rapporté une valeur fausse ; la page n’a simplement pas obtenu de portée de Worker qui réponde. Cela en fait le signal individuel le moins coûteux de tout l’ensemble : une page peut être parfaitement cohérente sur chaque surface qu’elle expose et activer quand même ce bit en n’en exposant pas une. Tout test qui ne lit que les surfaces ayant répondu le manquera.

La position de Function.prototype.toString est celle qu’une page peut influencer le plus directement, et l’analyse de fonctions natives remplacées et ce que voit une liste de toString couvre quelles modifications survivent à ce contrôle et quels emballages le passent. La chaîne ici enregistre seulement que le motif s’est déclenché ; elle ne dit pas quelle modification l’a causé.

Quel bit exige que deux groupes se contredisent

Un motif ne peut pas être évalué depuis un seul groupe, parce qu’il existe précisément pour en comparer deux. La sonde lui donne un agent utilisateur et une plateforme de polices et enregistre ce que la comparaison décide :

cross:agree-win -> uaOS=WINDOWS fontOS=WINDOWS fontOSBad=false
cross:agree-mac -> uaOS=APPLE fontOS=APPLE fontOSBad=false
cross:disagree-ua-mac-font-win -> uaOS=APPLE fontOS=WINDOWS fontOSBad=true
cross:disagree-ua-win-font-mac -> uaOS=WINDOWS fontOS=APPLE fontOSBad=true
cross:android-with-mac-font -> uaOS=LINUX fontOS=APPLE fontOSBad=true

Quand les deux groupes nomment la même famille de plateforme, rien ne se déclenche. Quand ils nomment des familles différentes, la comparaison se déclenche dans les deux sens, et elle se déclenche aussi pour un agent utilisateur Android portant une plateforme de polices qui se lit comme Apple. Le sens n’importe pas, seule la contradiction, ce qui en fait un contrôle de cohérence et non un seuil sur une valeur.

Le cas Android est le plus parlant pour un déploiement. Un profil qui rapporte un agent utilisateur Android alors que ses mesures de polices se résolvent comme une famille Apple de bureau active ce motif bien qu’aucun des deux groupes ne paraisse faux isolément. L’agent utilisateur est une chaîne Android plausible et la plateforme de polices une chaîne Apple plausible ; ils ne peuvent simplement pas être vrais du même appareil.

Ce que le motif fait de cette contradiction est la partie facile à manquer :

font-vs-ua-feeds-extreme -> botHash=000010000 set=1 badBot=extremeLieCount

La contradiction entre groupes n’a pas de bit propre. Elle alimente la cinquième position, le motif de mensonge extrême, à côté d’un nombre absolu de mensonges individuels. Un rapport qui dit que le bit de mensonge extrême s’est activé peut donc signifier qu’une page a accumulé un très grand nombre de petites incohérences, ou qu’une seule contradiction entre groupes a suffi. Le bit ne distingue pas ces deux cas, et qui le lit doit revenir à la sortie par groupe pour savoir lequel.

Ce choix de conception est délibéré et il a un coût. Ranger une contradiction qualitative dans le même bit qu’un compte quantitatif fait perdre à la chaîne une information que les groupes sous-jacents possèdent encore. La chaîne est un résumé, et le résumé est lacunaire d’une manière précise et documentée.

Pourquoi l’ordre des bits compte

Les neuf positions ne sont pas équivalentes, parce que la décision rapporte le premier bit actif comme sa raison. La sonde active quatre motifs à la fois puis répète les mêmes quatre dans un autre ordre d’entrée :

many-bits -> botHash=110100100 set=4 badBot=liedWorkerScope
many-bits-reversed-input -> botHash=110100100 set=4 badBot=liedWorkerScope

Quatre bits actifs et la raison rapportée est toujours celle du plus à gauche. L’ordre d’entrée ne change ni la chaîne ni la raison, ce qui signifie que l’ordre vit dans la liste fixe et non dans l’ordre d’achèvement des groupes. Une page qui active quatre motifs n’est informée que d’un seul, et c’est celui qui est le plus à gauche.

La conséquence pratique est qu’une seule raison rapportée ne signifie pas un seul constat. Un rapport qui nomme une raison à côté de quatre bits actifs vous dit qu’il y en a quatre, et choisit de montrer le plus à gauche. Qui ne lit que la raison sous-estimera ce que la page a réellement fait.

Deux des neuf positions ne peuvent pas être activées depuis l’intérieur d’une page :

server-bits -> positions=6,8 always=00

Les positions des empreintes lâches excessives et du mélange à la foule sont calculées là où beaucoup de sessions peuvent être comparées, donc un navigateur qui s’évalue lui-même rapporte zéro pour les deux quoi que fasse la page. Une exécution côté page couvre donc sept des neuf motifs, et les deux qu’elle ne couvre pas sont ceux qui exigent une population plutôt qu’une session.

Les chaînes à un seul bit disent la même chose sur la granularité :

single:liedWorkerScope -> 100000000 position=1
single:functionToStringHasProxy -> 001000000 position=3
single:workerScopeIsBlocked -> 000000100 position=7

Trois constats différents, trois chaînes différentes, chacune avec exactement un bit. La chaîne est précise sur le motif déclenché et muette sur sa force. Une page qui active la position un parce qu’une portée de Worker a rapporté une valeur fausse et une page qui l’active parce que la portée s’est contredite en six points produisent la même chaîne.

La table des versions de Windows dont dépend le motif de version de plateforme montre pourquoi ce motif est grossier lui aussi :

win-release:0.3.0 -> 8.1
win-release:8.0.0 -> 10 (1903|1909)
win-release:13.0.0 -> 11
win-release:15.0.0 -> 11

Chaque version de plateforme à partir de 13 correspond à Windows 11, donc le motif ne distingue pas une compilation de Windows 11 d’une autre. C’est un contrôle au niveau de la famille, ce qui le rend utile pour repérer une inadéquation et inutile pour identifier une compilation.

Consigner une lecture de recoupement

Une entrée rédigée rend les quatre champs concrets. Une exécution qui a renvoyé botHash=110100100 avec badBot=liedWorkerScope est consignée comme la chaîne plus le commit plus la sortie par groupe de la portée de Worker, de la liste de fonctionnalités, du contrôle Function.prototype.toString et de la mesure de polices, et elle nomme les deux positions non évaluées. Un lecteur peut alors voir que quatre motifs se sont déclenchés, que la raison rapportée est la position un, et que la comparaison polices contre agent utilisateur a contribué par la position cinq plutôt que par un bit propre.

Une lecture de recoupement étaye une affirmation bornée : cette version de la bibliothèque, ces groupes ont produit cette chaîne de décision. Quatre champs la gardent vérifiable :

  1. Le commit de la bibliothèque et la liste ordonnée des motifs, parce que les positions et leur sens sont du code, et un réordonnancement change silencieusement la raison rapportée.
  2. La sortie par groupe à côté de la chaîne de décision, parce que la chaîne réunit une contradiction qualitative et un compte quantitatif dans un bit et que les groupes gardent encore la distinction.
  3. Quels motifs ont été évalués et lesquels ne l’ont pas été, parce que deux des neuf exigent une population et valent toujours zéro dans une exécution côté page.
  4. Les bits actifs sous forme de chaîne plutôt qu’un compte, parce que quatre bits avec une raison rapportée et un seul bit sont des constats différents et qu’un compte ne les sépare pas.

Sources publiques

Conclusion pratique

Lisez un résultat de CreepJS comme une chaîne ordonnée de motifs nommés plutôt qu’un score, parce que la chaîne dit quel groupe a parlé et le score ne dirait que combien. Traitez une portée de Worker bloquée comme un constat à part entière même quand rien n’a menti, puisque c’est le motif individuel le moins coûteux et le plus facile à manquer. Attendez-vous à ce que le motif polices contre agent utilisateur se déclenche dans les deux sens, et rappelez-vous qu’il alimente le bit de mensonge extrême plutôt qu’un bit propre, donc la raison seule ne distingue pas une inadéquation qualitative d’un grand nombre de petites. Pour le contrôle d’intégrité dont dépend l’une des neuf positions, lisez fonctions natives remplacées et ce que voit une liste de toString ; pour la façon dont une décision bâtie sur plusieurs couches est notée et filtrée, lisez pourquoi un seul signal bizarre ne condamne pas.

#CreepJS#Groupes D’empreintes#Recoupement#Signaux Sans Tête#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.