TL;DR
localStorage is accessible to any JavaScript on your page, including XSS payloads. Never store auth tokens, secrets, or sensitive PII there. Use it only for non-sensitive preferences. For auth, use HttpOnly cookies. These prompts help you audit and fix storage issues.
Storage Security Audit
Copy this prompt to have your AI scan your codebase for insecure localStorage and sessionStorage usage. You'll get a report flagging every instance where tokens, API keys, or PII are stored client-side, along with safer alternatives.
Audit Storage Usage
Audit my codebase for insecure localStorage/sessionStorage usage.
Search for:
- localStorage.setItem
- localStorage.getItem
- sessionStorage.setItem
- sessionStorage.getItem
- window.localStorage
- window.sessionStorage
For each usage, identify:
- What data is being stored
- Is it sensitive? (tokens, PII, secrets)
- Can it be accessed by XSS?
- Is there a safer alternative?
Flag as dangerous:
- Auth tokens (JWT, session IDs)
- API keys
- User PII (email, phone, address)
- Payment information
- Passwords or password hints
OK to store:
- UI preferences (theme, language)
- Non-sensitive cached data
- Draft content (with user consent)
Move Tokens to HttpOnly Cookies
Use this prompt to migrate your auth tokens from localStorage to HttpOnly cookies. Your AI will produce updated login endpoints, API request handlers, and a step-by-step migration plan including CSRF protection.
Replace localStorage Tokens
Move auth tokens from localStorage to HttpOnly cookies.
Current (insecure):
// Storing JWT in localStorage
localStorage.setItem('token', jwt);
// Sending in header
fetch('/api', { headers: { Authorization: Bearer ${localStorage.getItem('token')} }});
New approach (secure): // Server sets HttpOnly cookie on login Set-Cookie: token=jwt; HttpOnly; Secure; SameSite=Lax; Path=/
// Client just makes requests, cookie auto-sent fetch('/api', { credentials: 'include' });
// Server reads from cookie instead of header const token = req.cookies.token;
Migration steps:
- Update login endpoint to set HttpOnly cookie
- Update API to read from cookie
- Remove localStorage token code
- Add CSRF protection (needed with cookies)
- Update logout to clear cookie server-side
XSS = localStorage compromise: If your site has any XSS vulnerability, attackers can read everything in localStorage. HttpOnly cookies are immune to XSS JavaScript access.
Safe Storage Patterns
Copy this prompt to generate a safe localStorage wrapper that blocks sensitive data from being stored client-side. You'll get a drop-in utility with forbidden-key detection and JSON serialization handling.
Safe localStorage Usage
Implement a safe wrapper for localStorage.
Safe storage wrapper: const storage = { // Never store these types FORBIDDEN_KEYS: 'token', 'jwt', 'apiKey', 'password', 'secret',
set(key, value) {
if (this.FORBIDDEN_KEYS.some(k => key.toLowerCase().includes(k))) {
console.error(Security: Cannot store '${key}' in localStorage);
return;
}
try {
localStorage.setItem(key, JSON.stringify(value));
} catch (e) {
// Storage full or disabled
console.warn('localStorage unavailable');
}
},
get(key) { try { const item = localStorage.getItem(key); return item ? JSON.parse(item) : null; } catch { return null; } },
remove(key) { localStorage.removeItem(key); } };
Use this wrapper instead of direct localStorage access.
Token Storage Alternatives
This prompt asks your AI to compare all browser token storage options ranked by security. You'll get a clear breakdown of HttpOnly cookies, in-memory storage, sessionStorage, and localStorage with a recommended hybrid pattern.
Secure Token Storage Options
Compare secure options for storing auth tokens.
Options ranked by security:
- HttpOnly Cookie (Best)
- Can't be accessed by JavaScript
- Automatically sent with requests
- Needs CSRF protection
- Works well for SSR and traditional apps
- Memory (Good for SPAs)
- Store token in JavaScript variable/state
- Lost on page refresh (may want this)
- Pair with silent refresh for persistence
- Immune to XSS persistence (token lost if page closes)
- SessionStorage (Better than localStorage)
- Cleared when tab closes
- Still vulnerable to XSS
- Better for short-lived tokens
- localStorage (Avoid for tokens)
- Persists forever
- Fully exposed to XSS
- Only use for non-sensitive data
Recommended pattern:
- HttpOnly cookie for refresh token
- Memory for access token
- Silent refresh to get new access token
Pro tip: Use the BFF (Backend for Frontend) pattern. Your frontend talks to your backend, which handles all token storage and third-party API calls. Tokens never touch the browser.
Can I encrypt data in localStorage?
You can, but the encryption key must be in JavaScript, so an XSS attacker can just decrypt it too. Encryption in localStorage is security theater. Use HttpOnly cookies for sensitive data.
What about IndexedDB?
IndexedDB has the same security model as localStorage - accessible to any JavaScript. It's just for larger amounts of data. Same rules apply: no sensitive data.
Further Reading
Want to understand the vulnerability before fixing it? These guides explain what's happening and why.
Find Insecure Storage
Scan your frontend for sensitive data in localStorage.