LocalStorage vs. IndexedDB vs. Cookies vs. OPFS vs. WASM-SQLite
Posted by realPubkey@reddit | programming | View on Reddit | 67 comments
Posted by realPubkey@reddit | programming | View on Reddit | 67 comments
Eclipsan@reddit
No warning about the risk XSS poses when sensitive data is stored in local storage instead of HttpOnly cookies.
https://cheatsheetseries.owasp.org/cheatsheets/HTML5_Security_Cheat_Sheet.html#local-storage
Spajk@reddit
I mean to play the devil's advocate here. If you get compromised via XSS what stops the script from showing the legit login window and getting your login credentials?
Eclipsan@reddit
Great question!
If you get compromised by a script tailored to your app e.g. to show the legit login window/page, you are toast. No XSS mitigations I know about will save you. Even a content security policy can be bypassed.
But security is about layers and not being the low hanging fruit. A XSS tailored to your website is way rarer, because either: - You have to fuck up sanitization when displaying data that can be modified by a user. This is on you, and this is harder and harder to do with modern libs and frameworks, which handle sanitization by default. - Or the attacker has to compromise a lib you use just to target you. You probably aren't worth the investement, and they have to pull it off in the first place. If you are big enough to be worth the investement, you probably are big enough to dedicate resources to vetting every single third party lib you use.
AFAIK most XSS (like most malware) are generic and try to infect as much targets as possible. At most they will target vulnerabilities in a specific framework or platform.
CherryLongjump1989@reddit
Compromising a lib your website uses is not XSS.
Eclipsan@reddit
Granted, it's a supply chain attack. Doesn't change a thing. It's actually more prevalent than XSS attacks because it allows attackers to infect a lot of websites at once.
You don't know what security through obscurity means, then.
CherryLongjump1989@reddit
Security through obscurity is when you hope and pray that the attacker won't bother to jump through a few extra hoops after they already have full access to yoru system.
Eclipsan@reddit
No, it's not.
CherryLongjump1989@reddit
Yes, it is. Your chief argument a few comments ago is that no one would actually bother to inject a script onto your web page via XSS in order to actually target your web page, specifically. That's precisely what security through obscurity is.
Eclipsan@reddit
No, that argument is that your app is probably not interesting enough to attackers to make them invest resources into crafting tailored malware. Read it again:
In the comment you are refering to I exactly said that if you get compromised by a XSS (or supply chain attack) tailored to your system no amount of HttpOnly cookie or CSP will protect you:
I don't see how the initial argument was about that, but I will bite: If malicious JS ends up on the client, whether it is via XSS or supply chain attack, any data the client has access to is at risk. It includes data stored on the client and accessible via JS, and any data the client can request from the server (as that malicious JS can query the server on behalf of the user to retrieve data). So at that point it does not matter if said data is stored locally on the client or remotely on the server.
CherryLongjump1989@reddit
There is a word for this. When your website is relatively unknown, not big enough, and very few people know how it works. It begins with the letter "o", I believe.
Eclipsan@reddit
You are missing the point and I have gotten bored of repeating myself. Happy cherrypicking!
CherryLongjump1989@reddit
Actually you're right, I did not address your point directly enough. Your point was that if your website has nothing of value then no one will want to spend more effort attacking it than you spent on creating it to begin with.
I get your point, such as it is. But why would you want to secure your website by making it worthless?
CherryLongjump1989@reddit
These security layers that assume you've already been compromised sound just like security through obscurity and fear-mongering.
pokeybill@reddit
Came here to say this, not addressing security while describing these options is a problem.
Eclipsan@reddit
Especially when most websites with a JS frontend app store everything in local storage "because it's easier" and don't even have a content security policy to mitigate XSS.
rom_romeo@reddit
I'm far from someone defending that decision, but if you end up with an XSS security breach, it's pretty much a game over.
Eclipsan@reddit
Depends on the XSS. It's like saying you don't lock your home or car because thieves can pick locks anyway: Depends on the thief, their tools, the lock...
rom_romeo@reddit
That's correct. In another comment, I explained the importance of the HttpOnly cookie that gives you a slight advantage over local storage, which is very popular for storing access tokens "because it's easier". While the HttpOnly cookie can be sent with every request on behalf of an authorized user, with a proper SameSite attribute (Strict, preferably), it cannot be sent across domains, which significantly reduces the scope of an attack. With local storage, you're toasted.
CherryLongjump1989@reddit
So it's just a niche benefit for session tokens?
pokeybill@reddit
Yep, or they have a policy but there are holes punched in it for development and testing which were never closed when it got to prod.
goestowar@reddit
"That's a usability feature, we need to allow 3-rd party JS libraries to pull the cookie data for essential functionality"
Client goes ahead and tags the issue as an Accepted Risk.
catcint0s@reddit
Is that relevant for the article? If you wanna store data for your frontend you can't use HttpOnly cookies.
Eclipsan@reddit
It's relevant as a lot of devs store session/auth tokens "for their frontend" in local storage even though they don't need to: Their frontend and backend share the same domain (either directly or the front is on
example.com
and the back onapi.example.com
. In such cases, the browser is able to send the session/auth token automatically if it's stored in a cookie. But these devs reinvent the wheel by manually storing then sending the session/auth cookie in every XHR request made to the backend.tl;dr: If your frontend requires access to the session/auth token, you may need to rethink the architecture of your app and domains.
catcint0s@reddit
I meant the relevant part as in this is comparing local database solutions and the auth token/session doesn't have anything to do with that. I wasn't aware people are actually doing but yeah, if this is a common issue at least a mention would have been nice.
Eclipsan@reddit
It's comparing client storage solutions, it has a performance section, so why not a security section too?
Security is way too often an afterthought.
st4rdr0id@reddit
Well that can be said about pretty much every other local web storage method that is not HttpOnly cookies, including IndexedDB, WebSQL etc. I disagree with the relative XSS risk, these stores are visible from JS only to a given origin.
Eclipsan@reddit
Dunno, I have no experience with these.
You do realize that the whole point of a XSS is to run third party malicious code in a page from the first party origin to have access to the data that is indeed "owned" by said origin?
st4rdr0id@reddit
Yes, and the risk is relatively low. If you don't control the scripts that load with your web page then it's already over. That has nothing to do with local storage. Which by the way, needs to be explicitly queried if you want to use a piece of stored data. Cookies instead are attached to every single request inside an origin, and it's easier for the developer to forget clearing them. Cookies are a major privacy concern and they can also be cross origin, which local storage can't.
So imho the XSS vs local storage is a false dichotomy.
throwaway490215@reddit
I'm sorry - but are we so far removed from reality that
are particularly noteworthy in this case?
In so far that security is a concern: XSS might not be able to steal the HttpOnly cookie, but it can steal everything else. Content Security Policy do far more good than pointing out HttpOnly cookies. But I don't see either as especially critical in a blog about local storage options.
rom_romeo@reddit
XSS could also make requests on behalf of an authorized user which automatically sends the HttpOnly cookie in a request. Now, here comes the importance of the SameSite attribute! If it's None, then it can be sent across the domains and you're pretty much fubar. If it's Lax, then it can be sent across the subdomains. This is also where you have to be super careful. If you feature a multi-service architecture that shares the same authorization policy (services exposed on subdomains can authorize access when you present the cookie), and services are exposed on subdomains, then a breach can spill over and expose other services too. That's why the Strict attribute is the safest way to go.
Eclipsan@reddit
AFAIK you cannot defend against that.
Sure, though
Strict
means the cookie won't be sent when the user arrives on your website by following a link on another website (e.g. social media, slack, webmail...). So if they were already authenticated, it won't be the case when they arrive. Might not be an issue if you have a JS frontend: Clicking on the link can load a skeleton not relying on authentication, then the JS can send XHR requests to your backend (the browser will automatically attach the cookie) to hydrate the skeleton with user data.Eclipsan@reddit
I do: I raise awareness about that kind of stuff whenever I can, because most devs have very poor practices security wise.
You are absolutely right, though: - Security is about layers, so why not have both? A CSP can sadly be bypassed simply by redirecting the user via JS to a URL containing the data you want to extract. So it does not render HttpOnly cookies useless. Plus with a HttpOnly cookie you limit the opportunity of a XSS stealing credentials to the login page, where you could for instance only load JS that is strictly necessary to the login process, thus reducing the risk of a XSS. - Baby steps, I don't expect devs who don't know/do anything about XSS to be able to maintain an effective CSP.
Slappehbag@reddit
Do you have any advice or links on maintaining a strong CSP?
Eclipsan@reddit
Scan your website with https://developer.mozilla.org/en-US/observatory. And follow the other advices too, not only those about CSP.
If your website is not online yet, scan another one and follow the advices anyway. You can even scan the scanner itself: https://developer.mozilla.org/en-US/observatory/analyze?host=developer.mozilla.org
skytomorrownow@reddit
Is the safest bet authentication HttpOnly cookies, or an authentication header? Not a webdev, but have to dabble from time to time. Thanks.
coyoteazul2@reddit
Httponly cookies. After all, if you use authentication header you must keep the value somewhere. That somewhere can be read by malicious scripts
Eclipsan@reddit
Except if it's basic auth, then the header can be automatically handled by the browser. But who does that in production for client facing apps.
keepthepace@reddit
Why shouldn't you?
PurpleYoshiEgg@reddit
Mostly ergonomics, but also there's lack of control on the server side. If HTTP basic auth had support from browsers for more standard authentication practices, it would be nice.
But HTTP basic auth doesn't have a standard way to:
I do think authentication and authorization is kind of a standard enough thing that browsers should support a standard flow that ends in an HttpOnly cookie. If I'm not using a web framework for whatever reason, having to implement a login is dicey at best (because I'm not a security engineer), but I don't want to necessarily be tied down by a certain web framework (and, my one-shot test apps have a weird amount of longevity sometimes).
A login gateway might actually be the thing I'm looking for, but I haven't explored that space too much yet. The other option that is widely professed is OAuth, but that either requires setting up your own complicated infrastructure (with many security concerns) or utilizing a third party vendor, and neither option is simple when I just want username and password login for a specific site.
Eclipsan@reddit
Because it's very ugly UI/UX wise and it's no longer 2005?
And by client I meant end users, the average internet user. Not e.g. a professional user for a business app or intranet, these users are still (sadly?) used to dated UI/UX.
Plus I guess one could argue it's not great to send the user's password with every request and keep it in plaintext client side (at least in the browser's ram). Especially if the user forgets to logout (AFAIK by default basic auth creds are not cleared if the browser is closed).
keepthepace@reddit
Isn't there a way to pass basic auth in JS?
Eclipsan@reddit
Sure, though it means JS has access to the credentials, so we are back to square one: A XSS on any authenticated page of your app can steal them.
keepthepace@reddit
Well, if you are unwilling to use browser native features but also do not want JS to handle the credentials ever, what is left?
theXpanther@reddit
Http only cookies
cedear@reddit
Also no mention of the fact that browsers can and will randomly delete localstorage at any time. It's never reliable. But that probably goes for most/all of these methods.
gambiter@reddit
Did they add it after your comment? Because it seems to be there.
wPatriot@reddit
Are you confusing the owasp page with the article? They have similar layouts, so at first glance you might've assumed they were the same thing. Because the article doesn't seem to mention XSS or something similar.
gambiter@reddit
You're absolutely right! I got them mixed up because I opened them in separate tabs. Serves me right for commenting before my coffee kicked in. :)
st4rdr0id@reddit
It is sad that WebSQL was discontinued. It can still be used in most browsers though (except Firefox). It is hands down the best web storage method that was ever released. And unlike the wasm version, it comes built-in with the browser, no need to download a 1 MB file each time. I don't know why it can't be updated to more modern SQLite versions, this is a pretty solid library and knowing the spirit of the project I'm sure the newer versions are mostly compatible with the old ones.
pekter@reddit
The main issue is having a standard based on a third party library.
curiousdannii@reddit
localStorage isn't limited to 5MB, it's limited to 5 million characters. With base32768 you can store over 9MB of binary data in it. Which can be a big improvement if you need to depend on localStorage. For example, if you need to run from a file: url then localStorage might be your most reliable option...
Economy_Dinner_9582@reddit
does each benchmark include network download/wasm-startup?
realPubkey@reddit (OP)
Yes it does at throttled "average" internet speed. But this is only relevant for the benchmark of initial load. Everything else runs locally anyway so it does not use the internet.
CriticismEmotional13@reddit
Are you confusing the owasp page with the article?
stylist-trend@reddit
Looking at the linked article (which was updated today), I see literally one function that can be promise-based, and that's the
databases()
call. This sentence is way overselling the promise-based nature of IndexedDB.FoolHooligan@reddit
For the few times when I used indexdb (it was a hobby project,) I just used DexieJS for a more promise friendly API.
lord2800@reddit
Dexie seemed quite reasonably performant to me when I used it to load and query a large existing data set into the browser (think: entire database dump basically). What performance problems are people experiencing? I'm genuinely curious here.
FoolHooligan@reddit
I haven't had any performance issues with it. This article is just a performance comparison and Dexie seemed to do the worst. But it's perfectly adequate.
stylist-trend@reddit
Oh yeah, I've used Dexie and it's nice, but I was excited about IDB 3.0 making more things promise-based, which I was sad to find out was wrong.
bwainfweeze@reddit
Would you say they’re… overpromising?
stylist-trend@reddit
Lol, I was trying so hard to avoid writing that word because it felt way too on-point
ggppjj@reddit
Marketing post that includes browser history manipulation to prevent you from going back.
They can fuck themselves.
FoolHooligan@reddit
Very nice article. The bar chart image at the end is a good TLDR.
OptionX@reddit
Was this written by a person?
ApartmentWorking3164@reddit
Yes, I wrote it. There is no ChatGPT in use because I know people dislike that.
OptionX@reddit
Ok, thank you for confirming it. You never know these days.
binarymax@reddit
I’ve been waiting 10 years for something like OPFS. Wrote this in 2015. https://max.io/articles/the-state-of-state-in-the-browser/