News

A shared ChatGPT link could run attacker code and read your private chats

Security firm Parameter turned an ordinary public ChatGPT share link into attacker JavaScript that ran inside the signed in session of whoever opened it, listed their chats and read a private conversation. OpenAI rated it P1, fixed it on October 26 and paid a $5,000 bounty. No real world abuse was reported.

Shared ChatGPT conversations feel about as harmless as a link can get. Someone sends you a chat, you open it, you read what the model said. That is exactly why the research published by the security firm Parameter this week is worth a careful look. Its team showed that a single public ChatGPT share link could run the attacker's own JavaScript inside the signed in session of anyone who opened it. In their proof, that code listed the victim's recent conversations, opened a private chat that had never been shared with anyone, and sent part of it to a server the researchers controlled.

OpenAI fixed the problem on October 26, 2026, rated it P1, its most serious severity class, and paid a total bug bounty of $5,000. Parameter published its full writeup on October 28, and The Hacker News covered it on October 31. There is no report of anyone using the flaw against real users, and ChatGPT users do not need to do anything now. But the way the attack worked says a lot about how hard it is to keep a modern AI product safe when it keeps adding features that run code.

The ChatGPT share link bug at a glance: one public share link was the whole attack, zero or one clicks were needed, attacker code ran after about 4.5 seconds in the automatic Preview version, OpenAI rated it P1 after first triaging it as P2, the fix came 8 days after the report, the bounty was $5,000 and no real world attacks were reported

What Parameter found

The writeup, titled Do the Math: How We Took Over ChatGPT Accounts and written by Mukul Goyal, describes the attack in plain terms. An attacker creates a conversation in ChatGPT, publishes it with the normal share feature, and sends the resulting link to a target. That link could travel the way any shared chat travels: in an email, in a team chat, in a support ticket or in a social media post.

When the victim opened it, the payload executed as chatgpt.com, with the same access to the victim's account that the real ChatGPT web app has. The victim did not have to install a ChatGPT App, join a Project or workspace, paste anything, or open developer tools. In the most stable version of the attack, the victim opened the share and clicked ChatGPT's normal Preview button once. In a later version, the researchers marked the HTML block so that ChatGPT opened the Preview by itself. Then opening the link was the only action needed. Parameter says it reproduced that automatic path three times in a separate account, including after a hard refresh, and that its test alert appeared after about 4.5 seconds.

The researchers stress that an alert box was never the point. Because the code ran as chatgpt.com, it could call ChatGPT's own authenticated backend APIs as the victim. In their words, they could essentially perform any action on behalf of the victim's ChatGPT account. The proof stayed deliberately small: it only sent a short selected value from a private conversation to their server. But the code had already received the full response, so the limit was a choice by the researchers, not a limit of the bug.

Two harmless features, one dangerous bridge

The clever part of this chain is that no single feature was broken in an obvious way. ChatGPT has a Preview feature that turns an HTML code block in a chat into a small working web page. Since that page can contain any code, OpenAI runs it inside a restricted frame on a different web address. The browser treats it as a separate website, so code in the Preview cannot read the main ChatGPT page around it. Parameter tested this and found that the isolation held.

The way across came from a second feature. The malicious conversation also contained a normal interactive graph. To draw it, ChatGPT loaded an open source math library called MathLive, and MathLive installed a listener in the main ChatGPT page that waits for messages about its on screen math keyboard. Browsers let frames send each other such messages through an interface called postMessage. Parameter compares it to a mail slot: the sandboxed Preview cannot walk into the main page, but it can still drop a letter through the slot. That is only safe if the receiver checks who sent the letter.

MathLive did not check. Its controller accepted keyboard messages from any web address and did not require them to come from a window it had connected to before. One of those messages could replace the keyboard layout, and the layout was allowed to contain HTML. When the keyboard was shown, MathLive put that HTML into the real ChatGPT page. A helper function that looked like it might clean the HTML turned out to pass it through unchanged.

Diagram of the five step exploit chain: an attacker publishes a shared chat with a graph and an HTML block, the graph loads MathLive which installs a keyboard message listener in the chatgpt.com page, the sandboxed Preview sends a keyboard layout containing raw HTML, MathLive writes that HTML into the page and creates an unsandboxed srcdoc iframe that counts as chatgpt.com, and an allowed YouTube oEmbed callback runs the payload past the content security policy

From HTML to running code

Injecting HTML is not yet the same as running code. Script tags that arrive this way do not execute. So the researchers used the HTML to create a new embedded frame with a feature called srcdoc, which carries the content of the frame directly in an attribute. MathLive created that frame without a sandbox attribute. Because the main ChatGPT page created it, the browser gave the new frame the identity of chatgpt.com, which meant code inside it could reach the parent page.

One more barrier remained. ChatGPT uses a content security policy, a list that tells the browser which scripts a page may load. That policy correctly blocked inline JavaScript, but it allowed scripts from YouTube. Parameter found that YouTube's oEmbed endpoint accepted a callback parameter and echoed it back as JavaScript before returning its error message. By ending the callback with a small trick that neutralized the rest of the response, the researchers turned a YouTube URL into a script that ran their code. The final callback was 5,533 characters long, wrapped inside a YouTube URL of 7,309 characters.

Parameter is careful to say that the YouTube step was a workaround, not the root cause. Blocking that one endpoint would have removed one route to JavaScript, but an untrusted Preview would still have been able to push HTML into the main ChatGPT page.

How the share link made it real

The first working version needed a researcher controlled ChatGPT App to send the messages, which would have required the victim to connect that App. That is a much weaker attack. Parameter then tried an HTML attachment, but when the chat was exported as a public share, the attachment survived while the earlier graph did not, and without the graph nothing was listening for the messages.

The breakthrough was to put both pieces into one ordinary public conversation: a genuine graph that loaded MathLive, followed by an assistant written HTML block that sent the two messages. The share link preserved the whole chain for anyone who opened it. Because the graph and the Preview loaded independently, the payload sometimes fired before MathLive was ready, so the final version simply retried the messages for a short time.

What OpenAI fixed, and how fast

Parameter's timeline shows a fairly quick response. The researchers confirmed the MathLive path against ChatGPT's production code on October 13, showed delivery through a public share between separate accounts on October 16, and submitted the report to OpenAI's bug bounty program on October 18. They added the private chat proof on October 19. On October 21, OpenAI reproduced the issue and raised its severity from the initial P2 triage to P1.

The fix had to roll out across two versions of ChatGPT's web frontend. On October 22, OpenAI reported one frontend fixed. On October 23, changes to the content security policy blocked part of the chain while the second update was still pending. On October 26, OpenAI confirmed that both frontends rejected the cross frame MathLive messages, closed the report and paid the bounty.

Timeline of the disclosure: October 13 Parameter confirms the MathLive message path in production, October 16 the attack works through a public share between accounts, October 18 report submitted to OpenAI, October 21 OpenAI reproduces it and raises severity to P1, October 26 both web frontends fixed and $5,000 bounty paid, October 28 Parameter publishes the writeup, October 31 MathLive 0.111.2 hardens its message handling

The library itself has also changed. The MathLive changelog lists version 0.111.2, released on October 31, with a security section that matches the report. Keyboard, proxy and mathfield messages now default to same origin validation, so cross origin setups must name their trusted partners explicitly. Messages that change state are bound to the connected window, so another frame cannot take over while the keyboard is visible. And cross window settings can still pick built in layouts but can no longer supply custom HTML layouts, even if origin checks are switched off. Any other website that embeds MathLive with its virtual keyboard should update.

Comparison of what went wrong and what changed: the keyboard listener accepted messages from any origin and window, now messages default to same origin and must come from the connected window; layout settings could carry raw HTML, now cross window settings cannot supply custom layouts; the generated frame had no sandbox and inherited chatgpt.com, now OpenAI's frontends reject the cross frame messages

Why a $5,000 bounty raised eyebrows

The payout is the detail many readers noticed first. A bug that lets anyone take over the session of a signed in ChatGPT user with one link is about as serious as web bugs get for a service with hundreds of millions of users. OpenAI's own P1 rating reflects that. Yet the reward was $5,000 in total. Parameter does not complain about the amount in its writeup, and bounty tables usually depend on factors like the exact impact proven and the program's own rules. Still, it is a modest sum for a chain this deep, and it is the kind of number that decides whether skilled researchers report a bug or sell it.

Simon Willison, who has written for years about prompt injection and the risks of letting AI tools render untrusted content, summarized the chain on October 31 and pointed to the core problem: the message receiving code used innerHTML, so anything that could send a message could add HTML to the parent page, and nothing stopped sandboxed frames such as HTML previews from doing so.

Why it matters

The lesson goes beyond one library. AI chat products are turning into small operating systems. They render charts, run previews, execute code, load third party components and let users share all of it with a single link. Every one of those features can be safe in isolation. Parameter's chain only existed in the seams between public sharing, Preview, MathLive, frame creation and the content security policy.

For security teams, the practical points are clear. A shared ChatGPT link should be treated like any other link from an unknown sender, because it runs inside the visitor's own authenticated session. Developers who build similar features should check both the origin and the exact source window of every postMessage they accept, should never let cross window settings carry raw HTML, and should keep dynamically created frames sandboxed whenever untrusted content can influence them. A content security policy is a useful second line of defense, but as this case shows, an allowed third party domain can be enough to defeat it.

There is also a privacy angle. People put very personal things into chatbots: health questions, contracts, code, business plans. A bug that reads private conversations is in some ways worse than a classic account takeover on a social network, because the data is so concentrated and so candid.

Dany's take

I like this research because it is honest about how boring each piece looks. A graph, a math keyboard, a preview window, a YouTube embed. None of that sounds like an attack surface, and that is exactly the point. The more features AI apps ship every week, the more of these seams appear, and the people who find them are often small teams like Parameter, not the vendors.

OpenAI deserves credit for reproducing the issue quickly, upgrading it to P1 and fixing it in eight days. But I think $5,000 for a one link account takeover with private chat access is too low, and it sends the wrong signal at a moment when AI companies want the security community to trust them with their most sensitive work. My personal rule after reading this: treat shared AI chats like attachments from strangers, and if you build anything with postMessage, go and check your listeners tonight.

Sources: Parameter Labs writeup, The Hacker News, MathLive changelog 0.111.2, Simon Willison.

Source: parameter.ai

Newsletter

The AI news that matters, in your inbox.