FixVibe

// secrets / spotlight

Tokens im Browser-Storage

localStorage ist von JavaScript lesbar. Dort gespeicherte Auth-Tokens sind per Design XSS-stehlbar.

What it is

Storing auth tokens in localStorage is one of the most-debated patterns in web security and one of the most-shipped patterns in production. The motivation is real — cookies are fiddly, CSRF protection is annoying, cross-domain requests don't carry cookies easily — and the framework tutorials make it look easy: 'just save the JWT in localStorage and add it to your fetch headers.' The trade-off the tutorials don't make explicit: localStorage is JavaScript-readable by definition, so you've forfeited the single biggest XSS-blast-radius reduction (HttpOnly cookies). Every successful XSS in your app — DOM-based, reflected, or stored — is now a complete account takeover: any script running on your page can read the token and send it anywhere.

How it happens

localStorage is plain key-value storage accessible from any JavaScript running on the origin. Unlike cookies, there is no flag that prevents scripts from reading it; the API is `localStorage.getItem('token')` and that's it. sessionStorage has the same story (just a shorter lifetime). The exfiltration takes one line of JavaScript: an attacker who lands any flavor of XSS — even a brief one in an obscure code path — reads the token, ships it to attacker.tld, and now has session-equivalent access from anywhere. Some apps try to mitigate by using short-lived tokens, but 'short' in JS is still long enough — the attacker doesn't replay the token weeks later, they replay it in real time during the same session.

Common variants

JWT in localStorage

Most common pattern. Login response stores the JWT, fetch interceptor adds it to Authorization headers. XSS reads it, session is over.

OAuth tokens in sessionStorage

Same readable-from-JS story; just a shorter window. Some SPA frameworks default to this for OAuth flows.

Refresh token in localStorage

Worse than access tokens — refresh tokens persist longer and let the attacker mint new access tokens indefinitely.

PII in browser storage

Not just tokens. Some apps cache user PII, billing info, or document drafts in localStorage. XSS exfiltrates all of it, not just the auth token.

What an attacker gets

Full session hijack on any successful XSS. The token doesn't need to be valid for long — the exfiltration is instant. With refresh tokens stored alongside, the attacker maintains access indefinitely. PII leakage if the app caches user data in storage — emails, addresses, document content. In B2B SaaS, this becomes a multi-tenant disclosure event.

// what fixvibe reports

What FixVibe reports

Runs on every URL scan: paste your app's URL, nothing to install. The free preview shows your top findings; Hobby and above unlock the full report. Each finding shows the affected URL or host, its severity and fix steps you can paste into your AI coding tool.

How to fix it

Store auth tokens in HttpOnly + Secure + SameSite=Lax cookies. The browser sends them automatically with same-site requests; JavaScript can't read them. Treat localStorage as user-readable display state (UI preferences, last-viewed item, etc.) rather than auth state. If you have a genuine architectural need for token-in-JS (cross-domain APIs that can't use cookies, mobile webview integrations), keep the token lifetime aggressively short (5-15 min), use refresh-token rotation with detection of replay (refresh tokens are single-use; re-using a previously-used refresh token signals theft), and pair with strict CSP so the XSS that reads the token is hard to land in the first place. Under no circumstance should refresh tokens or PII live in localStorage long-term — the cost-benefit of 'easier development' versus 'XSS = total compromise' is wildly lopsided.

// lass es auf deiner eigenen App laufen

Ship weiter, während FixVibe mitwacht.

Paste your app's URL for a free preview. Nothing to install.

Secrets
39
Tests in dieser Kategorie
Module
5
dedizierte secrets-Prüfungen
every URL scan
230+
passive checks on each scan
Scan your URL free →

// aktuelle Checks · praktische Fixes · mit Vertrauen shippen

Tokens im Browser-Storage: what it is and how to fix it · FixVibe