Hacker News new | ask | show | jobs
by ashishb 449 days ago
Next.js is based on a fundamentally flawed premise that one can write code that runs in the browser as well as the backend.

The security posture for the code running in the browser is very different from the code running on a trusted backend.

A separation of concerns allows one to have two codebases, one frontend (untrustworthy but limited access) and one backend (trustworthy but a lot of access).

4 comments

This vulnerability has nothing to do with isomorphic code, right? Next middleware only runs on the server (or on “the edge,” which is still a server even if it’s running in a browser-esque environment).
How many frontend (full stack) guys even understand the difference?
How many people offering knee-jerk takedowns of Next.js understand the difference? Hard to say.
This vuln doesn't really have anything to do with that premise. Middleware always run on the server.
While it's true that running code in isomorphic manner by definition gives you more footguns, you can mitigate it somewhat if you architect the framework with that in mind. In rust land for example, you can just not implement "Serialize" trait on your sensitive data structs and it can't leave server realm without developer jumping through some hoops.
I don't think this is true in principle. It should be pretty easy to statically verify that the separation is safe using something similar to trusted types and the Typescript type checker. It's not possible in Next.js, but that doesn't mean the premise is wrong.
That could help in some cases (maybe even the areas where their server-side replicas of browser APIs aren’t quite consistent), but how would it handle things like someone putting a validation or access control check in the client-side code? A lot of these things come down to the code correctly doing what a confused author intended.

In this case, it’d also be interesting to try to figure out how a fix would look like in that model. You could have some way for a type-checker to tell the requests apart such as a union type for Client|Edge|Server requests but you’d need a way to assert that the header couldn’t be present on all of them, which suggests the real problem is using in-band signaling. It seems like a solid argument for type-checking since making the relationship clear enough to validate also makes it harder for humans to screw up.

The simplest way is that all resources require an authenticated type for access, and getting that authenticated type requires an input (secret) only available on the server.

Facebook does something like this and it works pretty well

How many startups/small companies that uses next.js do any static verification?
I don't know, but I am just pointing out that the problems here are really about execution, not vision.

There's no reason we can't properly enforce security boundaries in the browser, we already do it between the website's code and the local machine.

These ideas have been around a long time and predate the internet. See for example Liskov's work on Thor:

https://dl.acm.org/doi/pdf/10.1145/233269.233346

If a vision has not been executed despite so many people trying may be something is wrong with it?
No, many have executed this vision. Facebook was doing this since at least 2010