I'm primarily a backend dev, and so I am always extremely careful about auditing what any external api's do. I did not, however, realise that every "use server" was in effect creating another api. Now if you'll excuse me, I have several codebases to audit. Thanks for the heads up.
I created an auth decorator that calls the underlying action only if the user is authenticated and authorized to use the endpoint. Maybe you could do the same:- export const SomeAction = isAuthenticated("admin", () => { });
Inplicitly creating endpoints is the problem. The more things you make implicit in a framework, the greater the opportunity for a nightmare to be created.
I totally agree! I tend to use the new stuff without fully understanding the implications of it or sometimes even not understanding the implications at all, but just doing it because it makes things easier 😅
As of 8/22 the Next team has put out a fix for this issue via tree shaking unused action ids, and I think it’s being backported to v14 There’s a deeper problem imo around the design of having implicit endpoint creation, but it’s nice this specific problem is fixed
So not worth the "cleanness" of the code IMO. I'd way rather prefer writing some boilerplate to keep things explicit so it's really hard to make mistakes like this.
@@smallmoneybigmoney So true. I am working full time on java+angular apps which "share endpoints" using OpenAPI. Everything is automatically generated. Works like TRPC, the only difference is that you have to restart your server and client for changes to be present. And we can use OpenAPI in any language we want...
Unless they also fixed the source map files, the treeshaking is "useless". The source map files are generated BEFORE the treeshaking, so while the final bundle might not have the code, your source map files WILL have it... Meaning you still expose everything if users have access to source map files.
"When you're exposing things with 'use server', you have to assume that th[e] function can be run by anybody. I think a lot of the issue that's happening here is that web developers aren't used to dealing with access control." Great video, as always, but IMHO, this is the TL:DR of this video, and maybe it's worth its own reel/short.
True anyone that has implemented similar things in a proper backend environment with API and stuff will realise that it needs to be protected as it's exposed I don't get it why don't people wrap their heads around this aspect when writing server actions
Theo the type of guy to explain a problem for 10 minutes only to be like : " yeah so we ARENT gonna talk about this actually, this is completely different"
RSC is such a developer experience disaster. Too much magic and confusion of where your code runs. Having concrete application boundaries is a good thing!
I kind of understand the use of "use server", but is kind of complex to maintaining as the app keeps growing, I prefer a separated backend, and not doing sql querys inside the actions, instead calling my backend that needs authorization that don't care about the exposes endpoints on nextjs, that way, I don't have to worry about those security issues that next js has.
@@rob6129the issue is actually the fact that this kind of thing should've never come into existence in the first place. Security issues arise from either software problems or, more commonly, anthropic effects. In this, like in many other cases, it's people trying to cut corners and take shortcuts when they really shouldn't.
@@rob6129 It's called the "separation of concers". And it's the simplest form of it. There is one thing that is sure - human error will occur. We want to minimalize the chance for it as much as we can. Have everyone forgot OpenAPI? You can generate trpc-like endpoints from nearly any backend language without much hussle...
Part of the issue here is overloading the export keyword to mean two different things: to create an endpoint and to allow it to be called from other modules. I feel like it's an unnecessary footgun in the design.
NextJS suffers from the same thing most large web frameworks do. Complexity. In an effort to make things "easier" they've actually made it very complex. So much so that people often do incorrect things because they don't really understand the complexity.
25:15 if code review is your only line of defence against something, you're not well defended against it, because for a ton of people it's "just a job" and they don't care to fully understand every detail in changes they review; mistakes and oversights are a big reason for security breaches.
I know its so funny how its like young CTO's and principal types are rediscovering web development from 15+ years ago. People spend so much time on solved problems as well as pursuing paths that are known to lead to doom and gloom. Every generation of young devs thinks they're the first people to encounter every issue that's new to them and god forbid they bother to check with all the search and LLMs and other tools at our disposal these days
I've said this in the comments of a different video, but in webdev, time really is a flat circle. Every decade or so something that was deemed Bad™ comes back as the New Amazing Thing™... except that it's really just the so-called Bad™ thing with a slight twist.
How long until NextJS reinvents Express middleware? :) Also, isn't one of the top engineering rules in *any* system to default to a safe or secure mode? Like railroad crossings defaulting to enabled, or door magnets turning off with loss of power? Shouldn't it be defaulting to not exposing your endpoints unless you tell it to?
One could argue for or against whether it could be considered "security" issue-it depends on the context. The equivalent of this issue is your client includes info about endpoints-either defined manually or through code generation, for example, but are unused. Unless you had some profiling tools that could flag unused endpoints. The counter-intuitive part is that you'd expect the bundler to not include any unused exported actions, just like any other module bundling does tree-shaking. Rhys is just pointing out that it could leak endpoints that you didn't intent in case you thought it was tree-shaked. Vercel fixed this in Next by tree-shaking the unused exported actions as you'd expect. The upside of this is that it's easier to augment unused endpoints through static analysis, compared to a lot of codegen solutions.
“Express middleware” IS middleware lol, its a pattern used in all servers, nothing to reinvent. Also, yes, NextJs should totally do that, because the current “middleware” is not actually a middleware at all, at least not in the user space
No their goal is to "ship fast" "even before it works" in a goal to lock developers into their ecosystem so they can rationalize how an AWS reseller got a multibillion dollar valuation.
Everyone says controll your Access but everyone falls short of Showing how to do it correctly. My loved example is a Company Blog system, one user writes a Article and sets the state to review and then a other user can change/publish the Article. Not to simple and not to Complex to show every Access Controll you need. The best part is how you design the Article flow changes the AccessControll
True - which is why it is our job as development leads to create a system in which developers are less likely to make these mistakes, through code organization and composition - as we do in any other backend framework…
JS devs seem so odd to me sometimes. They berate people for using HTMX cause it breaks separation of concerns, but then they just blatantly throw server side code into their client side files?
I think in your example requiring an auth check is an anti-pattern type suggestion, as in the case of your function "donotuse" etc.. you already believe its not going to become an endpoint, so... you won't be putting auth checks in there. I suspect the best possible standard is "user server" per function, I would probably just make that the standard on a team if it were a nextjs project .
19:00 less "unintuitive" and more "why is this not the first line in the docs". "'use server' turns the function (or in the top level, all exported functions in the file) into supercharged endpoints" or something like that.
This. Documentation should be like a user manual to a dishwasher, where on the top there are all the dangers listed, and not a novel, where you gotta read it all before you get it.
Honestly might make a simple ESLint plugin to require a comment like “// safe-public-endpoint” (or something to that effect) on all exports of a “use server” marked file to at least make the developer acknowledge that this is an endpoint and is safe if hit directly. Obviously not robust, but I’d rather rely on automated CI checks to flag issues than code review.
Wasn’t the hidden variables in a form to share state an anti-pattern once upon a time? We decided that API calls was the right thing to do because it makes it clear what is intended and designed and you can more easily force security on the back end. This seems like one of those ‘easy now but nightmare to debug and optimize later’ scenarios.
I think the big concern is the very, very, very low barrier to error and the kinda unintuitive behavior of "use server" not currently being tree-shaken (only create endpoints for used routes on a page) meaning it's very easy to create the problem and, honestly, not easy to check unless you already know about the quirk. Code review is great but it assumes everyone understands the "make it all an endpoint" behavior, which I wouldn't consider intuitive.
Because it's more convenient but convenience is the bane of cleanliness, efficiency, security and basically everything else other than development speed. People care more about putting out garbage quickly than putting out good stuff slowly.
This is one of the reasons I like having a Spring Boot backend instead. It's so easy to have auth on *every* endpoint all controlled in one spot rather than having to remember to secure each one individually. Next.js should have something similar.
The mayor problem, I think, is that the abstraction seems specifically build so you don't have to think about the fact that you are writing and calling endpoints. Designing the API to make the server boundary invisible, then saying "silly developer, don't you know there are risks to this free-floating string" is not productive and doesn't help make things more secure.
Same thought I had. You can move the function you want to test to its own file that does not "use server" and test it from there (this was shown in the video), but that's annoying. Ability to test random things without exporting them is one of the things I miss most working in JS/TS compared to Rust.
Yeah that’s actually one of the benefits of classes. Assuming your using typescript you can mark the method as private but still allow them to be accessible for testing.
it would look better imo if the use server functions would explicitly receive as arguments the variables used from the ui context, so whoever looks at the code knows at a glance what inputs are generated and what is sent
I need to think about this more. But at first glance, it smells like how PHP would smell where it gave so much flexibility but gave all the footguns with it that led to so many security errors. Ah wells. More areas to go search for bug bounties in I guess.
as a Java developer I find the problem and especially the conclusion to be the absolute basics of server development and it is so trivial that I'm quite speechless how did people arrive at this problem...
yeah, folks really don’t understand that its just an api, and issues have to be solved through code composition and organization, not by nextjs placing fake guardrails. Same thing happened back when react couldn’t explain to people what dtos are, and ended up implementing a crappy field level sccess control mechanism 😂
Most big tech / companies projects do not include only 1 frontend application. I think use server makes a lot of sense for those who have only 1 client side and most developers are front-end. However, in most real world scenarios you would have 1 or more apis serving 2 or more front end application in which case server actions makes no sense unless you want to replicate the same code again and again for each client side. Regarding the access control, it had nothing to do with server actions. It is much more related to the knowledge one might have regarding this topic.
Why is communication around Server Actions not making it immediately obvious that's it's basically an HTTP route. That important details would have prevented this very issue of unprotected routes.
@@hello19286 MFW people convinced they need globally distributed "serverless" "edge" functions for apps that will never have a lot of users nor a global audience and so they make sweeping compromises on security, architecture, and design decisions to meet this set of requirements that they don't have nor ever will
- separate server actions to their own file and use “use server” on the top - don’t return sensitive data from server action - validate requester identity in the server actions
See this is why I'm a big fan of the LAMP stack, at least I know it's insecure and I can at least mitigate it by literally requiring every input be purely alphanumeric, and I usually have three seperate functions all using different mechanisms to do that check.
Strings with different characters are not really a problem if you use prepared statements for the SQL. And just use htmlspecialchars to avoid XSS. And your kinda paranoid. One Funktion does the trick.
The solution can't be "audit and code review", the security of actions is way too fragile. Relying on people doesn't scale, sometime somewhere they will fail for whatever reason, and you will wish you had a compiler or linter telling "are you sure is this what you want?"
IMHO - Your GraphQL issue is only there because of the use of the schema dsl, I've always used the programatic api's and composed PER role graphs, they all run on the same ctx, but the graphs actually omit entire branches based on permissions.
Seems like a good use case for a higher order function that wraps the function with auth. Not sure if that is going to make the TS type definitions a bit unwieldy though. Very mixed feelings about this. I can see the arguments both ways. Leaning towards breaking widely held assumptions and making it insecure by default is a "bad thing" though. IFF the dev knows this, it is fine. But how many are actually going to know it is exposed?
So if there is a unintentionally exposed function which does some heavy processing like data sync, calculations, or an AI generated response of text/image. Someone could abuse it to call it directly where dev didnt think of implementing a check. Because they implemented a check on the original endpoint and not here. Can it happen ?
Why doesn't the bundler expose only the exported functions? Rather than all exported from a file? They still can allow all exports in an endpoint by coming up some other stupid term like "use server; export all"
Vercel might wanna add some type of "use this function to verify all use server"-functions. Instead of having to aduit all this shit and figure out every little possible leak that might happen...
In express I call the auth middleware before every protected route. IT IS EXPLICIT. The problem with server actions pattern is lack of CONTROL for BE devs, and IMPLICIT creation of endpoints. Next.js auth middleware called on every route is bullshit, it should be selectivelly called on protected routes only.
If you read the documentation for Next.js they actually have a part that says that all server actions should be treated as public API endpoints and protected. So who's fault is it then ?
Looks like i was already doing things correctly but i didn't know that :D I'm new to web dev but i'm a senior backend dev so i probably already did this out of habit.
I think Next.js tries to be too clever for it's own good and might drug Server Side React down with it. Too much abstraction and complexity, bad development experience (hard to trace errors, buggy hot reloading, memory hog server). You switch back to a Vite project and everything is light/fast and crystal clear.
I love your content. Since the twitter drama with yacine, you seem too preocupied with not being perceived as a shill, so your content seems targeted as cleansing your reputation (I love elixir, I am a serious programmer, etc.). Just be yourself, and focus on cool/useful content, nobody cares about purist, and everyone is tired with yacine's antics anyway.
Just don't use top-level "use-server". Do yourself a favour and understand that each function with the "use server" pragma creates an endpoint. From there, opt in as you see fit.
I'm primarily a backend dev, and so I am always extremely careful about auditing what any external api's do. I did not, however, realise that every "use server" was in effect creating another api. Now if you'll excuse me, I have several codebases to audit.
Thanks for the heads up.
I created an auth decorator that calls the underlying action only if the user is authenticated and authorized to use the endpoint. Maybe you could do the same:-
export const SomeAction = isAuthenticated("admin", () => {
});
@@dough-pizza could you make a npm package or at least a GitHub repo for just the rest of the population like myself? I think it's useful Sir.
Inplicitly creating endpoints is the problem. The more things you make implicit in a framework, the greater the opportunity for a nightmare to be created.
That's why I keep using API routes in NextJS instead of server actions. Less magic going on.
I totally agree! I tend to use the new stuff without fully understanding the implications of it or sometimes even not understanding the implications at all, but just doing it because it makes things easier 😅
As of 8/22 the Next team has put out a fix for this issue via tree shaking unused action ids, and I think it’s being backported to v14
There’s a deeper problem imo around the design of having implicit endpoint creation, but it’s nice this specific problem is fixed
So not worth the "cleanness" of the code IMO. I'd way rather prefer writing some boilerplate to keep things explicit so it's really hard to make mistakes like this.
@@smallmoneybigmoney So true. I am working full time on java+angular apps which "share endpoints" using OpenAPI. Everything is automatically generated. Works like TRPC, the only difference is that you have to restart your server and client for changes to be present.
And we can use OpenAPI in any language we want...
Unless they also fixed the source map files, the treeshaking is "useless". The source map files are generated BEFORE the treeshaking, so while the final bundle might not have the code, your source map files WILL have it... Meaning you still expose everything if users have access to source map files.
"When you're exposing things with 'use server', you have to assume that th[e] function can be run by anybody. I think a lot of the issue that's happening here is that web developers aren't used to dealing with access control."
Great video, as always, but IMHO, this is the TL:DR of this video, and maybe it's worth its own reel/short.
True anyone that has implemented similar things in a proper backend environment with API and stuff will realise that it needs to be protected as it's exposed I don't get it why don't people wrap their heads around this aspect when writing server actions
@@sulavbaral9972 These are frontend devs we are talking about. They don't worry about user input, that's backend guys' problem.
*frontend developers
@@sulavbaral9972 because it's not immediately obvious is basically an HTTP route. That important details isn't well communicated.
@@kylemichaelsullivan Bingo
Theo the type of guy to explain a problem for 10 minutes only to be like : " yeah so we ARENT gonna talk about this actually, this is completely different"
RSC is such a developer experience disaster. Too much magic and confusion of where your code runs. Having concrete application boundaries is a good thing!
I kind of understand the use of "use server", but is kind of complex to maintaining as the app keeps growing, I prefer a separated backend, and not doing sql querys inside the actions, instead calling my backend that needs authorization that don't care about the exposes endpoints on nextjs, that way, I don't have to worry about those security issues that next js has.
Its not a security issue its a skill issue
@@rob6129 most security issues are skill issues. Memory leak in a C code base, skill issue. Still a security issue.
@@rob6129the issue is actually the fact that this kind of thing should've never come into existence in the first place. Security issues arise from either software problems or, more commonly, anthropic effects. In this, like in many other cases, it's people trying to cut corners and take shortcuts when they really shouldn't.
@@rob6129 It's called the "separation of concers". And it's the simplest form of it.
There is one thing that is sure - human error will occur. We want to minimalize the chance for it as much as we can.
Have everyone forgot OpenAPI? You can generate trpc-like endpoints from nearly any backend language without much hussle...
server actions are literally “separated backend api calls”, you are missing the point
Part of the issue here is overloading the export keyword to mean two different things: to create an endpoint and to allow it to be called from other modules. I feel like it's an unnecessary footgun in the design.
NextJS suffers from the same thing most large web frameworks do. Complexity. In an effort to make things "easier" they've actually made it very complex. So much so that people often do incorrect things because they don't really understand the complexity.
Maybe they should invent an HTTP header for Authorization. They mustn’t have thought about it…
But what if one endpoint is supposed to be public and the internal function not?
25:15 if code review is your only line of defence against something, you're not well defended against it, because for a ton of people it's "just a job" and they don't care to fully understand every detail in changes they review; mistakes and oversights are a big reason for security breaches.
They basically recreated AspNet WebForms.
It only took 15 years and the pendulum came back to server components entangled .
I know its so funny how its like young CTO's and principal types are rediscovering web development from 15+ years ago. People spend so much time on solved problems as well as pursuing paths that are known to lead to doom and gloom. Every generation of young devs thinks they're the first people to encounter every issue that's new to them and god forbid they bother to check with all the search and LLMs and other tools at our disposal these days
100% the truth, they have so many similarities, it’s only flashier here because of React itself.
I've said this in the comments of a different video, but in webdev, time really is a flat circle. Every decade or so something that was deemed Bad™ comes back as the New Amazing Thing™... except that it's really just the so-called Bad™ thing with a slight twist.
I feel like "use server" should have some sort of mandatory access level argument
How long until NextJS reinvents Express middleware? :)
Also, isn't one of the top engineering rules in *any* system to default to a safe or secure mode? Like railroad crossings defaulting to enabled, or door magnets turning off with loss of power?
Shouldn't it be defaulting to not exposing your endpoints unless you tell it to?
One could argue for or against whether it could be considered "security" issue-it depends on the context. The equivalent of this issue is your client includes info about endpoints-either defined manually or through code generation, for example, but are unused. Unless you had some profiling tools that could flag unused endpoints.
The counter-intuitive part is that you'd expect the bundler to not include any unused exported actions, just like any other module bundling does tree-shaking. Rhys is just pointing out that it could leak endpoints that you didn't intent in case you thought it was tree-shaked.
Vercel fixed this in Next by tree-shaking the unused exported actions as you'd expect. The upside of this is that it's easier to augment unused endpoints through static analysis, compared to a lot of codegen solutions.
“Express middleware” IS middleware lol, its a pattern used in all servers, nothing to reinvent. Also, yes, NextJs should totally do that, because the current “middleware” is not actually a middleware at all, at least not in the user space
next safe actions
No their goal is to "ship fast" "even before it works" in a goal to lock developers into their ecosystem so they can rationalize how an AWS reseller got a multibillion dollar valuation.
@@furycorp you cant say there is no effort being put in to this
React keeps making various forms of useEffect footguns lol
React itself is a footgun
Everyone says controll your Access but everyone falls short of Showing how to do it correctly. My loved example is a Company Blog system, one user writes a Article and sets the state to review and then a other user can change/publish the Article. Not to simple and not to Complex to show every Access Controll you need. The best part is how you design the Article flow changes the AccessControll
I don't know, man; it looks leakier than my 43-year-old toilet in my apartment. There's no way every developer can keep up with every exposed point.
True - which is why it is our job as development leads to create a system in which developers are less likely to make these mistakes, through code organization and composition - as we do in any other backend framework…
separation of concerns went from html and css in js, to backend in frontend really quick. what a mess.
JS devs seem so odd to me sometimes. They berate people for using HTMX cause it breaks separation of concerns, but then they just blatantly throw server side code into their client side files?
In our team, we always end our filename with .server for server run code. For example, actions.server.ts
actions are basically running on server, aren't they? if not, they are just js/ts functions..
I think in your example requiring an auth check is an anti-pattern type suggestion, as in the case of your function "donotuse" etc.. you already believe its not going to become an endpoint, so... you won't be putting auth checks in there.
I suspect the best possible standard is "user server" per function, I would probably just make that the standard on a team if it were a nextjs project
.
19:00 less "unintuitive" and more "why is this not the first line in the docs". "'use server' turns the function (or in the top level, all exported functions in the file) into supercharged endpoints" or something like that.
This. Documentation should be like a user manual to a dishwasher, where on the top there are all the dangers listed, and not a novel, where you gotta read it all before you get it.
It is there in the docs
Honestly might make a simple ESLint plugin to require a comment like “// safe-public-endpoint” (or something to that effect) on all exports of a “use server” marked file to at least make the developer acknowledge that this is an endpoint and is safe if hit directly.
Obviously not robust, but I’d rather rely on automated CI checks to flag issues than code review.
I like that idea, make it part of the jsDocs or something so it shows up in the intelligence anywhere the function gets used
Wasn’t the hidden variables in a form to share state an anti-pattern once upon a time? We decided that API calls was the right thing to do because it makes it clear what is intended and designed and you can more easily force security on the back end. This seems like one of those ‘easy now but nightmare to debug and optimize later’ scenarios.
I dont know if adding export to a function might cause a security issue, we need to start re evaluating if this is the way to go
I think the big concern is the very, very, very low barrier to error and the kinda unintuitive behavior of "use server" not currently being tree-shaken (only create endpoints for used routes on a page) meaning it's very easy to create the problem and, honestly, not easy to check unless you already know about the quirk.
Code review is great but it assumes everyone understands the "make it all an endpoint" behavior, which I wouldn't consider intuitive.
Powerful feature but could have been more explicit by annotating every exported endpoint separately instead.
BTW, given you're an insider of Versel, in-depth explanations like this would be so much more appreciated than drama or clickbaits
it's too hard
Frontend and backend should be seperate. Why every frontend framwork pushing fullstack?
Because it's more convenient but convenience is the bane of cleanliness, efficiency, security and basically everything else other than development speed. People care more about putting out garbage quickly than putting out good stuff slowly.
This is one of the reasons I like having a Spring Boot backend instead. It's so easy to have auth on *every* endpoint all controlled in one spot rather than having to remember to secure each one individually. Next.js should have something similar.
Should be “use api” or should have been a decorator or function wrapper or just have an api prefix apiDoSomething.
I think this is related to the adoption of functional programming over traditional OOP. Interesting stuff.
The mayor problem, I think, is that the abstraction seems specifically build so you don't have to think about the fact that you are writing and calling endpoints. Designing the API to make the server boundary invisible, then saying "silly developer, don't you know there are risks to this free-floating string" is not productive and doesn't help make things more secure.
When you say endpoint, does that mean we can call server actions from postman or similar tool? How?
Yes, server actions are just functions converted to post endpoints but it acts like an rpc call
@@heunha9269 say I have a use server action in a form at app/dashboard/page.tsx. how can I call it using postman?
So how do you write tests for these functions if you can’t export them? Can you make these private methods of a class and export that?
Same thought I had. You can move the function you want to test to its own file that does not "use server" and test it from there (this was shown in the video), but that's annoying. Ability to test random things without exporting them is one of the things I miss most working in JS/TS compared to Rust.
Yeah that’s actually one of the benefits of classes. Assuming your using typescript you can mark the method as private but still allow them to be accessible for testing.
damn the videos in the middle of the flow have started.
This is massively giving "hey, this bug may be a feature" approach
it would look better imo if the use server functions would explicitly receive as arguments the variables used from the ui context, so whoever looks at the code knows at a glance what inputs are generated and what is sent
I need to think about this more. But at first glance, it smells like how PHP would smell where it gave so much flexibility but gave all the footguns with it that led to so many security errors. Ah wells. More areas to go search for bug bounties in I guess.
My understanding is that "server only" directive is a safety catch for any trouble "use server" could cause.
This video is a good example for FE devs to learn and understand API gotchas.
Thats why I like zsa, create a server action that does the auth boiler plate, and reuse it with every action, using a 1 liner.
as a Java developer I find the problem and especially the conclusion to be the absolute basics of server development and it is so trivial that I'm quite speechless how did people arrive at this problem...
I mean if you dont have proper checks in api also it will have this same problem?
yeah, folks really don’t understand that its just an api, and issues have to be solved through code composition and organization, not by nextjs placing fake guardrails. Same thing happened back when react couldn’t explain to people what dtos are, and ended up implementing a crappy field level sccess control mechanism 😂
@@MrManafon people don't even understand how to have proper access control and then complain saying it's an issue lmao
Most big tech / companies projects do not include only 1 frontend application. I think use server makes a lot of sense for those who have only 1 client side and most developers are front-end. However, in most real world scenarios you would have 1 or more apis serving 2 or more front end application in which case server actions makes no sense unless you want to replicate the same code again and again for each client side.
Regarding the access control, it had nothing to do with server actions. It is much more related to the knowledge one might have regarding this topic.
that "sub to theo" callout was pretty smooth
The more and more I watch videos about Next, the better I feel that I switched to Remix from using Next.
Why is communication around Server Actions not making it immediately obvious that's it's basically an HTTP route. That important details would have prevented this very issue of unprotected routes.
Yeah it completely abstracts away the explicit calls to and from the server , obviously it’s a foot gun . Convenient at what cost?
MFW people don’t use middleware to secure all their routes
MFW people use cookies which are ass to validate in middleware due to how poorly designed middleware's "edge" runtime is.
@@hello19286 MFW people convinced they need globally distributed "serverless" "edge" functions for apps that will never have a lot of users nor a global audience and so they make sweeping compromises on security, architecture, and design decisions to meet this set of requirements that they don't have nor ever will
- separate server actions to their own file and use “use server” on the top
- don’t return sensitive data from server action
- validate requester identity in the server actions
See this is why I'm a big fan of the LAMP stack, at least I know it's insecure and I can at least mitigate it by literally requiring every input be purely alphanumeric, and I usually have three seperate functions all using different mechanisms to do that check.
Strings with different characters are not really a problem if you use prepared statements for the SQL. And just use htmlspecialchars to avoid XSS.
And your kinda paranoid. One Funktion does the trick.
@@jjjannes Being paranoid can't hurt for backend security.
Next-safe-action library is great for this usecase. Use library Middleware for user permission check
The solution can't be "audit and code review", the security of actions is way too fragile. Relying on people doesn't scale, sometime somewhere they will fail for whatever reason, and you will wish you had a compiler or linter telling "are you sure is this what you want?"
IMHO - Your GraphQL issue is only there because of the use of the schema dsl, I've always used the programatic api's and composed PER role graphs, they all run on the same ctx, but the graphs actually omit entire branches based on permissions.
0:13 Tons of Damage!
😂
oh boy
You’re all probably expect me
both are terrible decisions
“The delete button can own its behavior” somewhere Carson Gross just took his seventh shot of whiskey
Seems like a good use case for a higher order function that wraps the function with auth. Not sure if that is going to make the TS type definitions a bit unwieldy though. Very mixed feelings about this. I can see the arguments both ways. Leaning towards breaking widely held assumptions and making it insecure by default is a "bad thing" though. IFF the dev knows this, it is fine. But how many are actually going to know it is exposed?
Btw, what's with the namings? "endpoint-exports" would be a bit more descriptive than "actions". Less marketable, but a bit more self-explanatory.
IF you had an auth check in middleware for all the routes - wouldn't that blanket protect all POST to those routes?
Maybe Vercel should change that decorator to something else, like "as endpoint" instead of "use server"...
Does middleware do the same thing as checking headers security wise?
So if there is a unintentionally exposed function which does some heavy processing like data sync, calculations, or an AI generated response of text/image.
Someone could abuse it to call it directly where dev didnt think of implementing a check. Because they implemented a check on the original endpoint and not here.
Can it happen ?
Why doesn't the bundler expose only the exported functions? Rather than all exported from a file?
They still can allow all exports in an endpoint by coming up some other stupid term like "use server; export all"
Would using `next safe action` with middleware that checks for auth of some kind fix the problem?
Vercel might wanna add some type of "use this function to verify all use server"-functions. Instead of having to aduit all this shit and figure out every little possible leak that might happen...
Is there an ESLint or prettier plugin that you can use to lint for this?
When you typing I can see some suggestions words are showing randomly. Do you want to share, what are you using for this?
What do we do. Make it as bad practice and write eslint rule for newbie’s?
In express I call the auth middleware before every protected route. IT IS EXPLICIT.
The problem with server actions pattern is lack of CONTROL for BE devs, and IMPLICIT creation of endpoints.
Next.js auth middleware called on every route is bullshit, it should be selectivelly called on protected routes only.
relying on a code review for security aint it
If you read the documentation for Next.js they actually have a part that says that all server actions should be treated as public API endpoints and protected. So who's fault is it then ?
A middleware that checks the auth user, would solve the issue??
This video should have been called "Frontend devs slowly realizing that frontend dev isn't fullstack dev".
Colocation is all good until, you realize the implicit nature of use server is a leaky abstraction.
The solution is as simple as not allowing file-level "use server", just function level
Couldn't static analysis detect that an exported use server function is not used in the client?
Why is your Arc logo so beautifully shiny ✨ unicorny 🦄 looking? Like if if it was kissed by a fairy 🧚
I want this too!
That was a convoluted way to say frontend devs have skill issues 😅
If by "skill issues" you mean: a completely different specialty and foisting this on them was always going to end in tears
Looks like i was already doing things correctly but i didn't know that :D I'm new to web dev but i'm a senior backend dev so i probably already did this out of habit.
Thank you so much theo
Why to use server isn’t it already on server side rendering ?
I think Next.js tries to be too clever for it's own good and might drug Server Side React down with it.
Too much abstraction and complexity, bad development experience (hard to trace errors, buggy hot reloading, memory hog server).
You switch back to a Vite project and everything is light/fast and crystal clear.
I always prefer to spend more time writing explicit actions and routes with clear access control.
Which VS code theme does theo using !
If you have to dig into how internals of a framework work doesn’t it mean there’s smth wrong with it?
Ohh no, someone could hit my laravel controller with a post. If I do not check if they are allowed to, they could do something bad 🤯
So none of you did read the docs for next? This was clearly mentioned in there. How is this new?
What's wrong with the React (again)?
dude! Remix is def way more safe, faster and straightforward
Oh shit. We've came a full circle. A frontend framework templating a server xddd oh god. Js environment is a wacky one
So the lesson is, ensure origin is userId
I love your content. Since the twitter drama with yacine, you seem too preocupied with not being perceived as a shill, so your content seems targeted as cleansing your reputation (I love elixir, I am a serious programmer, etc.). Just be yourself, and focus on cool/useful content, nobody cares about purist, and everyone is tired with yacine's antics anyway.
theo go over why csrf token is useless on modern browseers
I know why I hate nextJS. The lack of separation of concerns makes me concerned.
Why is this video edited so weirdly? It jumps ahead then goes backwards to explain code that was existing.
Theo is the vercel guy
Just don't use top-level "use-server".
Do yourself a favour and understand that each function with the "use server" pragma creates an endpoint. From there, opt in as you see fit.
The only real solution 23:22
This is the way
good video