AI NewsDev toolsAnnouncement

Parameter Labs took over ChatGPT accounts through a sandboxed HTML preview

Parameter Labs chained a math-library listener, an unsandboxed iframe and a YouTube script endpoint. One shared link read a victim's ChatGPT conversations in 4.5 seconds. OpenAI paid $5,000 and fixed it.

AI News

Editorial2 min read

LinkedInX

Why it mattersA sandboxed iframe does not keep the main page safe on its own. Any listener in the parent that trusts cross-frame messages is part of the attack surface.

A sandboxed iframe does not keep the parent page safe on its own. Parameter Labs sent one shareable ChatGPT link that read a signed-in user's private conversations in 4.5 seconds. The chain ran through a math library, an unsandboxed iframe and a YouTube script endpoint on the allowlist.

Mukul Goyal at Parameter Labs published the writeup. OpenAI classified the report as P1 and paid a $5,000 bug bounty. The team disclosed on 18 October and OpenAI released the fix on 26 October, eight days later.

The chain

ChatGPT's HTML Preview feature renders a user's HTML in a sandboxed iframe. The main ChatGPT page loaded the MathLive math library on a graph. MathLive installed a postMessage listener for its on-screen keyboard, and that listener did not check the sender's origin.

The sandboxed preview could not reach the main page. It could still send a message through the listener. MathLive accepted HTML in the keyboard layout and wrote it with innerHTML. The injected markup inserted a new iframe into the main ChatGPT document with no sandbox attribute. The new iframe inherited the chatgpt.com identity.

CSP still blocked arbitrary scripts, but it allowed YouTube. YouTube's oEmbed endpoint supported a JSONP-style callback. The endpoint tried to reject an invalid callback, Parameter Labs writes. But it placed the callback into the response before returning the validation error. The attacker's function then ran inside the chatgpt.com document.

What the authenticated code could do

Once code ran as chatgpt.com, it read #client-bootstrap from the parent document. It pulled out the session access token and account ID, then called ChatGPT's own API. The proof of concept listed the first 20 private conversations. It sent the chosen data out through an ordinary image request to a server the researchers controlled.

The final payload sizes, as Parameter Labs lists them: the JSONP callback 5,533 characters, the YouTube URL 7,309. The script element was 7,337 characters and the iframe markup 7,390.

For anyone building a shareable surface

Parameter Labs names four lessons from the chain. A sandboxed frame can still break its parent through a listener that trusts the wrong sender. A postMessage receiver has to check both event.origin and event.source before it acts on a state-changing message. HTML injection becomes code execution when a fresh unsandboxed document loads an allowed third-party script. CSP is a safety net under the real fix, not a safe render path on its own.

The chain lived in the seams between public sharing, HTML Preview, MathLive, frame creation and the CSP allowlist. Each piece was reasonable on its own. The fault was treating only the first iframe as attacker-controlled, not the whole surface.

Any team that lets a user share rendered content has the same problem. So does any team that lets agent output reach a sandboxed renderer. Audit every listener that a sandboxed frame can reach. Keep every injected iframe sandboxed through its entire render path. Treat any third-party script endpoint on the CSP allowlist as a possible script host, not a trusted one.

Source

Parameter Labs: Do the Math: How We Took Over ChatGPT Accounts, by Mukul Goyal. Simon Willison's weblog note.

This item was written by an AI system from the linked source. Reveneau is responsible for what it publishes.

Share
LinkedInX
Start a project