Open the Link, Lose the Account: A Math Library's Mail Slot Turned a ChatGPT Share Into Code Execution
The most dangerous link in October looked exactly like a helpful one: an ordinary ChatGPT conversation, shared through the product's normal public-link feature. Security firm Parameter showed on 28 October 2026 that opening it could run an attacker's JavaScript inside the victim's signed-in ChatGPT session — enumerating conversation lists, pulling content from a private chat that was never shared, and calling ChatGPT's own authenticated APIs as the victim. The researchers reported it through OpenAI's bug bounty on 18 October; OpenAI reproduced both the code execution and the private-chat exfiltration, raised the severity from P2 to P1, and had fixes rolled out across both web frontend versions by 26 October. No real-world exploitation is reported — the private-chat proof ran between researcher-controlled accounts — but the chain is a textbook study in how two harmless features compose into account takeover.
The sandbox did its job; the mail slot did not. ChatGPT renders an HTML code block as a working page through its Preview feature, and because that page can contain arbitrary code, it runs in a restricted frame on a separate origin — the Preview genuinely could not read the parent page. The way in came from a second feature in the same conversation: an interactive graph that loaded the MathLive math library into the main ChatGPT page, installing a postMessage listener for on-screen-keyboard traffic. As Parameter tells it, that listener accepted a keyboard-layout message from any sender without checking origin, and the layout payload was allowed to carry raw HTML. The Preview therefore had a path across the boundary: send two messages — one replacing the virtual keyboard layout with attacker HTML, one telling MathLive to display the keyboard — and the trusted main page rendered the payload via innerHTML. A helper named createHTML looked like it might sanitize the value; per the writeup, it marked the string as trusted and passed it through unchanged.
innerHTML does not run scripts — so the chain built a new document
Script tags injected through innerHTML do not execute, so the next step was an iframe using srcdoc, inserted into the main ChatGPT document without a sandbox attribute. Because the main page created the frame, the browser granted it the https://chatgpt.com identity, and code inside it could reach the parent page. Then came the Content Security Policy: it correctly blocked inline JavaScript but permitted scripts from YouTube, and YouTube's oEmbed endpoint reflected a JSONP-style callback parameter into its response before its own validation error. Terminating the callback with ;void neutralized the trailing object, and since YouTube was already CSP-allowed, the browser loaded the response as a script — arbitrary JavaScript running as chatgpt.com. Parameter is explicit that the YouTube step was workaround, not cause: the defect was an untrusted Preview able to push HTML into the main site through three compounding choices — an unchecked sender, an HTML-capable settings message, and an unsandboxed srcdoc frame.
Delivery was the product's own sharing UX
What elevates this above a lab curiosity is that the whole chain survived inside one public /share/ link, deliverable by email, chat message, support ticket, or social post. The victim installed nothing, joined nothing, and never opened developer tools. In the most reliable version the victim clicked ChatGPT's Preview button once; Parameter later got the page to open Preview on its own, reducing the interaction to opening the link. From a defensive standpoint this is the same lesson as the trojanized Claude Code build planted in a marketplace — the trusted channel is the weapon — except here no software was even installed. It also sharpens the picture painted by October's misalignment reports: the frontier systems are being asked to police their own boundaries, and the boundaries keep being drawn in the wrong place.
What to do
- ChatGPT users: nothing to install or reset. The fix is server-side; both frontend versions reject the attack messages as of 26 October. Treat any shared chat link with the suspicion you would give an unexpected attachment.
- Audit every postMessage listener for sender checks. A listener that acts on
update-setting-style messages with an origin policy of none is a sandbox escape waiting for a second feature. Parameter's suggested 20-line listener audit is the right shape: enumerate listeners, require origin and source-window validation, and never accept HTML through settings payloads. - Sandbox srcdoc frames and distrust trusted-type helpers. Frames created from markup strings need explicit
sandboxattributes, and anycreateHTML-style helper that marks input trusted without sanitizing is a bypass, not a control. - Allowlist CSP sources as attack surface, not decoration. Every entry in
script-src— including JSONP-capable endpoints like oEmbed — is a potential script gadget. Review them with the assumption that an attacker already has an injection point.
Sources:
- Parameter Labs — "Do the Math: How We Took Over ChatGPT Accounts" (28 October 2026; reported 18 October, fixed 26 October, P1; read first-hand)
- The Hacker News — "A Shared ChatGPT Link Could Run Attacker Code in Your Session and Read Private Chats" (31 October 2026; P2-to-P1 escalation, $5,000 bounty, auto-Preview variant; read first-hand)