From 40edebb925e9a7056f69217c830386d6526ebf75 Mon Sep 17 00:00:00 2001 From: Jake Writer Date: Fri, 25 Sep 2026 21:43:44 -0600 Subject: [PATCH] chore(data): drop the 23 presets whose GPU has no WebGL data A preset records only its GPU's name. The WebGL parameters, extensions and shader precision behind it have to come from somewhere, and for these 23 nothing Camoufox has describes the GPU: fpgen has never seen Firefox report it on that OS. So each launch paired the name with another device's parameters, a mismatch any WebGL fingerprinter can see. They were: - Windows on ARM (Adreno 650); - Direct3D 10-level GPUs (vs_4_0/vs_4_1); - "Generic Renderer"; - 945GM and GTX 480 on macOS; - nouveau/Mesa buckets on Linux; - one Linux preset pairing NVIDIA's proprietary vendor string with the nouveau renderer name. scripts/clean-fingerprint-data.py now applies the rule, via a shared fingerprints.firefox_gpus(), and test_shipped_data asserts it. 374 presets remain, and every OS keeps its presets. ROADMAP.md lists capturing WebGL data for these GPUs, which would bring them back. Co-Authored-By: Claude Opus 5.5 --- ROADMAP.md | 5 + .../camoufox/fingerprint-presets-v150.json | 618 ------------------ pythonlib/camoufox/fingerprint-presets.json | 168 ----- pythonlib/camoufox/fingerprints.py | 16 + pythonlib/tests/test_shipped_data.py | 18 + scripts/clean-fingerprint-data.py | 13 +- 6 files changed, 49 insertions(+), 789 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 7beecdb..55ecf33 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -15,6 +15,11 @@ issue first. - **Draw more of the identity from fpgen.** Navigator, screen, window and headers come from fpgen today. Its fonts, voices, WebGL parameters, permissions, WebRTC capabilities and audio hashes are still drawn elsewhere. +- **Capture WebGL data for GPUs Camoufox cannot present yet**: Windows on ARM + (Adreno), Direct3D 10-level hardware, and the Mesa/nouveau and older Intel + Linux drivers. Presets naming them were dropped because nothing recorded + their WebGL parameters. They come back as normal identities once real + parameters for them exist. - **Reproducible identities across relaunches**: the same seed gives the same device, including its canvas and audio output ([#442](https://github.com/daijro/camoufox/issues/442), diff --git a/pythonlib/camoufox/fingerprint-presets-v150.json b/pythonlib/camoufox/fingerprint-presets-v150.json index 44d1de0..c055705 100644 --- a/pythonlib/camoufox/fingerprint-presets-v150.json +++ b/pythonlib/camoufox/fingerprint-presets-v150.json @@ -2881,76 +2881,6 @@ "Zuzana:cs-CZ:local" ] }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:149.0) Gecko/20100101 Firefox/149.0", - "platform": "MacIntel", - "hardwareConcurrency": 2, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1280, - "height": 800, - "colorDepth": 30, - "availWidth": 1280, - "availHeight": 800, - "devicePixelRatio": 2 - }, - "webgl": { - "unmaskedVendor": "Intel Inc.", - "unmaskedRenderer": "Intel 945GM, or similar" - }, - "speechVoices": [ - "Alex:en-US:local", - "Alice:it-IT:local", - "Alva:sv-SE:local", - "Amelie:fr-CA:local", - "Anna:de-DE:local", - "Carmit:he-IL:local", - "Damayanti:id-ID:local", - "Daniel:en-GB:local", - "Diego:es-AR:local", - "Ellen:nl-BE:local", - "Fiona:en-scotland:local", - "Fred:en-US:local", - "Ioana:ro-RO:local", - "Joana:pt-PT:local", - "Jorge:es-ES:local", - "Juan:es-MX:local", - "Kanya:th-TH:local", - "Karen:en-AU:local", - "Kyoko:ja-JP:local", - "Laura:sk-SK:local", - "Lekha:hi-IN:local", - "Luca:it-IT:local", - "Luciana:pt-BR:local", - "Maged:ar-SA:local", - "Mariska:hu-HU:local", - "Mei-Jia:zh-TW:local", - "Melina:el-GR:local", - "Milena:ru-RU:local", - "Moira:en-IE:local", - "Monica:es-ES:local", - "Nora:nb-NO:local", - "Paulina:es-MX:local", - "Rishi:en-IN:local", - "Samantha:en-US:local", - "Sara:da-DK:local", - "Satu:fi-FI:local", - "Sin-ji:zh-HK:local", - "Tessa:en-ZA:local", - "Thomas:fr-FR:local", - "Ting-Ting:zh-CN:local", - "Veena:en-IN:local", - "Victoria:en-US:local", - "Xander:nl-NL:local", - "Yelda:tr-TR:local", - "Yuna:ko-KR:local", - "Yuri:ru-RU:local", - "Zosia:pl-PL:local", - "Zuzana:cs-CZ:local" - ] - }, { "navigator": { "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:150.0) Gecko/20100101 Firefox/150.0", @@ -6895,76 +6825,6 @@ "Zuzana:cs-CZ:local" ] }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:149.0) Gecko/20100101 Firefox/149.0", - "platform": "MacIntel", - "hardwareConcurrency": 4, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1920, - "height": 1080, - "colorDepth": 30, - "availWidth": 1920, - "availHeight": 984, - "devicePixelRatio": 1 - }, - "webgl": { - "unmaskedVendor": "Intel Inc.", - "unmaskedRenderer": "Intel 945GM, or similar" - }, - "speechVoices": [ - "Alex:en-US:local", - "Alice:it-IT:local", - "Alva:sv-SE:local", - "Amelie:fr-CA:local", - "Anna:de-DE:local", - "Carmit:he-IL:local", - "Damayanti:id-ID:local", - "Daniel:en-GB:local", - "Diego:es-AR:local", - "Ellen:nl-BE:local", - "Fiona:en-scotland:local", - "Fred:en-US:local", - "Ioana:ro-RO:local", - "Joana:pt-PT:local", - "Jorge:es-ES:local", - "Juan:es-MX:local", - "Kanya:th-TH:local", - "Karen:en-AU:local", - "Kyoko:ja-JP:local", - "Laura:sk-SK:local", - "Lekha:hi-IN:local", - "Luca:it-IT:local", - "Luciana:pt-BR:local", - "Maged:ar-SA:local", - "Mariska:hu-HU:local", - "Mei-Jia:zh-TW:local", - "Melina:el-GR:local", - "Milena:ru-RU:local", - "Moira:en-IE:local", - "Monica:es-ES:local", - "Nora:nb-NO:local", - "Paulina:es-MX:local", - "Rishi:en-IN:local", - "Samantha:en-US:local", - "Sara:da-DK:local", - "Satu:fi-FI:local", - "Sin-ji:zh-HK:local", - "Tessa:en-ZA:local", - "Thomas:fr-FR:local", - "Ting-Ting:zh-CN:local", - "Veena:en-IN:local", - "Victoria:en-US:local", - "Xander:nl-NL:local", - "Yelda:tr-TR:local", - "Yuna:ko-KR:local", - "Yuri:ru-RU:local", - "Zosia:pl-PL:local", - "Zuzana:cs-CZ:local" - ] - }, { "navigator": { "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:149.0) Gecko/20100101 Firefox/149.0", @@ -8256,33 +8116,6 @@ "Microsoft Zira Desktop - English (United States):en-US:local" ] }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:150.0) Gecko/20100101 Firefox/150.0", - "platform": "Win32", - "hardwareConcurrency": 2, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1366, - "height": 768, - "colorDepth": 24, - "availWidth": 1366, - "availHeight": 728, - "devicePixelRatio": 1 - }, - "webgl": { - "unmaskedVendor": "Google Inc. (AMD)", - "unmaskedRenderer": "ANGLE (AMD, Radeon R9 200 Series Direct3D11 vs_4_0 ps_4_0), or similar" - }, - "speechVoices": [ - "Microsoft Helena - Spanish (Spain):es-ES:local", - "Microsoft Laura - Spanish (Spain):es-ES:local", - "Microsoft Pablo - Spanish (Spain):es-ES:local", - "Microsoft Helena Desktop - Spanish (Spain):es-ES:local", - "Microsoft Zira Desktop - English (United States):en-US:local" - ] - }, { "navigator": { "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:150.0) Gecko/20100101 Firefox/150.0", @@ -8534,33 +8367,6 @@ "Microsoft Zira Desktop - English (United States):en-US:local" ] }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:150.0) Gecko/20100101 Firefox/150.0", - "platform": "Win32", - "hardwareConcurrency": 4, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1920, - "height": 1080, - "colorDepth": 24, - "availWidth": 1920, - "availHeight": 1040, - "devicePixelRatio": 1 - }, - "webgl": { - "unmaskedVendor": "Google Inc. (Intel)", - "unmaskedRenderer": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_4_1 ps_4_1), or similar" - }, - "speechVoices": [ - "Microsoft Helena - Spanish (Spain):es-ES:local", - "Microsoft Laura - Spanish (Spain):es-ES:local", - "Microsoft Pablo - Spanish (Spain):es-ES:local", - "Microsoft Helena Desktop - Spanish (Spain):es-ES:local", - "Microsoft Zira Desktop - English (United States):en-US:local" - ] - }, { "navigator": { "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:150.0) Gecko/20100101 Firefox/150.0", @@ -9588,32 +9394,6 @@ "Microsoft Zira Desktop - English (United States):en-US:local" ] }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:150.0) Gecko/20100101 Firefox/150.0", - "platform": "Win32", - "hardwareConcurrency": 4, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1366, - "height": 768, - "colorDepth": 24, - "availWidth": 1299, - "availHeight": 768, - "devicePixelRatio": 1 - }, - "webgl": { - "unmaskedVendor": "Google Inc. (Intel)", - "unmaskedRenderer": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_4_1 ps_4_1), or similar" - }, - "speechVoices": [ - "Microsoft Raul - Spanish (Mexico):es-MX:local", - "Microsoft Sabina - Spanish (Mexico):es-MX:local", - "Microsoft Sabina Desktop - Spanish (Mexico):es-MX:local", - "Microsoft Zira Desktop - English (United States):en-US:local" - ] - }, { "navigator": { "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:150.0) Gecko/20100101 Firefox/150.0", @@ -9810,29 +9590,6 @@ "Microsoft David Desktop - English (United States):en-US:local" ] }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:150.0) Gecko/20100101 Firefox/150.0", - "platform": "Win32", - "hardwareConcurrency": 2, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1680, - "height": 1050, - "colorDepth": 24, - "availWidth": 1680, - "availHeight": 1010, - "devicePixelRatio": 1 - }, - "webgl": { - "unmaskedVendor": "Google Inc. (NVIDIA)", - "unmaskedRenderer": "ANGLE (NVIDIA, NVIDIA GeForce 8800 GTX Direct3D11 vs_4_0 ps_4_0), or similar" - }, - "speechVoices": [ - "Microsoft Zira Desktop - English (United States):en-US:local" - ] - }, { "navigator": { "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:150.0) Gecko/20100101 Firefox/150.0", @@ -9887,26 +9644,6 @@ "Microsoft Zira Desktop - English (United States):en-US:local" ] }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0", - "platform": "Win32", - "hardwareConcurrency": 4, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1366, - "height": 768, - "colorDepth": 24, - "availWidth": 1366, - "availHeight": 720, - "devicePixelRatio": 1 - }, - "webgl": { - "unmaskedVendor": "Google Inc. (Intel)", - "unmaskedRenderer": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_4_1 ps_4_1), or similar" - } - }, { "navigator": { "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0", @@ -10893,33 +10630,6 @@ "Microsoft Zira Desktop - English (United States):en-US:local" ] }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0", - "platform": "Win32", - "hardwareConcurrency": 8, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1280, - "height": 800, - "colorDepth": 24, - "availWidth": 1280, - "availHeight": 752, - "devicePixelRatio": 1.5 - }, - "webgl": { - "unmaskedVendor": "Google Inc. (Unknown)", - "unmaskedRenderer": "ANGLE (Unknown, Generic Renderer Direct3D11 vs_5_0 ps_5_0), or similar" - }, - "speechVoices": [ - "Microsoft Hortense - French (France):fr-FR:local", - "Microsoft Julie - French (France):fr-FR:local", - "Microsoft Paul - French (France):fr-FR:local", - "Microsoft Hortense Desktop - French:fr-FR:local", - "Microsoft Zira Desktop - English (United States):en-US:local" - ] - }, { "navigator": { "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0", @@ -10976,33 +10686,6 @@ "Microsoft Zira Desktop - English (United States):en-US:local" ] }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0", - "platform": "Win32", - "hardwareConcurrency": 8, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1366, - "height": 768, - "colorDepth": 24, - "availWidth": 1366, - "availHeight": 720, - "devicePixelRatio": 1 - }, - "webgl": { - "unmaskedVendor": "Google Inc. (Unknown)", - "unmaskedRenderer": "ANGLE (Unknown, Adreno (TM) 650 Direct3D11 vs_5_0 ps_5_0), or similar" - }, - "speechVoices": [ - "Microsoft David - English (United States):en-US:local", - "Microsoft Mark - English (United States):en-US:local", - "Microsoft Zira - English (United States):en-US:local", - "Microsoft David Desktop - English (United States):en-US:local", - "Microsoft Zira Desktop - English (United States):en-US:local" - ] - }, { "navigator": { "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0", @@ -11436,85 +11119,6 @@ "Microsoft Zira Desktop - English (United States):en-US:local" ] }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0", - "platform": "Win32", - "hardwareConcurrency": 12, - "maxTouchPoints": 10 - }, - "screen": { - "width": 1440, - "height": 960, - "colorDepth": 24, - "availWidth": 1440, - "availHeight": 912, - "devicePixelRatio": 2 - }, - "webgl": { - "unmaskedVendor": "Google Inc. (Unknown)", - "unmaskedRenderer": "ANGLE (Unknown, Generic Renderer Direct3D11 vs_5_0 ps_5_0), or similar" - }, - "speechVoices": [ - "Microsoft David - English (United States):en-US:local", - "Microsoft Mark - English (United States):en-US:local", - "Microsoft Zira - English (United States):en-US:local", - "Microsoft David Desktop - English (United States):en-US:local", - "Microsoft Zira Desktop - English (United States):en-US:local" - ] - }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0", - "platform": "Win32", - "hardwareConcurrency": 4, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1366, - "height": 768, - "colorDepth": 24, - "availWidth": 1366, - "availHeight": 728, - "devicePixelRatio": 1 - }, - "webgl": { - "unmaskedVendor": "Google Inc. (Intel)", - "unmaskedRenderer": "ANGLE (Intel, Intel(R) HD Graphics Direct3D11 vs_4_0 ps_4_0), or similar" - }, - "speechVoices": [ - "Microsoft Raul - Spanish (Mexico):es-MX:local", - "Microsoft Sabina - Spanish (Mexico):es-MX:local", - "Microsoft Sabina Desktop - Spanish (Mexico):es-MX:local", - "Microsoft Zira Desktop - English (United States):en-US:local" - ] - }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0", - "platform": "Win32", - "hardwareConcurrency": 8, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1536, - "height": 864, - "colorDepth": 24, - "availWidth": 1536, - "availHeight": 816, - "devicePixelRatio": 1.25 - }, - "webgl": { - "unmaskedVendor": "Google Inc. (Unknown)", - "unmaskedRenderer": "ANGLE (Unknown, Adreno (TM) 650 Direct3D11 vs_5_0 ps_5_0), or similar" - }, - "speechVoices": [ - "Microsoft Daniel - Portuguese (Brazil):pt-BR:local", - "Microsoft Maria - Portuguese (Brazil):pt-BR:local", - "Microsoft Maria Desktop - Portuguese(Brazil):pt-BR:local", - "Microsoft Zira Desktop - English (United States):en-US:local" - ] - }, { "navigator": { "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0", @@ -12126,26 +11730,6 @@ } ], "linux": [ - { - "navigator": { - "userAgent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0", - "platform": "Linux x86_64", - "hardwareConcurrency": 8, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1920, - "height": 1080, - "colorDepth": 24, - "availWidth": 1920, - "availHeight": 1080, - "devicePixelRatio": 1 - }, - "webgl": { - "unmaskedVendor": "NVIDIA Corporation", - "unmaskedRenderer": "NVIDIA GeForce 8800 GTX, or similar" - } - }, { "navigator": { "userAgent": "Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0", @@ -12466,26 +12050,6 @@ "unmaskedRenderer": "NVIDIA GeForce GTX 980, or similar" } }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0", - "platform": "Linux x86_64", - "hardwareConcurrency": 2, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1368, - "height": 768, - "colorDepth": 24, - "availWidth": 1368, - "availHeight": 728, - "devicePixelRatio": 1 - }, - "webgl": { - "unmaskedVendor": "Mesa", - "unmaskedRenderer": "GeForce 8800 GTX, or similar" - } - }, { "navigator": { "userAgent": "Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0", @@ -12506,128 +12070,6 @@ "unmaskedRenderer": "Intel(R) HD Graphics, or similar" } }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (X11; Linux x86_64; rv:149.0) Gecko/20100101 Firefox/149.0", - "platform": "Linux x86_64", - "hardwareConcurrency": 2, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1366, - "height": 768, - "colorDepth": 24, - "availWidth": 1366, - "availHeight": 717, - "devicePixelRatio": 1 - }, - "webgl": { - "unmaskedVendor": "Intel Open Source Technology Center", - "unmaskedRenderer": "Intel(R) HD Graphics 400, or similar" - }, - "speechVoices": [ - "Catalan:ca:remote", - "Bishnupriya Manipuri:bpy:remote", - "Nahuatl (Classical):nci:remote", - "Dutch:nl:remote", - "Azerbaijani:az:remote", - "Kyrgyz:ky:remote", - "English (Great Britain):en:remote", - "Chinese (Cantonese):yue:remote", - "English (Lancaster):en:remote", - "Vietnamese (Northern):vi:remote", - "Amharic:am:remote", - "Gaelic (Irish):ga:remote", - "Latvian:lv:remote", - "Swahili:sw:remote", - "Afrikaans:af:remote", - "Malay:ms:remote", - "Tatar:tt:remote", - "Nepali:ne:remote", - "Serbian:sr:remote", - "Oriya:or:remote", - "Arabic:ar:remote", - "Interlingua:ia:remote", - "Italian:it:remote", - "Aragonese:an:remote", - "German:de:remote", - "Assamese:as:remote", - "Bengali:bn:remote", - "Georgian:ka:remote", - "Lithuanian:lt:remote", - "Danish:da:remote", - "English (Caribbean):en:remote", - "Papiamento:pap:remote", - "Chinese (Mandarin):cmn:remote", - "Bosnian:bs:remote", - "Guarani:gn:remote", - "Marathi:mr:remote", - "Persian:fa:remote", - "Hindi:hi:remote", - "Bulgarian:bg:remote", - "Lingua Franca Nova:lfn:remote", - "Hungarian:hu:remote", - "Icelandic:is:remote", - "Burmese:my:remote", - "Maltese:mt:remote", - "Esperanto:eo:remote", - "Portuguese (Portugal):pt:remote", - "Spanish (Spain):es:remote", - "Kurdish:ku:remote", - "Lojban:jbo:remote", - "Czech:cs:remote", - "Turkish:tr:remote", - "Tamil:ta:remote", - "Spanish (Latin America):es:remote", - "Indonesian:id:remote", - "Armenian (West Armenia):hy:remote", - "Kannada:kn:remote", - "Greek (Ancient):grc:remote", - "Armenian (East Armenia):hy:remote", - "Greenlandic:kl:remote", - "French (Switzerland):fr:remote", - "Norwegian Bokmål:nb:remote", - "Portuguese (Brazil):pt:remote", - "Urdu:ur:remote", - "Punjabi:pa:remote", - "Japanese:ja:remote", - "Romanian:ro:remote", - "Gujarati:gu:remote", - "Latin:la:remote", - "Polish:pl:remote", - "French (France):fr:remote", - "Slovenian:sl:remote", - "Malayalam:ml:remote", - "Russian:ru:remote", - "Croatian:hr:remote", - "Korean:ko:remote", - "Welsh:cy:remote", - "Slovak:sk:remote", - "poz/mi:mi:remote", - "English (Scotland):en:remote", - "Vietnamese (Southern):vi:remote", - "English (West Midlands):en:remote", - "Persian (Pinglish):fa:remote", - "Albanian:sq:remote", - "Finnish:fi:remote", - "English (Received Pronunciation):en:remote", - "Greek:el:remote", - "French (Belgium):fr:remote", - "Gaelic (Scottish):gd:remote", - "Telugu:te:remote", - "Konkani:kok:remote", - "Sindhi:sd:remote", - "Estonian:et:remote", - "Basque:eu:remote", - "Oromo:om:remote", - "English (America):en:remote", - "Swedish:sv:remote", - "Macedonian:mk:remote", - "Setswana:tn:remote", - "Sinhala:si:remote", - "Vietnamese (Central):vi:remote" - ] - }, { "navigator": { "userAgent": "Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0", @@ -12748,46 +12190,6 @@ "unmaskedRenderer": "Intel(R) HD Graphics, or similar" } }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (X11; Linux x86_64; rv:150.0) Gecko/20100101 Firefox/150.0", - "platform": "Linux x86_64", - "hardwareConcurrency": 2, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1366, - "height": 768, - "colorDepth": 24, - "availWidth": 1366, - "availHeight": 718, - "devicePixelRatio": 1 - }, - "webgl": { - "unmaskedVendor": "Intel Open Source Technology Center", - "unmaskedRenderer": "Intel(R) HD Graphics 400, or similar" - } - }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:149.0) Gecko/20100101 Firefox/149.0", - "platform": "Linux x86_64", - "hardwareConcurrency": 24, - "maxTouchPoints": 0 - }, - "screen": { - "width": 3072, - "height": 1728, - "colorDepth": 24, - "availWidth": 3072, - "availHeight": 1728, - "devicePixelRatio": 2 - }, - "webgl": { - "unmaskedVendor": "NVIDIA Corporation", - "unmaskedRenderer": "NVIDIA GeForce 8800 GTX, or similar" - } - }, { "navigator": { "userAgent": "Mozilla/5.0 (X11; Linux x86_64; rv:149.0) Gecko/20100101 Firefox/149.0", @@ -13419,26 +12821,6 @@ "unmaskedRenderer": "Intel(R) HD Graphics 400, or similar" } }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (X11; Linux x86_64; rv:149.0) Gecko/20100101 Firefox/149.0", - "platform": "Linux x86_64", - "hardwareConcurrency": 2, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1366, - "height": 768, - "colorDepth": 24, - "availWidth": 1366, - "availHeight": 735, - "devicePixelRatio": 1 - }, - "webgl": { - "unmaskedVendor": "Mesa", - "unmaskedRenderer": "Radeon HD 5850, or similar" - } - }, { "navigator": { "userAgent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:149.0) Gecko/20100101 Firefox/149.0", diff --git a/pythonlib/camoufox/fingerprint-presets.json b/pythonlib/camoufox/fingerprint-presets.json index 95ba132..f448235 100644 --- a/pythonlib/camoufox/fingerprint-presets.json +++ b/pythonlib/camoufox/fingerprint-presets.json @@ -208,25 +208,6 @@ "Zuzana:cs-CZ:local" ] }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:109.0) Gecko/20100101 Firefox/115.0", - "platform": "MacIntel", - "hardwareConcurrency": 4, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1280, - "height": 800, - "colorDepth": 30, - "availWidth": 1280, - "availHeight": 714 - }, - "webgl": { - "unmaskedVendor": "Intel Inc.", - "unmaskedRenderer": "Intel(R) HD Graphics" - } - }, { "navigator": { "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:147.0) Gecko/20100101 Firefox/147.0", @@ -337,75 +318,6 @@ "unmaskedRenderer": "Apple M1, or similar" } }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:148.0) Gecko/20100101 Firefox/148.0", - "platform": "MacIntel", - "hardwareConcurrency": 4, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1920, - "height": 1080, - "colorDepth": 30, - "availWidth": 1920, - "availHeight": 1011 - }, - "webgl": { - "unmaskedVendor": "NVIDIA Corporation", - "unmaskedRenderer": "NVIDIA GeForce GTX 480, or similar" - }, - "speechVoices": [ - "Alex:en-US:local", - "Alice:it-IT:local", - "Alva:sv-SE:local", - "Amelie:fr-CA:local", - "Anna:de-DE:local", - "Carmit:he-IL:local", - "Damayanti:id-ID:local", - "Daniel:en-GB:local", - "Diego:es-AR:local", - "Ellen:nl-BE:local", - "Fiona:en-scotland:local", - "Fred:en-US:local", - "Ioana:ro-RO:local", - "Joana:pt-PT:local", - "Jorge:es-ES:local", - "Juan:es-MX:local", - "Kanya:th-TH:local", - "Karen:en-AU:local", - "Kyoko:ja-JP:local", - "Laura:sk-SK:local", - "Lekha:hi-IN:local", - "Luca:it-IT:local", - "Luciana:pt-BR:local", - "Maged:ar-SA:local", - "Mariska:hu-HU:local", - "Mei-Jia:zh-TW:local", - "Melina:el-GR:local", - "Milena:ru-RU:local", - "Moira:en-IE:local", - "Monica:es-ES:local", - "Nora:nb-NO:local", - "Paulina:es-MX:local", - "Rishi:en-IN:local", - "Samantha:en-US:local", - "Sara:da-DK:local", - "Satu:fi-FI:local", - "Sin-ji:zh-HK:local", - "Tessa:en-ZA:local", - "Thomas:fr-FR:local", - "Ting-Ting:zh-CN:local", - "Veena:en-IN:local", - "Victoria:en-US:local", - "Xander:nl-NL:local", - "Yelda:tr-TR:local", - "Yuna:ko-KR:local", - "Yuri:ru-RU:local", - "Zosia:pl-PL:local", - "Zuzana:cs-CZ:local" - ] - }, { "navigator": { "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:147.0) Gecko/20100101 Firefox/147.0", @@ -2982,28 +2894,6 @@ "Microsoft Huihui Desktop - Chinese (Simplified):zh-CN:local" ] }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0", - "platform": "Win32", - "hardwareConcurrency": 2, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1366, - "height": 768, - "colorDepth": 24, - "availWidth": 1366, - "availHeight": 728 - }, - "webgl": { - "unmaskedVendor": "Google Inc. (Intel)", - "unmaskedRenderer": "ANGLE (Intel, Intel 945GM Direct3D11 vs_4_0 ps_4_0)" - }, - "speechVoices": [ - "Microsoft Anna - English (United States):en-US:local" - ] - }, { "navigator": { "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:148.0) Gecko/20100101 Firefox/148.0", @@ -3188,45 +3078,6 @@ "Microsoft Zira Desktop - English (United States):en-US:local" ] }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:148.0) Gecko/20100101 Firefox/148.0", - "platform": "Win32", - "hardwareConcurrency": 8, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1680, - "height": 1050, - "colorDepth": 24, - "availWidth": 1680, - "availHeight": 1010 - }, - "webgl": { - "unmaskedVendor": "Google Inc. (NVIDIA)", - "unmaskedRenderer": "ANGLE (NVIDIA, NVIDIA GeForce 8800 GTX Direct3D11 vs_4_0 ps_4_0), or similar" - }, - "speechVoices": [ - "Microsoft David - English (United States):en-US:local", - "Microsoft James - English (Australia):en-AU:local", - "Microsoft Linda - English (Canada):en-CA:local", - "Microsoft Richard - English (Canada):en-CA:local", - "Microsoft George - English (United Kingdom):en-GB:local", - "Microsoft Hazel - English (United Kingdom):en-GB:local", - "Microsoft Susan - English (United Kingdom):en-GB:local", - "Microsoft Sean - English (Ireland):en-IE:local", - "Microsoft Heera - English (India):en-IN:local", - "Microsoft Ravi - English (India):en-IN:local", - "Microsoft Catherine - English (Australia):en-AU:local", - "Microsoft Mark - English (United States):en-US:local", - "Microsoft Zira - English (United States):en-US:local", - "Microsoft George - English (Great Britain):en-GB:local", - "Microsoft Sarah Mobile - English (Great Britain):en-GB:local", - "Microsoft Hazel Desktop - English (Great Britain):en-GB:local", - "Microsoft David Desktop - English (United States):en-US:local", - "Microsoft Zira Desktop - English (United States):en-US:local" - ] - }, { "navigator": { "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:148.0) Gecko/20100101 Firefox/148.0", @@ -4360,25 +4211,6 @@ "unmaskedRenderer": "NVIDIA GeForce GTX 980, or similar" } }, - { - "navigator": { - "userAgent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:148.0) Gecko/20100101 Firefox/148.0", - "platform": "Linux x86_64", - "hardwareConcurrency": 8, - "maxTouchPoints": 0 - }, - "screen": { - "width": 1920, - "height": 1080, - "colorDepth": 24, - "availWidth": 1920, - "availHeight": 1010 - }, - "webgl": { - "unmaskedVendor": "NVIDIA Corporation", - "unmaskedRenderer": "GeForce GTX 480, or similar" - } - }, { "navigator": { "userAgent": "Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0", diff --git a/pythonlib/camoufox/fingerprints.py b/pythonlib/camoufox/fingerprints.py index 9e4ab16..9294091 100644 --- a/pythonlib/camoufox/fingerprints.py +++ b/pythonlib/camoufox/fingerprints.py @@ -6,6 +6,7 @@ import secrets import sqlite3 import unicodedata from dataclasses import asdict, dataclass, is_dataclass +from functools import lru_cache from pathlib import Path from random import Random, choice, randint, randrange from typing import Any, Dict, FrozenSet, List, Optional, Set, Tuple @@ -37,6 +38,21 @@ def _generator(): return _FP_GENERATOR +@lru_cache(maxsize=None) +def firefox_gpus(os_name: str) -> FrozenSet[Tuple[str, str]]: + """Every (vendor, renderer) that fpgen has seen Firefox report on this OS. + + A GPU outside this set has no recorded WebGL parameters behind it, so an + identity naming it could only borrow another device's. + """ + import fpgen + + return frozenset( + (result.value['vendor'], result.value['renderer']) + for result in fpgen.trace(target='gpu', browser='Firefox', os=_FPGEN_OS[os_name.lower()]) + ) + + @dataclass class Screen: """A bound on the screen a generated fingerprint may claim. diff --git a/pythonlib/tests/test_shipped_data.py b/pythonlib/tests/test_shipped_data.py index 9909307..89a3114 100644 --- a/pythonlib/tests/test_shipped_data.py +++ b/pythonlib/tests/test_shipped_data.py @@ -94,3 +94,21 @@ def test_every_gpu_row_can_be_drawn_on_some_os(): ) ] assert undrawable == [] + + +@pytest.mark.parametrize("filename", PRESET_FILES) +def test_every_preset_gpu_has_webgl_data(filename): + """A preset records only its GPU's name; the WebGL parameters behind it come + from fpgen. A GPU fpgen has never seen Firefox report on that OS has none, so + launching it would pair the name with another device's parameters.""" + from camoufox.fingerprints import firefox_gpus + + presets = json.loads((DATA / filename).read_text())["presets"] + for os_name, entries in presets.items(): + known = firefox_gpus(os_name) + for index, preset in enumerate(entries): + gpu = (preset["webgl"]["unmaskedVendor"], preset["webgl"]["unmaskedRenderer"]) + assert gpu in known, ( + f"{filename} {os_name}[{index}]: {gpu[1]!r} has no WebGL data" + " -- run scripts/clean-fingerprint-data.py --write" + ) diff --git a/scripts/clean-fingerprint-data.py b/scripts/clean-fingerprint-data.py index 6b2c393..616044f 100644 --- a/scripts/clean-fingerprint-data.py +++ b/scripts/clean-fingerprint-data.py @@ -11,7 +11,9 @@ never existed. What it covers: fingerprint-presets.json, fingerprint-presets-v150.json - Each preset is converted the way a launch converts it and checked. A row + Each preset is converted the way a launch converts it and checked, and + its GPU must be one fpgen has seen Firefox report on that OS: WebGL + parameters come from fpgen, and a GPU it has never seen has none. A row that fails is dropped rather than repaired: repairing would write an invented value ("what core count does a 2-core Apple M1 really have?") into a file whose entire purpose is being real. @@ -42,7 +44,7 @@ REPO = Path(__file__).resolve().parent.parent sys.path.insert(0, str(REPO / 'pythonlib')) from camoufox import coherence # noqa: E402 -from camoufox.fingerprints import from_preset # noqa: E402 +from camoufox.fingerprints import firefox_gpus, from_preset # noqa: E402 PRESET_FILES = ( REPO / 'pythonlib' / 'camoufox' / 'fingerprint-presets.json', @@ -60,7 +62,12 @@ def preset_violations(preset, os_name): config = from_preset(preset, FF_VERSION) except Exception as exc: # a row too malformed to convert is itself a defect return [coherence.Violation('unconvertible', f'{type(exc).__name__}: {exc}')] - return coherence.validate(config, OS_KEY[os_name]) + violations = coherence.validate(config, OS_KEY[os_name]) + gpu = (preset.get('webgl', {}).get('unmaskedVendor'), preset.get('webgl', {}).get('unmaskedRenderer')) + if gpu not in firefox_gpus(os_name): + violations.append(coherence.Violation( + 'gpu-without-webgl-data', f'fpgen has never seen Firefox on {os_name} report {gpu[1]!r}')) + return violations def clean_presets(path, write):