ChatGPT теперь знает, что вы делаете на других сайтах: разбор механизма рекламного трекера OpenAI

· 2 мин чтения
privacy openai chatgpt tracking security
ChatGPT теперь знает, что вы делаете на других сайтах: разбор механизма рекламного трекера OpenAI

Рекламный коллектор OpenAI на bzr.openai.com выставляет cookie __obi с областью действия .openai.com. Пока вы находитесь в ChatGPT, значение привязано к вашему аккаунту; затем этот же cookie уходит обратно в OpenAI с обычных сайтов, которые вы посещаете. Любой рекламодатель, размещающий объявления в ChatGPT, устанавливает на своём сайте небольшой код измерения OpenAI — точно так же, как ритейлеры давно ставят трекинг-код Meta и Google. Загрузка этого кода отправляет __obi в OpenAI вместе с данными о просматриваемой странице: какие товары вы ищете, какие статьи читаете, как совершаете покупки. Итог: OpenAI может связать ваше поведение на сторонних сайтах с аккаунтом ChatGPT.

Автор исследования (Buchodi's Threat Intel) воспроизвёл весь механизм на своём телефоне, подтвердил его двумя независимыми методами перехвата трафика и сверил с несколькими месяцами наблюдений: 936 рекламных пикселей на 1029 хостнеймах.

Как это работает

Шаг 1. ChatGPT создаёт идентификатор и подписывает его. На chatgpt.com клиент генерирует 16 случайных байт и вызывает POST /backend-api/bazaar/obi/sync-token (или /backend-anon/ для неавторизованных). Бэкенд возвращает JWT, подписанный RS256:

{
  "iss": "chatgpt-wadi",
  "aud": "bzr.openai.com",
  "purpose": "obi_sync",
  "operation": "set",
  "consent_decision": "analytics_allowed",
  "consent_policy_version": "user_granular_consent_v1",
  "sub": "<64-hex account subject>",
  "subject_type": "account_user",
  "obi": "<22-char identifier>",
  "exp": "<iat + 60s>"
}

sub — аккаунт, obi — идентификатор. Токен связывает их, ограничен коллектором и живёт 60 секунд. Префикс bzr — это bazaar, внутреннее название рекламной платформы OpenAI; wadi — выдающий сервис.

Шаг 2. Идентификатор становится cookie на домене OpenAI. Клиент отправляет токен кросс-сайтовым POST на bzr.openai.com/v1/obi/sync. Ответ:

Set-Cookie: __obi=<value>; Domain=.openai.com; HttpOnly;
            Max-Age=31536000; Path=/; SameSite=none; Secure

SameSite=none вместе с Secure — ровно та конфигурация, при которой cookie отправляется в кросс-сайтовых запросах. Срок жизни — один год. Значение obi из JWT и значение cookie идентичны.

Шаг 3. Сайты рекламодателей отправляют его обратно. Со страницы рекламодателя к хостам OpenAI уходят три класса запросов, и на телефоне с __obi в хранилище все три несли его:

Запрос Нёс __obi Примечание
GET bzrcdn.openai.com/sdk/oaiq.min.js да сама загрузка скрипта
POST bzr.openai.com/v1/sdk/events с obref да события конверсий
POST bzr.openai.com/v1/sdk/events, «голое» тело да путь SDK «без учётных данных»
GET bzrcdn.openai.com/pixel-config/… нет cookie вовсе контрольный

Особенно интересна первая строка: у пиксельного SDK есть кодовый путь без передачи учётных данных, и это не помогает — браузер прикрепляет cookie к самому запросу <script src>, который загружает SDK, ещё до того, как выполнится какой-либо код OpenAI. Сам факт загрузки тега раскрывает идентификатор.

Что передаётся вместе с ним

Тот же SDK собирает идентификационные данные со страницы рекламодателя. В полезной нагрузке четыре источника, размеченные самой OpenAI: in — значения, которые рекламодатель передаёт намеренно; fm, ht и js — значения, которые SDK соскребает с полей форм, отрисованного текста страницы и шины tag-manager. В наблюдаемом трафике соскребённой идентификации оказалось больше, чем явно переданной: 685 событий против 255.

Крупнейший источник email — шина tag-manager. SDK подменяет window.dataLayer.push своей функцией, читает также adobeDataLayer, а переименованные слои GTM находит, вытаскивая параметр l= из URL скрипта gtm.js. Текущие версии забирают из неё email и телефон. Версия 0.1.31 до 27 августа собирала ещё и имена с географией — потом область применения сузили.

Email, телефон, имя и фамилия перед отправкой хешируются SHA-256. Страна, регион, город и почтовый индекс передаются в открытом виде. Почтовый индекс оказался самым массово собираемым полем форм: 100 событий на 28 сайтах.

URL сокращаются до origin плюс path: ни один из 23 929 наблюдённых запросов не нёс query string. Но path сохраняются, и среди дошедших до коллектора были путь с медицинским диагнозом, воронка долговых решений и форма приёма судебных обращений.

Автоматическое сопоставление (automatic matching) было включено у 638 из 881 пикселя с известной настройкой — включая всех наблюдённых рекламодателей из сферы кредитования. Управляется оно из OpenAI Ads Manager. Denylist исключает пароли, одноразовые коды, номера карт, SSN, дату рождения, медицинскую историю, диагнозы и судебные поля.

Cookie, созданная для пересечения сайтов

В тех же запросах со страниц рекламодателей браузер блокировал все остальные cookie OpenAI:

Cookie Результат
oai-did, oaicom-stable-id заблокированы, SameSite=Lax
oai-client-auth-info, сессионные заблокированы, несовпадение домена
__obi отправлен

__obi — единственный идентификатор OpenAI с SameSite=None.

Наблюдаемый охват

На устройстве автора одно значение __obi ушло в OpenAI с 12 коммерческих сайтов под 13 различными пиксельными ID — среди них Chewy, Wayfair, ThriftBooks, Eventbrite, HelloFresh, Coursera и SeatGeek. Каждый запрос был принят с кодом 202.

В более широком трафике 12 из 30 различных значений __obi появлялись более чем у одного рекламодателя, одно — сразу у десяти.

Работает и без логина

Среди 932 декодированных sync-токенов 736 несли subject_type: account_user, а 196 — anonymous. Анонимный субъект так же стабилен, как аккаунтный: один на устройство, живёт как минимум 27 дней.

Что говорит cookie-политика OpenAI

В cookie-политике OpenAI __obi значится в разделе аналитических cookie: один год, на chatgpt.com и openai.com. Это единственная запись в разделе. Аналитические cookie там описаны как помогающие OpenAI понимать, как работают и используются её сервисы.

При этом аналитика и маркетинг у OpenAI — два отдельных согласия: oai_consent_analytics и oai_consent_marketing. Каждый декодированный токен нёс consent_decision: analytics_allowed. Таков результат для пользователя, который разрешил аналитику и отказал маркетингу.

Ответ OpenAI

14 сентября автор отправил описание механизма и два вопроса на press@openai.com и privacy@openai.com: почему __obi классифицирована как аналитическая cookie и получает ли её пользователь, который дал согласие на аналитику, но отказал маркетингу. Ответ пришёл от службы поддержки OpenAI: обращение признано, наблюдения «будут переданы внутри для анализа», ни один из вопросов не получил ответа.

Ограничения анализа

  • Браузеры. Наблюдение сделано в Chrome для Android. Intelligent Tracking Prevention в Safari блокирует все сторонние cookie, а все браузеры iOS работают на WebKit — на iOS механизм не функционирует. Десктопный Chrome не проверялся.
  • Гейтинг. Примерно одна сессия ChatGPT из пяти производила sync-токен. Мобильный веб-клиент ChatGPT показывает объявления вообще без синхронизации.
  • Связка не наблюдалась напрямую. Код 202 означает лишь, что коллектор принял событие с cookie. То, что OpenAI разрешает её в аккаунт на сервере, следует из конструкции, но зафиксировать это автор не мог.
  • Meta построила структурный эквивалент годы назад: залогиненный аккаунт, сторонние cookie в пиксельных запросах, офсайт-конверсии, разрешаемые в профиль. Механизм — стандартный adtech. Без прецедента осталось только одно: запускать его на AI-чате, куда люди рассказывают то, что не написали бы в соцсети, и который всё чаще действует от их имени.
  • Второй cookie пикселя так не делает. __obref выставляется на домене самого рекламодателя, у каждого сайта своё значение, и ни один сайт не видит чужого: 2828 из 2860 наблюдённых значений встречались ровно у одного рекламодателя.
  • Рекламодатели этого не видят. __obi принадлежит домену, который их скрипты читать не могут. Они поставили пиксель конверсий и не имеют никакого способа узнать, что их посетители связываются с идентичностью ChatGPT.

Источник: https://www.buchodi.com/chatgpt-now-knows-what-you-do-on-other-websites-via-ad-collector/