Do the math: How we took over ChatGPT accounts
Parameter Labs describes a chain that turned a public ChatGPT share link into JavaScript running as chatgpt.com in the victim's session. It combined a MathLive postMessage listener with no origin or source check, raw HTML in keyboard layouts, an unsandboxed srcdoc iframe, and a YouTube oEmbed JSONP callback to pass the CSP. The code read private conversations through backend APIs. OpenAI fixed it on 26 October 2026 and rated it P1.
What it is
Parameter Labs found a chain in the ChatGPT web frontend, fixed by OpenAI on 26 October 2026 and rated P1. A public /share/<id> conversation could run JavaScript as chatgpt.com in the session of anyone who opened it. The page names no CVE. The fix was server-side, so ChatGPT users have nothing to do.
How it works
The chain turns on two parts of one shared conversation that each look harmless alone.
flowchart LR
A[Graph loads MathLive in main page] --> C[Listener accepts message]
B[Preview iframe sends 2 messages] --> C
C --> D[HTML set via innerHTML]
D --> E[Unsandboxed srcdoc iframe, chatgpt.com origin]
E --> F[YouTube oEmbed JSONP passes CSP]
F --> G[Authenticated backend-api calls]- The graph makes MathLive install a
postMessagelistener in the main ChatGPT page. Its top-level controller used an origin policy of none and did not require the sender to be an approved window. - The sandboxed HTML Preview cannot read
parent.document, but it can post two messages: one replaces the virtual keyboard layout with attacker HTML, the other shows the keyboard. - MathLive joins the layout into a string and assigns it to
innerHTML. ThecreateHTMLhelper only marks the string as trusted and does not sanitize it. - The injected iframe uses
srcdocand has nosandboxattribute. It gets a fresh document with the chatgpt.com origin, so it can reach the parent. - The CSP blocks inline script but allows YouTube. The oEmbed endpoint echoed the
callbackparameter into atext/javascriptresponse before returning its validation error. Ending the callback with;voidswallowed the appended error object. Angle brackets were rewritten, so the payload avoided arrow functions. - The payload parsed
#client-bootstrapfor the access token and account ID. It calledGET /backend-api/conversations?...andGET /backend-api/conversations/<id>?num_turns=2, then sent a small slice of a private conversation to an external server through an image request.
Preconditions / Affected
- The victim only needs to open the attacker's share link while signed in to ChatGPT on the web. No app, project or pasted code is needed.
- The first version used a researcher-controlled ChatGPT App as the sender. That was dropped once the graph and the assistant-authored HTML Preview were placed in one ordinary conversation.
- The researchers reproduced the one-click variant (victim clicks Preview). They also reproduced an auto-open variant three times in a separate account, with the alert after about 4.5 seconds. The payload retried its messages for a limited period to win the load race with MathLive.
- A native HTML attachment did not work alone, because the graph that installs the listener was lost on export to a public share.
What to do
The page's own guidance for anyone building similar surfaces:
- Check both
event.originandevent.sourcebefore acting on state-changingpostMessagedata. - Do not accept raw HTML in cross-window settings.
- Keep dynamically created frames sandboxed when an untrusted frame can influence their content.
- Treat CSP as a backup. Blocking only the YouTube endpoint would have left an untrusted Preview able to insert HTML into the page.
Caveats
- OpenAI rolled the fix out across two frontend versions. CSP changes blocked part of the chain during rollout, and on 26 October OpenAI confirmed both versions rejected the cross-frame MathLive messages.
- The proof read one private conversation and exfiltrated a small value. The claim of acting as the victim on other authenticated APIs is the authors' reasoning and was not demonstrated.
Organisations named here
- OpenAI
- Parameter Labs
Technologies named here
- ChatGPT
- YouTube
- JavaScript
- MathLive
- YouTube oEmbed (Google)
Techniques named here
- Cross-site scripting
- Sandbox escape
- Account takeover via shared link
- JSONP callback abuse for CSP bypass
- JSONP CSP bypass
- postMessage origin validation
- postMessage origin validation bypass
Concepts named here
- Content Security Policy (CSP)
- Origin validation
- Sandbox escape
Related in AppSec
Flowise MCP Security Bypass Enables RCE
Inside an Oracle Database SQL Injection Attack | Huntress
OASIS
