Server Actions Security
Why you can never trust the Client payload.
Public Endpoints
It is a common misconception that Server Actions are 'internal' functions safely hidden away on the server.
In reality, Next.js compiles every Server Action into a public HTTP POST endpoint. Anyone with the URL can trigger it from outside your application.
Zero Trust Architecture
Because they are public endpoints, you must treat them with the exact same paranoia as a traditional REST API route.
You cannot trust the data being sent from the client, and you must verify that the user making the request is authorized to perform the action.
Internal Validation
Always retrieve the user's session securely *inside* the body of the Server Action.
Never accept sensitive identifiers (like userId or role) as arguments passed from the client, because a malicious user can simply change the arguments in their network request.
The Payload Forgery
Hover over the 'Bad Practice' and 'Good Practice' tabs to see how an attacker can manipulate arguments passed from the client, and how to prevent it by reading the session securely on the server.
Malicious POST Request
Content-Type: application/json
// Payload modified by attacker in browser:
{
"args": [
Server Action
// Attacker can delete ANY account by changing the payload.
await db.accounts.delete(userId);
Check yourself
Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.
Remember this
- Server Actions are exposed as public HTTP POST endpoints.
- Treat them with the same security paranoia as traditional API routes.
- Never trust sensitive identifiers (
userId,role) passed in as arguments. - Always validate the user's session and authorization INSIDE the action body.
- Use libraries like Zod to validate the incoming data payload.
Done with this concept?
Mark it complete to track your progress. No login needed.