DEV Community

Rvn
Rvn

Posted on

🧠 You're Trusting `localStorage`… You Shouldn’t 😬

We’ve all done it.
Quick login logic. JWT or token in hand.
localStorage.setItem("token", yourToken) — boom, done. Feels safe. Feels clean. Feels… modern.

But here’s the hard truth:

Anything in localStorage is accessible to any script on the page — malicious or not.

This isn’t a nitpick. This is a real attack vector you may have just handed over to a rogue third-party script, a careless plugin, or even a compromised CDN. Let's break this down.


🚨 The False Sense of Security

localStorage is often mistaken for a secure place to keep sensitive data like:

  • JWT access tokens
  • User credentials
  • Refresh tokens
  • Session states

It’s fast, persistent, and easy to use — but it’s also entirely exposed to the browser’s JavaScript environment. That means:

console.log(localStorage.getItem("token")) 
// returns your secret like candy from a vending machine
Enter fullscreen mode Exit fullscreen mode

Now imagine this line existing inside a third-party script you included — maybe an analytics tool, a chat widget, or a library you forgot to audit.
If it can run, it can read.


🧠 Let’s Visualize It

Let’s say your login flow stores a JWT:

localStorage.setItem("accessToken", jwt);
Enter fullscreen mode Exit fullscreen mode

Now let’s say a malicious script runs on the same domain:

const stolen = localStorage.getItem("accessToken");
sendToHacker(stolen);
Enter fullscreen mode Exit fullscreen mode

That’s it. No hacking tools needed.
Just the same access your app has — but used against you.


🔐 The Safer Alternative: httpOnly Secure Cookies

If you're storing sensitive auth tokens on the client, the right move is often to:

✅ Store them in cookies
✅ Mark them as httpOnly
✅ Mark them as secure and SameSite=Strict when appropriate

Here’s why this works:

Method Can JS Access It? Sent Automatically with Requests? Ideal For
localStorage ✅ Yes ❌ No Non-sensitive app state
httpOnly Cookie ❌ No ✅ Yes Auth/session tokens

A typical Express.js or backend setup would look like this:

res.cookie("accessToken", token, {
  httpOnly: true,
  secure: true,
  sameSite: "Strict", // or "Lax" depending on your use case
});
Enter fullscreen mode Exit fullscreen mode

Now that cookie is:

  • Sent only to your server
  • Inaccessible from JavaScript
  • Protected from XSS-based token theft

🤯 Common Objection: “But I Need It in JS!”

Sometimes devs say:

"I use my token in frontend API calls, so I need to read it in JavaScript."

But if you must access your token in the client, at least:

  • Never persist it beyond the session (sessionStorage > localStorage)
  • Consider encrypted IndexedDB + user-specific key
  • Store minimal privilege tokens client-side
  • Protect the token lifecycle with refresh tokens that are httpOnly

Still, the ideal solution for most use cases is to design your API and frontend so that auth happens via httpOnly cookies, with CSRF protection in place.


💡 Bonus Tip: Use Subresource Integrity (SRI)

If you include third-party scripts from CDNs, always use Subresource Integrity (SRI) hashes:

<script src="https://cdn.example.com/library.js"
        integrity="sha384-abc123..."
        crossorigin="anonymous"></script>
Enter fullscreen mode Exit fullscreen mode

This ensures the script hasn’t been tampered with.


✅ TL;DR — Fix the Front Too

🔓 localStorage is like a safe with no lock — anyone with JavaScript access can peek in.

Instead:

  • 🛡 Store sensitive data in httpOnly cookies
  • 🔒 Use secure and SameSite flags
  • 🚫 Keep tokens out of the JS runtime if possible
  • 🎯 Be intentional with what your frontend really needs to know

🎬 Watch It as a Short (Cinematic Edition)

I broke this down into a powerful 11-second dev short — no fluff, just clarity.
🎥 Check it out on [YouTube Shorts / TikTok] — or search for:
"You’re Trusting localStorage... You Shouldn’t 😬"


Thanks for reading!
If this saved your app from a silent data leak, share it with a dev who needs it.
Security isn’t just backend business — the frontend is your first line of defense.

👋 Follow me for more dev shorts, breakdowns, and modern web tactics.
Let’s write safer, smarter code — one line at a time.

Top comments (2)

Collapse
 
dotallio profile image
Dotallio

Hits close to home, been guilty of this for quick demos. Do you have any tips for auth flows where the client legitimately needs the token for APIs?

Collapse
 
00rvn00 profile image
Rvn

🙂‍↕️