Предсказание CreepJS: агрегация и неизвестные состояния
Сопоставьте поиск getPrediction в CreepJS с агрегацией сигналов renderPrediction и unknown-состояниями: ни один вывод не доказывает личность устройства.
BotBrowser Team
Нужна структурированная документация по теме Отпечатки?
Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.
BotBrowser может поддерживать согласованность заявленного профиля между поверхностями, видимыми браузеру, но не может подтверждать корректность стороннего предсказания по общей выборке. В закреплённом коде CreepJS getPrediction() ищет строку общих данных и выбирает кандидатов, а renderPrediction() отдельно читает decryptionData, объединяет поля сигналов и показывает состояния проверки или оценки. Это разные пути кода; ни один результат не доказывает личность человека или машины и не выносит вердикт о боте.
TL;DR
getPredictionищет в переданных данных строку, у которойidсовпадает с запрошенным хешем; сравнение также допускает преобразование обоих значений в строки. Локальная переменнаяdecryptedхранит ключ найденного объекта; эта функция не расшифровывает строку.- Поля системы, GPU и бренда GPU возвращаются только тогда, когда соответствующие списки кандидатов содержат ровно одно значение. Для устройства дополнительно может вернуться общая базовая часть нескольких имён.
- Рендерер сводит значения из 18 именованных записей сборщиков к трём объектам JavaScript
Set: для бренда GPU, GPU и устройства.Setудаляет повторяющиеся значения, после чего код удаляетundefined; агрегация не сохраняет сведения о том, какой сборщик дал каждое оставшееся значение. unknownHTML,pendingReview, оценки смешения данных, маркеры предсказания и маркер ошибки относятся к разным ветвям. Ни одна из них не является откалиброванной вероятностью правильности метки.
Contents
- Метка предсказания является результатом агрегации
- Сначала найдите строку общих данных
- Число кандидатов определяет возвращаемые значения
- Восемнадцать записей питают три множества без дублей
- Разделяйте выбор устройства и состояния оценки
- Сохраняйте запись сравнения с привязкой к источнику
- Practical conclusion
Метка предсказания является результатом агрегации
Слово «предсказание» может подтолкнуть к более сильной трактовке, чем допускает реализация. Увидев рядом имя устройства и оценку, читатель может решить, что страница распознала физическое устройство или измерила вероятность правильности имени. Закреплённая реализация CreepJS не подтверждает ни одного из этих выводов. Она показывает, как из входных данных выбираются и отображаются отдельные значения; в исходнике нет исследования калибровки, доверительного интервала или идентификатора конкретного человека.
Две функции отвечают на разные вопросы. getPrediction ищет одну строку общих данных и сокращает четыре списка кандидатов до полей system, device, gpu и gpuBrand. renderPrediction получает объекты сборщиков, объединяет выбранные поля между ними, а затем формирует разметку области предсказания и отдельных строк сигналов. Результат поиска и отрисованную сводку сборщиков не следует сводить к одной непрозрачной оценке.
В руководстве CreepJS по группам сигналов объясняется чтение меток по поверхностям, а анализ перекрёстной проверки групп прослеживает упорядоченные шаблоны за botHash. Эти темы не разбирают сопоставление строки общих данных и ветви кандидатов и отображения панели предсказания.
Различие важно при изменении отчёта. Метка может исчезнуть, потому что в списке кандидатов стало два значения, значения сборщиков перестали иметь общую базу, поле не было передано или сработала ветвь ошибки предсказания. Это разные пути с разным смыслом. Отсутствие одного значения не доказывает отсутствие GPU в браузере, а маркер ошибки не доказывает, что все сборщики запустились и разошлись во мнениях.
Область разбора ограничена закреплённой ревизией 10aa6724cd33a1015db1574211890518cd04f0cc файла CreepJS src/prediction/index.ts, а не текущим наблюдением за работающим сервисом CreepJS. Общий материал /docs/proof/fingerprinting-privacy-threat/ описывает сигналы отпечатка браузера, но не картирует ветви этого модуля предсказания.
Сначала найдите строку общих данных
getPrediction получает hash и data. Функция перебирает ключи data, ищет в массиве под каждым ключом и сравнивает id каждого элемента с запрошенным хешем. Сравнение допускает как прямое равенство, так и равенство после преобразования обоих значений в строки. Ключ, содержащий совпавший элемент, сохраняется в локальной переменной с именем decrypted.
Это имя переменной не доказывает выполнение криптографической операции. В этой функции важны поиск в массиве и сравнение идентификаторов. Исходный код здесь не расшифровывает элемент. Точное описание операции: «поиск строки общих данных по хешу», а не «расшифровка предсказания». Имя локальной переменной не меняет операцию, которую выполняет код.
После нахождения совпавшего элемента функция копирует в локальные переменные четыре массива: devices, systems, gpus и gpuBrands. Если массива нет, функция использует пустой массив. Затем объект результата выбирает публичное значение из каждого списка. Поэтому поиск может завершиться успешно, хотя одно или несколько возвращаемых полей останутся undefined: найти строку и получить одно однозначное значение это разные этапы.
| Исходное значение | Действие поиска | Осторожная трактовка |
|---|---|---|
item.id | Сравнить с переданным hash, в том числе после преобразования в строки | В переданном объекте данных найдена совпавшая запись. |
item.systems | Использовать пустой список при отсутствии; вернуть систему только для одного кандидата | Ноль или несколько кандидатов не дают единственного значения system. |
item.gpus | Использовать пустой список при отсутствии; вернуть GPU только для одного кандидата | Отсутствующая метка GPU не означает, что у браузера нет GPU. |
item.gpuBrands | Использовать пустой список при отсутствии; вернуть бренд только для одного кандидата | Функция не ранжирует несколько брендов и не задаёт уровень уверенности для одного из них. |
item.devices | Использовать пустой список при отсутствии; вернуть кандидата или общую базовую часть | Общий текстовый префикс служит правилом выбора, а не независимой проверкой оборудования. |
Последнюю строку особенно легко истолковать слишком сильно. В комментарии к коду Android 10 приведён как базовое имя, общее для Android 10 и Android 10 Blah Blah. Это пример правила включения одной строки в другую. Он не показывает, что CreepJS подтвердил точную версию ОС в работающем браузере.
Число кандидатов определяет возвращаемые значения
Правила возврата намеренно асимметричны. Для трёх полей требуется ровно один кандидат, а у device есть запасной вариант для общей базовой части. Длина массива объясняет, почему видимое поле может отсутствовать даже при наличии строки общих данных.
| Поле | Условие кандидата в закреплённом коде | Возвращаемое значение при невыполнении условия |
|---|---|---|
system | systems.length == 1 | undefined |
gpu | gpus.length == 1 | undefined |
gpuBrand | gpuBrands.length == 1 | undefined |
device | Одно устройство или базовое имя, входящее в каждую строку-кандидат | Помощник общей базы возвращает undefined, если ни одно имя не общее для всех. |
Для систем, моделей GPU и брендов GPU реализация не выбирает самый частый вариант и не сортирует кандидатов по оценке. Она проверяет, состоит ли массив из одного элемента. Если нет, поле становится undefined. Это явная граница неоднозначности, а не скрытое ранжирование.
Для устройств getBaseDeviceName ищет строку-кандидат a, которая содержится во всех строках-кандидатах b. При одном кандидате код возвращает его сразу, не вызывая помощник. При нескольких кандидатах может вернуться общая базовая часть; если ни одно имя не входит во все строки, эта ветвь не возвращает одно имя устройства. Правило основано на тексте, его нельзя описывать как вычисление расстояния между аппаратными конфигурациями.
Следующие примеры по исходнику показывают путь кода, а не текущий отчёт:
| Список кандидатов | Результат пути кода | Чего результат не доказывает |
|---|---|---|
В systems одна запись | Она возвращается как system | Что метка идентифицирует ОС конкретного человека. |
В gpus две записи | Единственное значение gpu не возвращается | Что оба GPU отсутствовали у всех сборщиков. |
devices содержит Android 10 и Android 10 Blah Blah | Может вернуться общая база Android 10 | Что конкретная версия Android независимо проверена. |
devices содержит несвязанные имена без общей для всех базы | Помощник базы не возвращает значение | Что браузер недействителен или автоматизирован. |
Значение undefined полезно сохранять как отдельное состояние. Замена его первым кандидатом, предполагаемым большинством или выведенным устройством добавила бы правило выбора, которого в этой функции нет. В таблице сравнения следует отдельно записывать «единственное значение не возвращено» и «исходное поле отсутствовало».
Восемнадцать записей питают три множества без дублей
Агрегированные поля gpuSystem и gpuModelSystem не описывают создание WebGL-контекстов или поддержку расширений; разбор WebGL-отчёта CreepJS отдельно рассматривает сигналы контекста и возможностей рендерера.
renderPrediction читает именованные объекты сигналов и создаёт три экземпляра Set. Каждое множество получает свойство из 18 записей: jsRuntime, emojiSystem, domRectSystem, svgSystem, mimeTypesSystem, audioSystem, canvasSystem, canvasPaintSystem, canvasTextSystem, canvasEmojiSystem, textMetricsSystem, webglSystem, gpuSystem, gpuModelSystem, fontsSystem, voicesSystem, screenSystem и deviceOfTimezone.
Свойства проецируются отдельно. Одно множество собирает gpuBrand, другое собирает gpu, третье собирает device. Перед чтением свойства для каждой записи используется резервный пустой объект. После построения каждого множества код удаляет undefined. Одинаковые повторяющиеся значения схлопываются до одного элемента, поскольку Set хранит только уникальные значения.
| Агрегированное множество | Свойство из каждой из 18 записей | Прямое преобразование в исходнике |
|---|---|---|
gpuBrands | .gpuBrand | Создать множество, затем удалить undefined. |
gpus | .gpu | Создать множество, затем удалить undefined. |
devices | .device | Создать множество, затем удалить undefined. |
Операция сводит коллекцию именованных полей к уникальным значениям, но итоговое множество не показывает, какой сборщик дал каждое оставшееся значение. Если пять сборщиков возвращают один gpuBrand, в множестве будет одно значение, а не счётчик пять. Если два сборщика расходятся, множество может содержать два значения, но интерфейс всё равно не сообщает, какой API дал каждое из них. Исходный модуль показывает список источников в коде; если происхождение важно для сравнения, его нужно сохранять отдельно.
Множество также не равно списку кандидатов строки общих данных. Массивы в getPrediction отвечают на вопрос, можно ли вернуть одно значение для хеша. Множества сборщиков в renderPrediction объединяют значения объектов сигналов для видимой сводки. Одно слово вроде «консенсус» для обоих путей скрыло бы это различие.
18 исходных полей можно сгруппировать по названной поверхности, но эти названия не означают одинаковое качество или независимость. Canvas image, Canvas paint, Canvas text и Canvas emoji представлены отдельными входами в коде. То же верно для gpuSystem и gpuModelSystem. Считать их полностью независимыми голосами означало бы добавить статистическое допущение, которого нет в реализации.
Разделяйте выбор устройства и состояния оценки
Перед отображением имени устройства интерфейс вычисляет специальный выбор Windows Remote Firefox Privacy. Код подсчитывает строки устройств, содержащие «Windows», и делит число таких строк на общее число строк. Эта ветвь работает только при доле выше 0.5; затем она проверяет фиксированный порядок предпочтений: Windows 7, Windows 8, Windows 8.1, Windows 11 и Windows 10, сначала проверяя написание с 64 битами для каждой версии. Если доля не превышает половину, помощник возвращает undefined.
Итоговый deviceName берётся из помощника RFP или, если результат falsy, из общей базовой части имён устройств. Комментарий говорит, что в данных выборки Firefox RFP игнорируется, поскольку возвращает Windows 10, а затем объясняет порядок предпочтений при наличии нескольких версий Windows. Это правило отображения конкретного источника. Оно не доказывает, что вся популяция следует такому порядку, и не должно подаваться как в целом точный определитель ОС.
crowdBlendingScoreGrade сопоставляет числовые диапазоны с буквами: A от 90, B от 80, C от 70, D от 60 и F ниже 60. Разметка показывает процент и букву только если тип crowdBlendingScore в JavaScript равен number. Отдельная ветвь bot показывает locked. Код задаёт отображение оценок и условие интерфейса, но не устанавливает, что предсказывает оценка и насколько она откалибрована.
Модуль показывает pendingReview в отдельной заметке, когда поле truthy. Эту метку нужно записывать отдельно от оценки и имени предсказания. Закреплённый исходник не позволяет заменить её словами «ошибка», «одобрено» или «проверка человеком завершена» без другого источника, который определяет это состояние.
Несколько деталей интерфейса можно записывать, не превращая их в заявления об уверенности:
| Видимое состояние | Условие исходника | Ограниченная трактовка |
|---|---|---|
** перед объединённой меткой | deviceName и gpuBrandName truthy | Рендерер располагает обеими строками. Звёзды не являются вероятностью. |
* перед одной меткой | Truthy только одна из двух строк | В этой ветви доступна одна из двух строк отображения. |
| Пустые значки предсказания | Обе строки falsy | Эта ветвь не показывает объединённую метку. |
pending review: … | pendingReview truthy | Отображается переданное поле; закреплённый исходник не определяет итог проверки. |
| Оценка и буква смешения данных | Значение имеет тип number, а ветвь блокировки не сработала | Интерфейс показывает число и диапазон оценки; точность неизвестна. |
locked | Ветвь bot truthy | Интерфейс использует ветвь блокировки и не показывает в ней оценку. |
Помощник hasValue требует отдельной осторожности. Он ищет первое значение свойства, тип которого не undefined; вызывающие его ветви отрицают результат, чтобы выбрать unknownHTML. Определённое значение false или 0 само является falsy и поэтому может попасть в ветвь неизвестного состояния. Следовательно, метка unknown не доказывает, что сборщик не запускался. Она может отражать то, как помощник обрабатывает falsy-значение. Это наблюдение ограничено закреплённой реализацией и требует повторной проверки, если в более поздней версии помощник изменится.
predictionErrorPatch образует ещё одну ветвь. Если передать ошибку и элемент предсказания существует, функция показывает Prediction Failed и пустые значки во многих строках. Этот маркер описывает интерфейс ошибки, а не правило числа кандидатов и не успешный запуск, в котором отсутствовали все сигналы. В записи нужно отделять ветвь ошибки от обычного отчёта, где неизвестными отображаются отдельные строки.
Сохраняйте запись сравнения с привязкой к источнику
Если два отчёта отличаются, сначала запишите вопрос и ревизию источника, а уже затем трактуйте метки. Эти поля сохраняют различия реализации без копирования необработанного хеша и полного идентификатора браузера:
| Поле записи | Что сохранить | Почему это важно |
|---|---|---|
| Источник | Репозиторий, SHA коммита и путь файла | Поздняя ревизия может изменить поиск или отображение. |
| Состояние поиска | Была ли в данных строка с совпавшим хешем; сам хеш не сохранять | Наличие строки и уникальность поля: отдельные результаты. |
| Число кандидатов | Число вариантов для систем, устройств, GPU и брендов GPU | Правила возврата зависят от длины массива и общей базы устройства. |
| Состояние агрегации | Какие именованные поля сборщиков присутствовали и имело ли множество ноль, одно или несколько уникальных значений | Дедуплицированное множество не хранит исходный список вкладов. |
| Состояние отображения | Маркер предсказания, ветвь unknown, pendingReview, показ числовой оценки, блокировка или маркер ошибки | Похожие пустые области могут появляться по разным путям. |
| Ограничения | Разбор закреплённого кода, текущее наблюдение страницы или явно ограниченный другой источник | Один лишь код не доказывает текущий результат сервиса или его точность. |
Не сохраняйте переданный хеш только потому, что поиск использует его. Для объяснения пути обычно достаточно логического признака наличия совпавшей строки и числа кандидатов. Сохранение необработанного идентификатора увеличивает объём данных без улучшения объяснения ветви.
Используйте эту таблицу для трактовки и сравнения поведения открытых источников. Это не протокол воспроизведения серверной части CreepJS, не тест её точности и не способ изменить оценку стороннего сервиса. Для таких утверждений нужны другие доказательства, которых в этом исходном файле нет.
Sources
- Модуль предсказания CreepJS в коммите
10aa6724cd33a1015db1574211890518cd04f0cc: поиск, сокращение кандидатов, агрегация сборщиков, неизвестные состояния, отображение оценки и маркер ошибки. - BotBrowser: угрозы отпечатка и приватности: общий контекст сигналов и приватности, не реализация предсказания CreepJS.
- BotBrowser: согласованность автоматизации: совместное рассмотрение поверхностей конфигурации, видимых браузеру; не определяет решение стороннего детектора.
Practical conclusion
Читайте панель предсказания CreepJS как набор зависящих от источника выходных состояний. Сначала проверьте наличие совпавшей строки общих данных, затем отдельно сохраните числа кандидатов, уникальные значения сборщиков и состояние отображения. Возвращённое одиночное значение, общая база имени устройства, диапазон оценки, заметка о проверке и неизвестный маркер не являются взаимозаменяемыми доказательствами. Закреплённый код объясняет, как собираются метки; он не превращает их в подтверждённую идентичность устройства или откалиброванный вердикт о боте.
Эта статья входит в руководство: Что такое отпечаток браузера?
Похожие статьи
Сигналы Math в CreepJS: источники полей
ОтпечаткиОтчёт CreepJS WebGL: контексты и сигналы
ОтпечаткиОтчёт BrowserLeaks WebGL: сбор и отсутствующие данные
ОтпечаткиМетрики эмодзи CreepJS: множества и суммы
ОтпечаткиАудиоотчёт CreepJS: рендеринг и пропуски
ОтпечаткиТаблицы шрифтов CreepJS: 51 имя и 14 вариантов возврата
Переведите BotBrowser из исследований в продакшн
Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.