[{"data":1,"prerenderedAt":421},["ShallowReactive",2],{"blog-prompts/secure-local-storage":3},{"id":4,"title":5,"body":6,"category":400,"date":401,"dateModified":402,"description":403,"draft":404,"extension":405,"faq":406,"featured":404,"headerVariant":407,"image":406,"keywords":406,"meta":408,"navigation":409,"ogDescription":410,"ogTitle":406,"path":411,"readTime":406,"schemaOrg":412,"schemaType":413,"seo":414,"sitemap":415,"stem":416,"tags":417,"twitterCard":419,"__hash__":420},"blog/blog/prompts/secure-local-storage.md","Secure Local Storage Usage with AI Prompts",{"type":7,"value":8,"toc":391},"minimark",[9,16,21,24,107,111,114,158,168,172,175,218,222,225,312,321,337,341,344,365,379],[10,11,12],"tldr",{},[13,14,15],"p",{},"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.",[17,18,20],"h2",{"id":19},"storage-security-audit","Storage Security Audit",[13,22,23],{},"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.",[25,26,28,31,34,56,59,73,76,93,96],"prompt-box",{"title":27},"Audit Storage Usage",[13,29,30],{},"Audit my codebase for insecure localStorage/sessionStorage usage.",[13,32,33],{},"Search for:",[35,36,37,41,44,47,50,53],"ul",{},[38,39,40],"li",{},"localStorage.setItem",[38,42,43],{},"localStorage.getItem",[38,45,46],{},"sessionStorage.setItem",[38,48,49],{},"sessionStorage.getItem",[38,51,52],{},"window.localStorage",[38,54,55],{},"window.sessionStorage",[13,57,58],{},"For each usage, identify:",[35,60,61,64,67,70],{},[38,62,63],{},"What data is being stored",[38,65,66],{},"Is it sensitive? (tokens, PII, secrets)",[38,68,69],{},"Can it be accessed by XSS?",[38,71,72],{},"Is there a safer alternative?",[13,74,75],{},"Flag as dangerous:",[35,77,78,81,84,87,90],{},[38,79,80],{},"Auth tokens (JWT, session IDs)",[38,82,83],{},"API keys",[38,85,86],{},"User PII (email, phone, address)",[38,88,89],{},"Payment information",[38,91,92],{},"Passwords or password hints",[13,94,95],{},"OK to store:",[35,97,98,101,104],{},[38,99,100],{},"UI preferences (theme, language)",[38,102,103],{},"Non-sensitive cached data",[38,105,106],{},"Draft content (with user consent)",[17,108,110],{"id":109},"move-tokens-to-httponly-cookies","Move Tokens to HttpOnly Cookies",[13,112,113],{},"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.",[25,115,117,120,128,131,134,137,140],{"title":116},"Replace localStorage Tokens",[13,118,119],{},"Move auth tokens from localStorage to HttpOnly cookies.",[13,121,122,123,127],{},"Current (insecure):\n// Storing JWT in localStorage\nlocalStorage.setItem('token', jwt);\n// Sending in header\nfetch('/api', { headers: { Authorization: ",[124,125,126],"code",{},"Bearer ${localStorage.getItem('token')}"," }});",[13,129,130],{},"New approach (secure):\n// Server sets HttpOnly cookie on login\nSet-Cookie: token=jwt; HttpOnly; Secure; SameSite=Lax; Path=/",[13,132,133],{},"// Client just makes requests, cookie auto-sent\nfetch('/api', { credentials: 'include' });",[13,135,136],{},"// Server reads from cookie instead of header\nconst token = req.cookies.token;",[13,138,139],{},"Migration steps:",[141,142,143,146,149,152,155],"ol",{},[38,144,145],{},"Update login endpoint to set HttpOnly cookie",[38,147,148],{},"Update API to read from cookie",[38,150,151],{},"Remove localStorage token code",[38,153,154],{},"Add CSRF protection (needed with cookies)",[38,156,157],{},"Update logout to clear cookie server-side",[159,160,161],"warning-box",{},[13,162,163,167],{},[164,165,166],"strong",{},"XSS = localStorage compromise:"," If your site has any XSS vulnerability, attackers can read everything in localStorage. HttpOnly cookies are immune to XSS JavaScript access.",[17,169,171],{"id":170},"safe-storage-patterns","Safe Storage Patterns",[13,173,174],{},"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.",[25,176,178,181,189,196,206,209,212,215],{"title":177},"Safe localStorage Usage",[13,179,180],{},"Implement a safe wrapper for localStorage.",[13,182,183,184,188],{},"Safe storage wrapper:\nconst storage = {\n// Never store these types\nFORBIDDEN_KEYS: ",[185,186,187],"span",{},"'token', 'jwt', 'apiKey', 'password', 'secret'",",",[13,190,191,192,195],{},"set(key, value) {\nif (this.FORBIDDEN_KEYS.some(k => key.toLowerCase().includes(k))) {\nconsole.error(",[124,193,194],{},"Security: Cannot store '${key}' in localStorage",");\nreturn;\n}",[197,198,203],"pre",{"className":199,"code":201,"language":202},[200],"language-text","try {\n  localStorage.setItem(key, JSON.stringify(value));\n} catch (e) {\n  // Storage full or disabled\n  console.warn('localStorage unavailable');\n}\n","text",[124,204,201],{"__ignoreMap":205},"",[13,207,208],{},"},",[13,210,211],{},"get(key) {\ntry {\nconst item = localStorage.getItem(key);\nreturn item ? JSON.parse(item) : null;\n} catch {\nreturn null;\n}\n},",[13,213,214],{},"remove(key) {\nlocalStorage.removeItem(key);\n}\n};",[13,216,217],{},"Use this wrapper instead of direct localStorage access.",[17,219,221],{"id":220},"token-storage-alternatives","Token Storage Alternatives",[13,223,224],{},"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.",[25,226,228,231,234,298,301],{"title":227},"Secure Token Storage Options",[13,229,230],{},"Compare secure options for storing auth tokens.",[13,232,233],{},"Options ranked by security:",[141,235,236,253,270,284],{},[38,237,238,239],{},"HttpOnly Cookie (Best)",[35,240,241,244,247,250],{},[38,242,243],{},"Can't be accessed by JavaScript",[38,245,246],{},"Automatically sent with requests",[38,248,249],{},"Needs CSRF protection",[38,251,252],{},"Works well for SSR and traditional apps",[38,254,255,256],{},"Memory (Good for SPAs)",[35,257,258,261,264,267],{},[38,259,260],{},"Store token in JavaScript variable/state",[38,262,263],{},"Lost on page refresh (may want this)",[38,265,266],{},"Pair with silent refresh for persistence",[38,268,269],{},"Immune to XSS persistence (token lost if page closes)",[38,271,272,273],{},"SessionStorage (Better than localStorage)",[35,274,275,278,281],{},[38,276,277],{},"Cleared when tab closes",[38,279,280],{},"Still vulnerable to XSS",[38,282,283],{},"Better for short-lived tokens",[38,285,286,287],{},"localStorage (Avoid for tokens)",[35,288,289,292,295],{},[38,290,291],{},"Persists forever",[38,293,294],{},"Fully exposed to XSS",[38,296,297],{},"Only use for non-sensitive data",[13,299,300],{},"Recommended pattern:",[35,302,303,306,309],{},[38,304,305],{},"HttpOnly cookie for refresh token",[38,307,308],{},"Memory for access token",[38,310,311],{},"Silent refresh to get new access token",[313,314,315],"tip-box",{},[13,316,317,320],{},[164,318,319],{},"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.",[322,323,324,331],"faq-section",{},[325,326,328],"faq-item",{"question":327},"Can I encrypt data in localStorage?",[13,329,330],{},"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.",[325,332,334],{"question":333},"What about IndexedDB?",[13,335,336],{},"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.",[17,338,340],{"id":339},"further-reading","Further Reading",[13,342,343],{},"Want to understand the vulnerability before fixing it? These guides explain what's happening and why.",[35,345,346,353,359],{},[38,347,348],{},[349,350,352],"a",{"href":351},"/blog/vulnerabilities/exposed-api-keys","Understanding exposed API keys",[38,354,355],{},[349,356,358],{"href":357},"/blog/how-to/hide-api-keys","How to hide API keys step-by-step",[38,360,361],{},[349,362,364],{"href":363},"/blog/best-practices/secrets","Secret management best practices",[366,367,368,374],"related-articles",{},[369,370],"related-card",{"description":371,"href":372,"title":373},"HttpOnly cookie setup","/blog/prompts/secure-cookies","Secure Cookies",[369,375],{"description":376,"href":377,"title":378},"Prevent XSS attacks","/blog/prompts/fix-xss-vulnerabilities","Fix XSS Vulnerabilities",[380,381,384,388],"cta-box",{"href":382,"label":383},"/","Start Free Scan",[17,385,387],{"id":386},"find-insecure-storage","Find Insecure Storage",[13,389,390],{},"Scan your frontend for sensitive data in localStorage.",{"title":205,"searchDepth":392,"depth":392,"links":393},2,[394,395,396,397,398,399],{"id":19,"depth":392,"text":20},{"id":109,"depth":392,"text":110},{"id":170,"depth":392,"text":171},{"id":220,"depth":392,"text":221},{"id":339,"depth":392,"text":340},{"id":386,"depth":392,"text":387},"prompts","2026-02-27","2026-03-06","AI prompts to use localStorage and sessionStorage securely. Understand what data should never be stored client-side and safe alternatives.",false,"md",null,"cyan",{},true,"AI prompts to handle browser storage securely.","/blog/prompts/secure-local-storage","[object Object]","BlogPosting",{"title":5,"description":403},{"loc":411},"blog/prompts/secure-local-storage",[418],"Frontend","summary_large_image","v6iWUMVSxVY5PUJHlI1odCaJ7VJ0NiEIUcnFWNH9xt4",1775843937937]