diamond

joined 1 year ago
 

tl;dr, I'm posting this Lemmy issue that proposes a CORS change to allow Lemmy web clients to work with Lemmy servers without needing a proxy (possible security risk). Please show your support by +1ing the issue and the PR!

Issue link: https://github.com/LemmyNet/lemmy/issues/3109 PR link: https://github.com/LemmyNet/lemmy/pull/3421

Background

The web has many security features, and one of them is CORS, or Cross-Origin Resource Sharing. CORS ensures that when you click a button on a website in your browser, your account information isn't immediately compromised. It's one of many layers that protect your information from malicious actors.

Lemmy currently has this feature. Its CORS is configured to reject HTTP requests from an origin that is not what it expects. For example, if I'm on cool-lemmy-client.com and I request a list of posts from beehaw.org, the browser will reject the request. This is because beehaw.org is telling the browser "hey, this request is only valid if it's made within the beehaw.org website, otherwise reject it!

This effectively means that third-party Lemmy web clients cannot talk to any Lemmy server. It's impossible because those web clients are hosted outside of Lemmy servers, so the browser will refuse any interaction with those Lemmy servers.

Why Wefwef works

Wefwef is a third-party web client. It also runs in the web browser, and yet it works. How does it do that?

It turns out that Wefwef actually runs a proxy in the middle. The browser essentially hits this proxy instead, and the proxy makes the request on behalf of the browser. When it returns data, the proxy simply passes that data back and tells the browser that its origin is allowed.

This works because CORS is a browser thing: requests are rejected in the browser, not anywhere else, and because the proxy is its own server and not a browser, it's not affected by CORS. This is also why applications like Jerboa work perfectly well.

Note: This is not to say anything about Wefwef! In fact, the developer of Wefwef expresses the same opinion!

Why proxies are bad

There are a myriad of issues that come with running a proxy for a web client, but it can be boiled down to 3 quick points:

  1. It creates a single point of load. All users of a particular web client now have to rely on a particular CORS proxy, and that puts a lot of load on that proxy.
  2. It exposes sensitive data to more parties. Specifically, CORS proxy operators (often the application maintainers) can see any information passed through it, including user tokens! Theoretically, they can steal your account.
  3. It is extra work for application maintainers to also maintain and scale CORS proxies.

Why it doesn't make sense

Restrictive CORS doesn't make sense for Lemmy. It is not an effective way to block third-party clients, since it is only a browser restriction. But people can still run proxies for their web applications, and that just makes things worse for everyone!

Lemmy doesn't benefit from restrictive CORS.

Why it's not a security problem

I said above that CORS helps prevent scenarios where your account information is stolen just by clicking a random button. However, this does not apply to Lemmy! To explain why, I need to look at how Lemmy (or any website) knows who you are.

Lemmy uses a JSON Web Token (JWT). Simply put, it's a piece of text that tells the server "this is user X", which is then cryptographically signed by the server, meaning it can't be altered by anyone else without also breaking the signature. This allows the server to trust that if the signature is valid, then user X's claim can be trusted.

Typically, the browser can send this token in two ways:

  1. It can do so using cookies. The server tells the browser "hey, store this token", and later requests made by the browser will also include this token.
  2. It can do this by manually appending the token somewhere in the request, usually in the Authorization header. The application is usually the one that receives the token and manually stores it somewhere. It then manually reads this token back when it needs to and appends it to its requests.

Applications that implement the first method would be vulnerable to the aforementioned security problem if CORS didn't exist: the browser could append the cookie to every subsequent request, including requests from other sites! This means that if I go to seemingly-legit.com and the site makes a request to beehaw.org, that request will be made on my behalf without my knowledge!

Fortunately, we can tune CORS so that we can still make requests to beehaw.org without randomly leaking user data! Specifically, CORS has a separate header that tells the browser not to send cookies, even if it allows requests from anywhere (Access-Control-Allow-Credentials vs. Access-Control-Allow-Origin). This is what Lemmy PR does.

Applications implementing the second method may or may not be vulnerable:

  • If it stores the token in its local storage, then only it can see that token. The browser does this by giving each origin (domain, e.g. google.com) a completely separate local store. Discord is one of the many applications that does this.
  • If it stores the token in the browser's cookie store, then it behaves the same as the first method. The only difference is that instead of the server telling the browser to set the cookie, it's the application code running on the browser that sets the cookie.

Lemmy stores tokens in the cookies. As long as we're careful about which CORS headers we return, the browser won't leak them!

What we should do

Lemmy issue #3109 discusses this issue. You can show your support by responding with a thumbs up (+1) or a heart.

I have also created Lemmy PR #3421 which fixes this problem directly in code. You can also show your support by responding to this PR with a thumbs up or a heart.

I'm currently developing a Lemmy web client, and I need the CORS changes merged in order to use it with Lemmy instances running v0.18 or newer. Having this merged would save me a lot of time and effort. The developer of Wefwef has expressed the same opinion. Please consider supporting the application developers by upvoting these issues!

[–] diamond@beehaw.org 2 points 1 year ago

Yeah, it's at https://slemmy.libdb.so, the source code is also on my github!

Heads up, it doesn't currently work with Lemmy v0. 18.0. PR https://github.com/LemmyNet/lemmy/pull/3301 tracks this. If you or anyone can contribute to this, please do!

[–] diamond@beehaw.org 4 points 1 year ago (3 children)

I use the one that I made! It was made rather early on before most of these apps became popular, but if it's my own app, I can make it however I want...

[–] diamond@beehaw.org 4 points 1 year ago (1 children)

+1 on SchildiChat here as well.

I used to use FluffyChat but it would corrupt its internal SQLite database randomly. That happened a couple of times so I just stopped using it entirely.

[–] diamond@beehaw.org 2 points 1 year ago

I'm adding this into my Lemmy client's README.

[–] diamond@beehaw.org 18 points 1 year ago

Shameless plug (sorry) but I'm working on one too! It's a web app that works on both desktop and mobile: https://slemmy.libdb.so.

It is a free-time kind of project (I work on it after my actual working hours), so it might not grow at the same pace as other newer apps, but I'm trying!

Source code is at https://libdb.so/slemmy, AGPLv3 license.

[–] diamond@beehaw.org 1 points 1 year ago

No plans for a Docker image atm but you should be able to easily host this using any web server! It just needs to be built, and I might make a Github Action to automate that.

For now, the site is fully static and doesn't require any server so you can just use the one hosted on Netlify.

 

Hi hi, I know I posted about this yesterday-ish, but Slemmy is now deployed! Head to https://slemmy.libdb.so to give it a try! Simply make a profile with your favorite instance and continue!

If you haven't seen yesterday-ish's post, here are some screenshots of Slemmy: https://imgur.com/a/KJqKuiF

Unfortunately, there's no signing in yet, so you can't do much besides reading posts. I'm actively working on this, though!

The project's source code is at https://github.com/diamondburned/slemmy. Its README contains the current features and what is planned for now. I started on this project not even a week ago, so it's likely unstable and not ready for heavy use yet. Please open an issue if you encounter any bugs, I would really appreciate it!

[–] diamond@beehaw.org 1 points 1 year ago

Yup! Each profile will eventually be its own (possibly anonymous) account that belongs to an instance, something like this:

profile screenshot

[–] diamond@beehaw.org 3 points 1 year ago (1 children)

Whoops! I forgot to update it.

 

This app will mostly be intended for reading, but it'll support multiple profiles, upvoting and commenting.

I currently plan on targeting both desktop and phone usage, with some primitive touch gestures to make it easier. Unfortunately, since this is just a progressive web app, that's going to feel a bit scuffed.

The source code is at https://github.com/diamondburned/slemmy. It's currently not usable for production yet :( but I'm working on it!

[–] diamond@beehaw.org 1 points 1 year ago (1 children)

I had no idea that NGINX has Lua plugins. You'd probably want to check if Caddy has equivalents for those plugins though, or just implement them in Go yourself.

[–] diamond@beehaw.org 2 points 1 year ago (3 children)

People comment a lot on performance, but I think Caddy can (and should) hold up perfectly fine. It might be worth it to experiment with running servers half on Caddy and half on NGINX, then see how the traffic is being handled by both to compare.

I do think the much cleaner config makes up for the maybe slight performance loss, though. It's just so much less work to set up and maintain compared to NGINX. The last time I've used NGINX was years ago, when I decided to drop it entirely in favor of Caddy. I do think NGINX is only "standard" because it came before Caddy, and that most applications should not prefer it over Caddy.

[–] diamond@beehaw.org 2 points 1 year ago

I think they definitely could've made a profile page while keeping the discriminator around. Something like discord.com/u/diamondburned/4507.

(For various reasons diamondburned#4507 is not too ideal for a URL, but it's a small difference. Right?)

view more: next ›