Sitemap
MeetCyber

hack the present, secure the future

Reflections from the Field: Why Web Storage Is a Goldmine on Our Penetration Tests

--

Press enter or click to view image in full size

Ryan Chaplin, one of our lead penetration testers at Raxis, just published a fantastic breakdown on the dangers of storing sensitive data in web storage — specifically localStorage and sessionStorage. If you’re a CISO keeping tabs on your organization’s web app security, this is a must-read topic that’s as relevant in 2025 as it was five years ago.

Let’s take a stroll through Ryan’s findings, sprinkle in a few war stories, and talk about what this means for both red and blue teams.

Web Storage: The Double-Edged Sword

Web storage was supposed to make life easier for developers and users alike, and it does with persistent data, instant access, and no more clunky cookies. But, as Ryan points out, convenience is often the enemy of security. Unlike HTTP-only cookies, web storage is fully accessible to JavaScript, which means if you have an XSS (cross-site scripting) vulnerability, you might as well be handing attackers the keys to the kingdom.

Five Scenarios from the Trenches

Ryan’s blog walks through five attack scenarios that we see in real-world engagements. Here’s my take on why each one matters.

1. XSS Attacks: JavaScript’s Open Door

Every pentester has that one XSS story. The moment you pop an alert box, pivot to document.cookie, and realize the devs have stashed JWTs, API keys, or even plaintext passwords in localStorage. Unlike cookies, web storage doesn’t have an HTTP-Only flag, so if you can inject JavaScript, you can exfiltrate everything.

Takeaway: If your app is vulnerable to XSS and you’re storing sensitive data in web storage, you’re playing with fire.

2. Session Hijacking on Shared Devices

SessionStorage is supposed to be ephemeral, but browsers aren’t perfect. If a user doesn’t close their browser (or it crashes and restores), session data can linger. LocalStorage is even worse — it sticks around until someone explicitly clears it. Ryan’s example of a banking app leaving session tokens behind is the type of thing we’ve exploited on web application penetration tests.

Takeaway: Don’t trust users to log out properly. Design your app to clean up after itself.

3. Serialized Data: The Hidden Landmine

Debug tokens, internal API keys, and sensitive metadata can all end up in localStorage. Sensitive data stored in serialized objects in localStorage can allow penetration testers (and our not-so-ethical counterparts) to obtain PII or even escalate privileges.

Takeaway: Sanitize before you serialize. If you don’t want it leaking, don’t store it.

4. Cross Domain Takeovers: One Weak Link Breaks the Chain

Get Mark Puckett’s stories in your inbox

Join Medium for free to get updates from this writer.

Web storage is shared across subdomains. If your main app is locked down but your blog isn’t, an XSS on the blog can compromise everything stored by the app.

Takeaway: Treat every subdomain as a potential attack vector. Isolate critical apps and keep your attack surface as small as possible.

5. Debugging Disasters: When Logs Leak Secrets

Logging is very useful for debugging and keeping track of incidents, but when those logs hit Sentry, Splunk, or your CI/CD pipeline, they can accidentally expose test credentials, user data, or admin tokens. Ryan’s example of a logging script capturing a developer’s admin token can happen much to easily.

Takeaway: Logging is for synthetic data only. Never log real tokens or user data, especially in production.

Best Practices: What We Tell Our Customers

Ryan’s recommendations are spot-on, and I’ll echo them here with a few of my own twists:

• Prevent XSS at All Costs: CSPs, input validation, and regular code reviews are your friends. Assume someone will eventually find a way to inject JavaScript.

• Treat Web Storage as Public: If you wouldn’t put it on a billboard, don’t put it in localStorage or sessionStorage.

• Auto-Clear on Logout: Make “clearStorage” part of your logout routine. Bonus points for clearing after periods of inactivity.

• Isolate Subdomains: Use separate domains for critical apps. Don’t let your blog or marketing site share storage with your main app.

• Lock Down Logging: Make it a policy to never log localStorage in production. Audit your logs for accidental leaks.

• Audit Regularly: Use tools like GitGuardian or TruffleHog to scan for secrets in storage and logs.

Final Thoughts: Assume Breach, Design for Resilience

If there’s one thing I’ve learned during my years as a penetration tester and now CEO of a penetration testing company, it’s that convenience always comes at a cost. Web storage is a powerful tool, but it’s not designed for secrets. Assume that anything in localStorage or sessionStorage will eventually be exposed, either through XSS, subdomain compromise, or good old-fashioned human error.

For CISOs: Make web storage a regular part of your threat modeling and penetration testing scope.

For Penetration Testers: Keep poking those storage APIs, You’ll be surprised what you find.

And if you haven’t read Ryan’s full blog yet, do yourself a favor and check it out. It’s a goldmine of real-world scenarios and practical advice for anyone serious about web application security.

--

--

Mark Puckett
Mark Puckett

Written by Mark Puckett

CEO of Raxis. Cybersecurity entrepreneur. Visit Raxis.com