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.
@dough-pizza3 ай бұрын
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", () => { });
@carvierdotdev3 ай бұрын
@@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.
@zactron19973 ай бұрын
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.
@rod67223 ай бұрын
That's why I keep using API routes in NextJS instead of server actions. Less magic going on.
@MaxOut9313 ай бұрын
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 😅
@kylemichaelsullivan3 ай бұрын
"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.
@sulavbaral99723 ай бұрын
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
@bl_sonic32883 ай бұрын
@@sulavbaral9972 These are frontend devs we are talking about. They don't worry about user input, that's backend guys' problem.
@magne60493 ай бұрын
*frontend developers
@aberba3 ай бұрын
@@sulavbaral9972 because it's not immediately obvious is basically an HTTP route. That important details isn't well communicated.
@martybando16683 ай бұрын
@@kylemichaelsullivan Bingo
@RhysSullivan3 ай бұрын
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
@smallmoneybigmoney3 ай бұрын
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.
@ooijaz60633 ай бұрын
@@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...
@thethirdrace51073 ай бұрын
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.
@echobucket3 ай бұрын
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.
@James-ry3bo3 ай бұрын
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!
@yashkhambhatta95363 ай бұрын
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"
@MilesFlavel3 ай бұрын
I feel like "use server" should have some sort of mandatory access level argument
@3ventic3 ай бұрын
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.
@3ventic3 ай бұрын
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.
@monad_tcp3 ай бұрын
They basically recreated AspNet WebForms. It only took 15 years and the pendulum came back to server components entangled .
@furycorp3 ай бұрын
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
@alecmeyer36143 ай бұрын
100% the truth, they have so many similarities, it’s only flashier here because of React itself.
@cobrasys3 ай бұрын
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.
@PedroCoelhoTorresАй бұрын
I have been watching this video and laughing alone at how funny this is. Asp net was 100 times better than whatever nextjs is doing specially 15 yrs ago. And yeah history keeps repeating itself. I am waiting for them releasing a feature called code behind where your frontend and backend look like the same fine but one is the server action and the other one is the html. 😂
@lidinzx3 ай бұрын
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.
@rob61293 ай бұрын
Its not a security issue its a skill issue
@collinoly3 ай бұрын
@@rob6129 most security issues are skill issues. Memory leak in a C code base, skill issue. Still a security issue.
@bennythetiger60523 ай бұрын
@@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.
@ooijaz60633 ай бұрын
@@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...
@MrManafon3 ай бұрын
server actions are literally “separated backend api calls”, you are missing the point
@BobKane-g6x3 ай бұрын
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.
@MrManafon3 ай бұрын
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…
@RoyaltyInTraining.3 ай бұрын
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?
@DarkSwordsman3 ай бұрын
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?
@dealloc3 ай бұрын
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.
@MrManafon3 ай бұрын
“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
@MerthanMerter3 ай бұрын
next safe actions
@furycorp3 ай бұрын
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.
@MerthanMerter3 ай бұрын
@@furycorp you cant say there is no effort being put in to this
@steverude3 ай бұрын
Maybe they should invent an HTTP header for Authorization. They mustn’t have thought about it…
@NubeBuster3 ай бұрын
But what if one endpoint is supposed to be public and the internal function not?
@memeteamdreamteam39903 ай бұрын
React keeps making various forms of useEffect footguns lol
@theairaccumulator71443 ай бұрын
React itself is a footgun
@khaled_osman3 ай бұрын
separation of concerns went from html and css in js, to backend in frontend really quick. what a mess.
@PpVolto3 ай бұрын
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
@kisaragi-hiu3 ай бұрын
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.
@cloynelson29743 ай бұрын
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.
@FeFeronkaMetallica3 ай бұрын
It is there in the docs
@kevin55233 ай бұрын
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
@nordern13 ай бұрын
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.
@bosung903 ай бұрын
In our team, we always end our filename with .server for server run code. For example, actions.server.ts
@rivomananamandaniaina51933 ай бұрын
actions are basically running on server, aren't they? if not, they are just js/ts functions..
@SimonHuggins3 ай бұрын
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.
@BellCube3 ай бұрын
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.
@prozacgod3 ай бұрын
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 .
@Fuzbo_3 ай бұрын
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.
@duven603 ай бұрын
I like that idea, make it part of the jsDocs or something so it shows up in the intelligence anywhere the function gets used
@NotherPleb3 ай бұрын
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?"
@SingWithCJ3 ай бұрын
Powerful feature but could have been more explicit by annotating every exported endpoint separately instead.
@aberba3 ай бұрын
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.
@SirCorrino3 ай бұрын
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.
@iftyislam67613 ай бұрын
Frontend and backend should be seperate. Why every frontend framwork pushing fullstack?
@theairaccumulator71443 ай бұрын
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.
@collinoly3 ай бұрын
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?
@---..3 ай бұрын
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.
@collinoly3 ай бұрын
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.
@DevinMakhulo3 ай бұрын
My understanding is that "server only" directive is a safety catch for any trouble "use server" could cause.
@cloynelson29743 ай бұрын
BTW, given you're an insider of Versel, in-depth explanations like this would be so much more appreciated than drama or clickbaits
@_crystaleyes19223 ай бұрын
it's too hard
@codedusting3 ай бұрын
When you say endpoint, does that mean we can call server actions from postman or similar tool? How?
@heunha92693 ай бұрын
Yes, server actions are just functions converted to post endpoints but it acts like an rpc call
@codedusting3 ай бұрын
@@heunha9269 say I have a use server action in a form at app/dashboard/page.tsx. how can I call it using postman?
@web_dev_cz3 ай бұрын
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...
@cloynelson29743 ай бұрын
This is massively giving "hey, this bug may be a feature" approach
@kiriappeee3 ай бұрын
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.
@andreichicu27993 ай бұрын
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
@aprilmintacpineda27133 ай бұрын
- 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
@shaked12333 ай бұрын
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.
@jazzymichael3 ай бұрын
I think this is related to the adoption of functional programming over traditional OOP. Interesting stuff.
@VitorLima-im4ee3 ай бұрын
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.
@sulavbaral99723 ай бұрын
I mean if you dont have proper checks in api also it will have this same problem?
@MrManafon3 ай бұрын
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 😂
@sulavbaral99723 ай бұрын
@@MrManafon people don't even understand how to have proper access control and then complain saying it's an issue lmao
@thegrumpydeveloper3 ай бұрын
Should be “use api” or should have been a decorator or function wrapper or just have an api prefix apiDoSomething.
@rns103 ай бұрын
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 ?
@AngelEduardoLopezZambrano3 ай бұрын
MFW people don’t use middleware to secure all their routes
@hello192863 ай бұрын
MFW people use cookies which are ass to validate in middleware due to how poorly designed middleware's "edge" runtime is.
@furycorp3 ай бұрын
@@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
@the_disco_option3 ай бұрын
that "sub to theo" callout was pretty smooth
@robhough23323 ай бұрын
IF you had an auth check in middleware for all the routes - wouldn't that blanket protect all POST to those routes?
@psyferinc.35733 ай бұрын
damn the videos in the middle of the flow have started.
@rixis29403 ай бұрын
This video is a good example for FE devs to learn and understand API gotchas.
@MrJfergs3 ай бұрын
Colocation is all good until, you realize the implicit nature of use server is a leaky abstraction.
@MrHopp243 ай бұрын
Yeah it completely abstracts away the explicit calls to and from the server , obviously it’s a foot gun . Convenient at what cost?
@francois-pierrethibault26513 ай бұрын
Next-safe-action library is great for this usecase. Use library Middleware for user permission check
@cobrasys3 ай бұрын
This video should have been called "Frontend devs slowly realizing that frontend dev isn't fullstack dev".
@igor9silva3 ай бұрын
The solution is as simple as not allowing file-level "use server", just function level
@prozacgod3 ай бұрын
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.
@incarnateTheGreat3 ай бұрын
The more and more I watch videos about Next, the better I feel that I switched to Remix from using Next.
@StingSting8443 ай бұрын
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"
@zacclifton54793 ай бұрын
Is there an ESLint or prettier plugin that you can use to lint for this?
@n1rus3 ай бұрын
What do we do. Make it as bad practice and write eslint rule for newbie’s?
@MarcelRobitaille3 ай бұрын
Couldn't static analysis detect that an exported use server function is not used in the client?
@DellmantHD3 ай бұрын
Would using `next safe action` with middleware that checks for auth of some kind fix the problem?
@captainlennysub3 ай бұрын
0:13 Tons of Damage!
@sahilpanigrahi61633 ай бұрын
😂
@vivsh.19993 ай бұрын
oh boy
@muhammadalifdanielbinmohdh31883 ай бұрын
You’re all probably expect me
@potors3 ай бұрын
both are terrible decisions
@abcdmku13 ай бұрын
relying on a code review for security aint it
@kassios3 ай бұрын
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.
@fronix50603 ай бұрын
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...
@cloynelson29743 ай бұрын
Btw, what's with the namings? "endpoint-exports" would be a bit more descriptive than "actions". Less marketable, but a bit more self-explanatory.
@cloudsss833 ай бұрын
Maybe Vercel should change that decorator to something else, like "as endpoint" instead of "use server"...
@mdazimbabu50013 ай бұрын
Why to use server isn’t it already on server side rendering ?
@RishavMondal-i1u3 ай бұрын
When you typing I can see some suggestions words are showing randomly. Do you want to share, what are you using for this?
@MrHopp243 ай бұрын
“The delete button can own its behavior” somewhere Carson Gross just took his seventh shot of whiskey
@Blue-Robin3 ай бұрын
Does middleware do the same thing as checking headers security wise?
@metalbroga3 ай бұрын
A middleware that checks the auth user, would solve the issue??
@codeChuck2 ай бұрын
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.
@ritikdwivedi59833 ай бұрын
Which VS code theme does theo using !
@brennan1233 ай бұрын
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?
@LutherDePapier3 ай бұрын
I've heard this before, the issue is that users need to be authenticated on every action. How is that not the most basic server-side best practice every developer should already know about?
@LutherDePapier3 ай бұрын
I mean for real, actions in React 19 are like actions in Remix. They're basically an endpoint anyone can hit if they know the endpoint. If you have a route called /create in Remix anyone can type /create in the URL. It's up to you as a developer to always authenticate on the action itself before doing anything else, even if there already is some middleware auth somewhere else in the project. So I really don't see what the issue is here.
@LutherDePapier3 ай бұрын
"Web developers aren't used to dealing with access control." So all this is is a skill issue. Noted.
@LutherDePapier3 ай бұрын
...And Ryan Florence is 100% right on this.
@lipemenezes233 ай бұрын
I always prefer to spend more time writing explicit actions and routes with clear access control.
@includenull3 ай бұрын
That was a convoluted way to say frontend devs have skill issues 😅
@duven603 ай бұрын
If by "skill issues" you mean: a completely different specialty and foisting this on them was always going to end in tears
@linuxguy11993 ай бұрын
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.
@jjjannes3 ай бұрын
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.
@linuxguy11993 ай бұрын
@@jjjannes Being paranoid can't hurt for backend security.
@LuicMarin3 ай бұрын
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 ?
@alexandertarasenko30383 ай бұрын
If you have to dig into how internals of a framework work doesn’t it mean there’s smth wrong with it?
@balqaasem2 ай бұрын
So the lesson is, ensure origin is userId
@FeFeronkaMetallica3 ай бұрын
So none of you did read the docs for next? This was clearly mentioned in there. How is this new?
@RezetRoy3 ай бұрын
What's wrong with the React (again)?
@dovonun3 ай бұрын
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 🤯
@metsatroll3 ай бұрын
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.
@Jdinrbfidndifofkdndjoflfndjdk3 ай бұрын
dude! Remix is def way more safe, faster and straightforward
@limbo35453 ай бұрын
I know why I hate nextJS. The lack of separation of concerns makes me concerned.
@MaxOut9313 ай бұрын
Why is your Arc logo so beautifully shiny ✨ unicorny 🦄 looking? Like if if it was kissed by a fairy 🧚 I want this too!
@SeanCassiere3 ай бұрын
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.
@dodyprass3 ай бұрын
The only real solution 23:22
@Magnom3653 ай бұрын
This is the way
@aymenbachiri-yh2hd3 ай бұрын
Thank you so much theo
@moosegoose12823 ай бұрын
theo go over why csrf token is useless on modern browseers
@LeonBlade3 ай бұрын
Why is this video edited so weirdly? It jumps ahead then goes backwards to explain code that was existing.
@12crenshaw3 ай бұрын
Oh shit. We've came a full circle. A frontend framework templating a server xddd oh god. Js environment is a wacky one
@mikert893 ай бұрын
Theo is the vercel guy
@CodingEnjoyer3 ай бұрын
Just use next safe actions and your problem is solved