ChatGPT now knows what you do on other websites via ad collector

发布时间 2026-09-20 10 天前
来源 Hacker News
字数 3,742 字
查看原文

AI智能总结

ChatGPT 现在通过广告采集器知道你在其他网站上的行为 OpenAI 在 `bzr.openai.com` 上的广告采集器会设置一个名为 `__obi` 的 cookie,作用域为 `.openai.com`。

ChatGPT 现在通过广告采集器知道你在其他网站上的行为

OpenAI 在 bzr.openai.com 上的广告采集器会设置一个名为 __obi 的 cookie,作用域为 .openai.com。当你在使用 ChatGPT 时,这个值会被生成并与你的 ChatGPT 账户绑定。随后,当你访问其他普通网站时,__obi 会被发送到 OpenAI。

任何在 ChatGPT 上投放广告的公司都会在自己的网站上安装一小段 OpenAI 代码,方式与零售商已经安装 Meta 和 Google 追踪代码相同。加载这段代码时,会连同你正在浏览的页面数据一起,把 __obi 发送给 OpenAI。这些数据包括你正在搜索的商品、你正在阅读的文章,以及你的购买行为。

结论是:OpenAI 能够把你的 ChatGPT 账户与你在这些网站上的行为关联起来。

我在自己的手机上完整复现了整套机制,使用两种独立的抓包方法加以验证,并与覆盖 1,029 个主机名、936 个不同广告主像素的数月观察流量做了交叉核对。

工作原理

第一步:ChatGPT 生成一个标识符并对其进行签名。

在 chatgpt.com 上,客户端会生成 16 个随机字节,并调用 POST /backend-api/bazaar/obi/sync-token(未登录时为 /backend-anon/)。后端返回一个 RS256 JWT:

{
  "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 位十六进制账户主体」",
  "subject_type": "account_user",
  "obi": "「已脱敏:22 字符标识符」",
  "exp": "「iat + 60 秒」"
}

sub 是账户,obi 是标识符。该令牌将二者绑定,作用域限定为采集器,并在 60 秒后过期。bzr 是 bazaar 的缩写,即 OpenAI 内部对广告平台的称呼;wadi 是签发该令牌的服务的名称。

第二步:该标识符成为 OpenAI 域名上的一个 cookie。

客户端将 {"token": "「JWT」"} 跨站 POST 到 bzr.openai.com/v1/obi/sync。响应如下:

Set-Cookie: __obi=「已脱敏」; Domain=.openai.com; HttpOnly;
            Max-Age=31536000; Path=/; SameSite=none; Secure

SameSite=none 加 Secure 是让 cookie 可以在跨站请求中携带所需的配置。Max-Age 为一年。JWT 中的 obi 值与 cookie 中的值完全一致。

第三步:广告主网站把 cookie 回传。

广告主页面会向 OpenAI 的主机发起三类请求。在一台已经带有 __obi cookie 的手机上,这三类请求都携带了该 cookie:

请求 是否携带 __obi 备注
GET bzrcdn.openai.com/sdk/oaiq.min.js 是 即脚本本身的加载
POST bzr.openai.com/v1/sdk/events(带 obref) 是 转化事件
POST bzr.openai.com/v1/sdk/events,裸 body 是 SDK 的 "无凭证" 路径
GET bzrcdn.openai.com/pixel-config/… 完全没有 cookie 头 对照组

第一行尤为值得关注。虽然像素 SDK 内部存在一条省略凭证的代码路径,但并没有用:在 OpenAI 任何代码运行之前加载脚本时,浏览器就会把 cookie 附带到脚本加载请求上。光是加载这个标签,标识符就已经泄露了。

一起被发送出去的数据

该 SDK 还会从广告主页面采集身份信息。载荷被划分为四个来源,由 OpenAI 自身命名:in 表示广告主主动传入的值,fm、ht、js 分别表示 SDK 从表单字段、页面渲染文字以及标签管理器总线中抓取的值。在观察到的流量中,抓取得到的身份信息数量多于广告主主动传入的身份信息,比例是 685 个事件对 255 个。

标签管理器总线是电子邮件字段的最大来源。SDK 会用自己的函数替换 window.dataLayer.push,也会读取 adobeDataLayer,还会通过解析 gtm.js 脚本标签上的 l= 参数来定位被改名的 GTM 层。当前版本会从中获取电子邮件和电话号码;版本 0.1.31 还会获取姓名和地理位置,直到 8 月 27 日该范围被收紧。

电子邮件、电话、姓和名在传输前会进行 SHA-256 哈希处理。国家、地区、城市和邮政编码则以明文形式发送。其中邮政编码是采集最多的表单字段,在 28 个网站上共出现 100 次。

URL 在发送前会被缩减为 origin 加 path;在观察到的 23,929 条样本中,没有一条带有查询字符串。路径会被保留,而发往采集器的路径中包含一个涉及医学状况的页面、一个债务解决方案的漏斗页面,以及一个诉讼接待表单。

在已知设置的 881 个像素中,有 638 个开启了自动匹配,包括观察到的所有信贷和借贷类广告主。该功能由 OpenAI Ads Manager 控制。系统维护一份屏蔽列表,其中包含密码、一次性验证码、银行卡号、社会安全号、出生日期、病史、诊断信息和法院相关字段。

这个 cookie 的设计目的就是跨站

在同样的广告主页面请求中,浏览器屏蔽了所有其他 OpenAI cookie:

Cookie 结果
oai-did、oaicom-stable-id 被屏蔽,SameSite=Lax
oai-client-auth-info、会话 cookie 被屏蔽,域名不匹配
__obi 被发送

__obi 是唯一配置了 SameSite=None 的 OpenAI 标识符。

实际触达范围

在我的设备上,同一个 __obi 值从 12 个商业网站、13 个不同的像素 ID 被发送给 OpenAI,其中包括 Chewy、Wayfair、ThriftBooks、Eventbrite、HelloFresh、Coursera 和 SeatGeek。所有请求均以 202 状态码被接受。

在更大范围的流量中,30 个不同的 __obi 值中有 12 个出现在多个广告主下,其中一个出现在了 10 个广告主下。

退出登录时同样有效

在解码的 932 个同步令牌中,736 个带有 subject_type: account_user,196 个带有 anonymous。匿名主体和账户主体一样稳定:每个设备一个,至少持续 27 天。

OpenAI 的 cookie 政策是怎么说的

OpenAI 的 cookie 政策 将 __obi 列为分析类 cookie,时长一年,作用域为 chatgpt.com 和 openai.com。它也是该章节中唯一一项。该政策将分析类 cookie 描述为帮助 OpenAI 了解其服务的表现和使用情况。

OpenAI 将分析和营销设置为两个独立的同意选项,分别为 oai_consent_analytics 和 oai_consent_marketing,而我解码的每一个同步令牌都带有 consent_decision: analytics_allowed。也就是说,即使用户允许了分析、拒绝了营销,依然会收到这个 cookie。

OpenAI 的回应

9 月 14 日,我把整套机制和两个问题发送到了 press@openai.com 和 privacy@openai.com:为什么 __obi 被归类为分析 cookie,以及授予分析同意但拒绝营销同意的用户是否仍然会收到它。回复来自 OpenAI Support。回复确认收悉,表示所观察到的现象将在内部共享以供审查,但并未回答上述两个问题。上述关于脚本加载时即泄露 cookie 的观察是在询问发出之后做出的。如果 OpenAI 后续作出回应,我会更新本文。

局限性

浏览器。 仅在安卓版 Chrome 上观察到。Safari 的智能防跟踪 会屏蔽所有第三方 cookie,而且 iOS 上的 Chrome 也运行在 WebKit 上,因此该机制在所有 iOS 浏览器上都不会生效。桌面版 Chrome 尚未测试。

触发率。 大约五次 ChatGPT 会话中会有一次产生同步令牌。ChatGPT 的移动网页客户端在投放广告时完全不会进行同步。按照下面的步骤操作时,可能会看到像素触发但没有附带 cookie 的情况。

关联动作未被直接观察到。 202 表示采集器在接收到附带 cookie 的事件后接收成功。OpenAI 在服务端将该事件解析到对应账户这一点是从机制设计上推导出来的,我并没有看到它实际发生。

结构上的等价物 Meta 多年前就已搭建。 一个已登录的账户、在像素触发时附带第三方 cookie、站外转化被解析到一份画像上。这套机制在广告技术领域是标准操作。真正没有先例的是把它放在一款 AI 聊天产品上运行。人们会向这类产品倾诉他们不会发到社交网络上的内容,而这类产品也在越来越多地代表他们采取行动。

像素设置的另一个 cookie 并不会带来这种影响。 __obref 是设置在广告主自有域名下的。每个网站获得的值都不同,其他网站无法看到。在观察到的 2,860 个值中,2,828 个仅出现在唯一一个广告主下。

广告主看不到这一点。 __obi 归属于其脚本无法读取的域名。广告主只是安装了一个转化像素,没有任何办法知道其访客正在被解析到一个 ChatGPT 身份上。