Empreinte

Fingerprinting CPU : proteger hardwareConcurrency

Comment navigator.hardwareConcurrency revele le nombre de coeurs CPU pour l'empreinte, et les techniques pour controler le rapport de coeurs dans tous les contextes.

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.

Introduction

La propriete navigator.hardwareConcurrency retourne le nombre de coeurs CPU logiques disponibles pour le navigateur. Elle a ete concue pour aider les applications web a optimiser les charges de travail paralleles, permettant au code JavaScript de decider combien de Web Workers lancer ou comment partitionner les taches de traitement de donnees. Mais cette meme propriete revele des informations materielles qui contribuent a l'empreinte de navigateur. Un appareil avec 6 coeurs logiques est bien moins courant qu'un avec 8, et un serveur avec 64 coeurs se demarque immediatement. Parce que le nombre de coeurs CPU est stable, facile a interroger et varie selon les configurations materielles, il est devenu un composant standard dans les systemes de pistage par empreinte. Cet article explique comment le nombre de coeurs CPU contribue a l'empreinte, pourquoi les simples remplacements creent des problemes, et comment BotBrowser fournit un rapport de nombre de coeurs coherent via son systeme de profils.

Impact sur la vie privee

Le nombre de coeurs CPU peut sembler etre un signal d'empreinte de faible valeur, mais sa contribution est significative en contexte. La valeur de tout attribut d'empreinte depend de sa distribution dans la population. Selon les donnees du projet AmIUnique, navigator.hardwareConcurrency possede environ 4,5 bits d'entropie, ce qui signifie qu'il peut distinguer environ 23 groupes differents. Bien que 23 groupes ne semblent pas beaucoup, chaque bit d'entropie double approximativement le pouvoir d'identification lorsqu'il est combine avec d'autres signaux.

La distribution est fortement asymetrique. Les valeurs de 4 et 8 representent la majorite des navigateurs de bureau. Les valeurs de 2 (machines anciennes, Chromebooks d'entree de gamme), 6 (certaines configurations Intel), 12 (processeurs Ryzen 5), 16 (ordinateurs de bureau haut de gamme) et tout ce qui depasse 16 sont progressivement plus rares. Une machine rapportant 24, 32 ou 64 coeurs est presque certainement un serveur ou une station de travail, ce qui est extremement rare dans les populations de navigation normales.

Les appareils mobiles ajoutent une differenciation supplementaire. La plupart des telephones rapportent 4 ou 8 coeurs, mais des familles SoC specifiques (Snapdragon, Exynos, MediaTek, Apple Silicon) associent des nombres de coeurs specifiques a d'autres proprietes identifiables. Un telephone avec un hardwareConcurrency de 8 combine avec un modele de user agent specifique reduit l'appareil a une poignee de modeles.

Le probleme de vie privee est amplifie parce que hardwareConcurrency est disponible dans tous les contextes d'execution : thread principal, workers dedies, workers partages et service workers. Il ne necessite aucune permission et ne peut pas etre bloque sans casser les applications web legitimes qui l'utilisent pour l'optimisation des performances.

Contexte technique

Comment fonctionne hardwareConcurrency

La propriete navigator.hardwareConcurrency retourne un entier long non signe representant le nombre de processeurs logiques disponibles. "Processeurs logiques" signifie les coeurs physiques multiplies par les threads par coeur (par exemple, un CPU 4 coeurs avec hyperthreading rapporte 8).

console.log(navigator.hardwareConcurrency); // ex: 8

La valeur est egalement disponible dans les contextes worker :

// Dans un Web Worker
console.log(self.navigator.hardwareConcurrency); // meme valeur

Pourquoi la valeur varie

Plusieurs facteurs determinent ce que hardwareConcurrency retourne :

  • Materiel physique. Le nombre de coeurs et de threads du CPU est determine par le modele de processeur. Les processeurs Intel i5 ont generalement 4 a 6 coeurs avec hyperthreading. Les processeurs AMD Ryzen 7 ont 8 coeurs avec SMT. Les puces Apple M-series ont des nombres de coeurs variables entre les clusters efficacite et performance.
  • Virtualisation. Les machines virtuelles rapportent le nombre de vCPU alloues, qui peut differer de la machine hote. Une VM avec 2 vCPU rapporte un hardwareConcurrency de 2, quel que soit le nombre reel de coeurs de l'hote.
  • Ordonnancement OS. Certains systemes d'exploitation permettent de limiter le nombre de processeurs visibles. Les environnements de conteneurs (Docker, LXC) peuvent restreindre la visibilite du CPU.
  • Implementation du navigateur. La plupart des navigateurs rapportent la valeur brute de l'OS. Certains ont experimente le plafonnement ou le regroupement de la valeur, mais Chromium rapporte actuellement le nombre reel.

Correlation avec d'autres signaux

Le nombre de coeurs CPU n'existe pas isolement. Les systemes de pistage le recoupent avec :

  • navigator.deviceMemory - une machine 2 coeurs avec 8 Go de RAM est plausible, une machine 2 coeurs avec 0,25 Go de RAM suggere une classe d'appareil differente.
  • navigator.platform - une plateforme "Linux x86_64" avec 4 coeurs se reduit a du materiel specifique. "Linux armv81" avec 8 coeurs suggere un serveur ARM specifique ou un telephone.
  • User agent. La version du navigateur et la version de l'OS contraignent quels nombres de coeurs sont realistes.
  • Timing des performances. Les performances d'execution parallele reelle (mesurees par des canaux lateraux de timing) peuvent etre comparees au nombre de coeurs rapporte.

Une incoherence entre le nombre de coeurs rapporte et les performances paralleles reelles est un signal fort que la valeur a ete alteree.

Approches de protection courantes et leurs limites

Remplacer manuellement hardwareConcurrency via une extension de navigateur ou une injection JavaScript est l'approche la plus courante. Cela change la valeur retournee mais cree plusieurs problemes :

  1. Incoherence de performance. Si vous rapportez 4 coeurs mais que votre machine reelle en a 16, les charges de travail paralleles (SharedArrayBuffer, Web Workers) s'executent plus rapidement qu'une machine 4 coeurs ne le permettrait. Cet ecart de timing est mesurable.
  2. Detection de prototype. Les remplacements JavaScript sur navigator.hardwareConcurrency peuvent etre detectes en inspectant le descripteur de propriete, en verifiant la chaine de prototype, ou en mesurant le temps d'execution du getter.
  3. Lacunes dans le contexte worker. Certaines extensions ne modifient que l'objet navigator du thread principal sans patcher les contextes worker. Un script de pistage s'executant dans un Web Worker voit la valeur reelle.

Randomiser la valeur cree des configurations irrealistes. Une valeur aleatoire de 7 ou 13 ne correspond a aucune architecture CPU reelle. Les valeurs doivent etre des puissances de 2 ou des configurations connues specifiques pour etre plausibles.

Utiliser une valeur commune fixe (comme toujours rapporter 8) est mieux que la randomisation mais reste risque si cela contredit d'autres signaux. Rapporter 8 coeurs alors que le user agent revendique un telephone Android livre avec un SoC 4 coeurs est incoherent.

L'exigence fondamentale est que le nombre de coeurs rapporte doit etre en coherence interne avec toutes les autres proprietes de l'appareil et ne doit pas contredire les caracteristiques de performance observables.

L'approche au niveau du moteur de BotBrowser

BotBrowser controle navigator.hardwareConcurrency au niveau du moteur Chromium via son systeme de profils d'empreinte. Cette approche offre plusieurs avantages par rapport aux modifications au niveau JavaScript.

Valeurs pilotees par le profil

Chaque profil d'empreinte BotBrowser specifie une valeur hardwareConcurrency qui correspond a la configuration CPU reelle de l'appareil profile. Un profil de bureau Windows 10 avec un Intel i7 rapporte 8 ou 16 coeurs. Un profil de telephone Android avec un Snapdragon 888 rapporte 8 coeurs. Les valeurs sont tirees de configurations d'appareils reels, pas de nombres arbitraires.

Coherence dans tous les contextes

Parce que le controle se fait au niveau du moteur, chaque contexte rapporte la meme valeur :

  • Thread principal navigator.hardwareConcurrency
  • Worker dedie self.navigator.hardwareConcurrency
  • Worker partage self.navigator.hardwareConcurrency
  • Service Worker self.navigator.hardwareConcurrency

Il n'y a pas de lacune ou un contexte retourne la valeur reelle tandis qu'un autre retourne la valeur du profil.

Coherence inter-signaux

La valeur hardwareConcurrency dans le profil fait partie d'une identite d'appareil complete. Elle s'aligne avec :

  • La chaine user agent et la plateforme
  • La valeur deviceMemory
  • La resolution d'ecran et les autres signaux materiels
  • La marque et la version du navigateur

Cela garantit qu'aucune verification de recoupement ne revele une incoherence.

Aucun artefact JavaScript

Parce que la valeur est definie au niveau du moteur, il n'y a pas de descripteurs de propriete modifies, pas de getters non natifs et pas de differences de timing par rapport a un acces de propriete natif. La propriete se comporte exactement comme elle le ferait sur le materiel profile.

Configuration et utilisation

Chargement de profil de base

chrome --bot-profile="/path/to/profile.enc" \
       --user-data-dir="$(mktemp -d)"

Le profil determine automatiquement le nombre de coeurs rapporte.

Verification de la valeur

// Dans la console du navigateur ou un script d'automatisation
console.log(navigator.hardwareConcurrency);
// Retourne le nombre de coeurs du profil, pas votre materiel reel

Integration Playwright

const { chromium } = require('playwright');

const browser = await chromium.launch({
  executablePath: '/path/to/botbrowser/chrome',
  args: [
    '--bot-profile=/path/to/profile.enc'
  ]
});

const page = await browser.newPage();
await page.goto('https://example.com');

const cores = await page.evaluate(() => navigator.hardwareConcurrency);
console.log(`Reported cores: ${cores}`);

// Verifier que le contexte worker correspond
const workerCores = await page.evaluate(() => {
  return new Promise(resolve => {
    const blob = new Blob([
      'postMessage(self.navigator.hardwareConcurrency)'
    ], { type: 'application/javascript' });
    const worker = new Worker(URL.createObjectURL(blob));
    worker.onmessage = e => resolve(e.data);
  });
});
console.log(`Worker cores: ${workerCores}`);
// Les deux valeurs devraient etre identiques

Integration Puppeteer

const puppeteer = require('puppeteer');

const browser = await puppeteer.launch({
  executablePath: '/path/to/botbrowser/chrome',
  defaultViewport: null,
  args: [
    '--bot-profile=/path/to/profile.enc'
  ]
});

const page = await browser.newPage();
await page.goto('https://example.com');

const cores = await page.evaluate(() => navigator.hardwareConcurrency);
console.log(`Reported cores: ${cores}`);

Verification

Verification de la valeur. Interrogez navigator.hardwareConcurrency et confirmez qu'il correspond a la valeur attendue pour votre profil charge. Il ne devrait pas refleter votre materiel reel.

Coherence worker. Creez un Web Worker et interrogez self.navigator.hardwareConcurrency a l'interieur. La valeur devrait correspondre exactement au thread principal.

Coherence inter-proprietes. Verifiez que le nombre de coeurs est plausible pour la plateforme, le user agent et la memoire de l'appareil du profil. Une configuration 8 coeurs avec 8 Go de memoire et un user agent Windows 10 est realiste. Une configuration 64 coeurs avec un user agent Android ne l'est pas.

Stabilite inter-sessions. Interrogez la valeur sur plusieurs sessions avec le meme profil. Elle devrait etre identique a chaque fois.

Bonnes pratiques

  • Utilisez un profil complet. N'essayez pas de remplacer juste hardwareConcurrency isolement. La valeur doit etre coherente avec toutes les autres proprietes de l'appareil. Les profils BotBrowser l'assurent automatiquement.
  • Choisissez des profils avec des configurations realistes. Les valeurs courantes (4, 8) se fondent mieux que les valeurs inhabituelles (6, 12, 24). Selectionnez des profils adaptes a votre cas d'utilisation cible.
  • Testez dans les contextes worker. Verifiez toujours que les requetes basees sur les workers retournent la meme valeur que le thread principal.
  • Evitez de remplacer manuellement le nombre de coeurs. Les profils BotBrowser sont concus avec des configurations coherentes en interne. Changer manuellement le nombre de coeurs sans ajuster les autres proprietes cree des incoherences detectables.

FAQ

Q : Quelles sont les valeurs de hardwareConcurrency les plus courantes ? R : Sur bureau, 4 et 8 sont de loin les plus courantes, representant ensemble plus de 70 % des navigateurs. Sur mobile, 4 et 8 dominent egalement. Les valeurs de 2, 6, 10, 12, 16 et superieures sont progressivement plus rares.

Q : Un site web peut-il mesurer mon nombre reel de coeurs independamment de ce que hardwareConcurrency rapporte ? R : En theorie, un site pourrait tenter de mesurer les performances d'execution parallele en utilisant SharedArrayBuffer et des timers haute resolution. En pratique, les mesures de securite du navigateur (precision reduite des timers, exigences COOP/COEP) rendent cela difficile. Le controle au niveau du moteur de BotBrowser aide egalement, car la valeur rapportee s'aligne avec le comportement attendu du profil.

Q : Est-ce que hardwareConcurrency change avec les mises a jour du navigateur ? R : Non. La valeur reflete la configuration materielle et OS, pas la version du navigateur. Elle reste stable entre les mises a jour du navigateur sur la meme machine.

Q : navigator.hardwareConcurrency est-il disponible dans tous les navigateurs ? R : Oui. Il est pris en charge dans tous les navigateurs majeurs (Chrome, Firefox, Safari, Edge) et a ete standardise dans la specification HTML.

Q : Pourquoi certaines VM rapportent-elles des nombres de coeurs differents de l'hote ? R : Les machines virtuelles rapportent le nombre de vCPU alloues par l'hyperviseur. Un hote avec 16 coeurs pourrait n'allouer que 2 ou 4 vCPU a une VM, ce qui est ce que hardwareConcurrency rapporte depuis l'interieur de la VM.

Q : Le nombre de coeurs affecte-t-il les performances des Web Workers dans BotBrowser ? R : BotBrowser controle la valeur rapportee, pas l'ordonnancement CPU reel. Les coeurs reels de votre materiel sont toujours utilises pour l'execution. La valeur du profil n'affecte que ce que JavaScript voit lors de l'interrogation de la propriete.

Resume

navigator.hardwareConcurrency est une propriete simple qui retourne un seul nombre, mais sa valeur contribue de maniere significative a l'empreinte de navigateur, surtout lorsqu'elle est combinee avec d'autres signaux materiels. BotBrowser controle cette valeur au niveau du moteur Chromium via son systeme de profils, assurant un rapport coherent dans tous les contextes d'execution JavaScript. Parce que la valeur fait partie d'un profil d'appareil complet, elle s'aligne avec le user agent, la plateforme, la memoire et tous les autres signaux d'identite.

Pour des sujets connexes, consultez Qu'est-ce que l'empreinte de navigateur, Protection des proprietes Navigator, Protection ecran et fenetre et Comportement deterministe du navigateur.

#Cpu#fingerprinting#hardwareConcurrency#Privacy

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.