One Shared ChatGPT Link Read Private Chats. The Library Behind It Still Has No Advisory.

A house key tied to a street lamp by string beside an open ground-floor window

On 18 October the researchers at Parameter Labs sent OpenAI's bug bounty program a report that said, in effect: one ordinary shared conversation, one opened link, your account. Eight days later OpenAI had fixed it, rated it P1, and paid $5,000. Parameter published the writeup on 28 October, and I have now read it end to end — not the headlines, the writeup — because the interesting part is not that ChatGPT had a hole. It is that the sandbox they built did its job, and the breach came through a seam no one had drawn.

Here is what one shared link did. An attacker authors a normal-looking ChatGPT conversation containing two pieces: a genuine interactive graph, and an HTML code block. They publish it with the ordinary share feature and send you the link. You open it — in the most reliable variant you also click the Preview button once; in a later variant nothing else, and the code ran by itself about 4.5 seconds after the page loaded, reproduced three times including after a hard refresh. From there the attacker's JavaScript ran as chatgpt.com, inside your signed-in session: it listed your recent conversations, opened a private one that had never been shared with anyone, and shipped a piece of it out through an image request. OpenAI's own figure for reach, as of September 2025, is 700 million weekly active users — reach, not impact: every proof in the writeup ran between researcher-controlled accounts and workspaces.

The chain is worth five sentences, because each step looked fine alone. The HTML Preview runs, correctly, in a sandboxed frame on a separate origin — that isolation held. But the graph in the same conversation loads MathLive into the main page, and MathLive registers a postMessage listener for its virtual keyboard that, for this one setting, accepted messages from any origin and never checked which frame sent them. The sandboxed Preview posted a keyboard-layout update carrying raw HTML; MathLive wrote it to innerHTML — its createHTML helper is a Trusted Types identity wrapper, which marks strings trusted without making them safe. The injected HTML was an iframe with srcdoc and no sandbox attribute, so the browser gave it the main page's own chatgpt.com identity. The content security policy still blocked inline scripts — so the payload came back through YouTube's oEmbed endpoint, whose JSONP callback echoed attacker code in a 200 response from a domain the CSP already allowed. The final callback was 5,533 characters. Every piece is a reasonable feature; the bug lived only in the combination.

Now the part the coverage mostly missed. I checked MathLive's GitHub security advisories directly on 1 November. Four advisories exist — the newest two, both High, published 9 October 2026, cover XSS through other sinks (\enclose attributes, \href values, MathML output). None of them covers the unauthenticated keyboard postMessage path this chain actually used. There is no CVE for this report either, and no advisory from MathLive upstream. OpenAI's fix was the right shape — both web frontends now reject the cross-frame messages, server-side, nothing for users to install — and during the rollout their CSP tightening blocked part of the chain while one frontend still needed the update. But the library that left the door open still has no published advisory or fixed version that I can find, and Ostorlab's independent analysis reaches the same conclusion while noting the release pages themselves disagree about which version is "latest."

If you build anything that renders model-produced HTML in a preview beside a logged-in session — and in 2026 that is every artifacts-style product — the lessons are concrete, not atmospheric. A postMessage receiver must verify both event.origin and event.source before any state-changing instruction. Cross-window settings must be data, never HTML. Dynamically created documents stay sandboxed when an untrusted frame can influence their content. And CSP is a backup control, not a wall: allow-listing a media giant's domain is one reflected endpoint away from allow-listing its attackers.

What to watch: whether MathLive publishes an advisory and a fixed release for the listener — that is the tell for whether this class of seam gets closed in the ecosystem or only in ChatGPT. Simon Willison, who linked the writeup on 31 October, thinks the $5,000 bounty was cheap for a P1 cross-user data-theft primitive at this scale. I agree. A bounty table prices the report, not the blast radius — and until upstream ships, the cheapest part of this story is the only part that repeats.