· via dev.to (home feed)
Next.js Server Actions get built-in CSRF checks that API routes must add themselves
A dev.to post explains that Next.js automatically verifies the Origin header on Server Action calls, while API route handlers accept forged cross-site requests unless developers add origin checks.

A post on dev.to draws attention to an asymmetry in Next.js security defaults: Server Actions and API route handlers look like similar server-side constructs, but only one of them defends against cross-site request forgery out of the box.
What Server Actions get automatically
According to the post, Next.js inspects the Origin header of every Server Action request and compares it against the application's own host. When the two do not match, the framework rejects the call before any developer-written code in the action executes. The author emphasises that this check requires no configuration — it emerges from the design of Server Actions, which are meant to be triggered from the app's own forms and components. Because Next.js knows its own build output and deployed domain, it has everything it needs to enforce the same-origin rule without help.
Why route handlers are left exposed
Route handlers under app/api/ are meant as flexible, general-purpose HTTP endpoints, and that flexibility is exactly why they receive no equivalent protection. Next.js cannot assume who is allowed to call such an endpoint — it might legitimately be a mobile client, a webhook from an external service, or the app's own frontend — so it performs no origin validation at all.
The post spells out the consequence. If a user is logged in to the app in one browser tab and a malicious site in another tab silently submits a form POST to the handler's URL, the browser attaches the session cookie to that request. From the handler's perspective, the forged request is indistinguishable from a legitimate call made by the app's own interface, unless an explicit check is added.
The fix is an explicit origin check
The remedy the author proposes mirrors what Server Actions receive for free: read the Origin header, compare it against the expected origin held in an environment variable such as the app's public URL, and return a 403 when the values disagree, before touching session or body data. Not every route needs this — a public GET endpoint returning non-sensitive data has no stake in where a request came from — but anything that mutates state on behalf of an authenticated session is precisely the kind of target CSRF exploits and should verify its origin.
Origin checks are not authorization
The post is careful to limit the claim. Origin verification defends specifically against requests forged on another site that exploit a victim's active session. It says nothing about whether the authenticated user is actually permitted to perform the action they requested. A Server Action that correctly refuses a cross-origin request can still let one user modify another user's data if it trusts an ID supplied by the client instead of deriving identity from the session. Origin checking and authorization are separate layers, and implementing one does not cover the other.
Why it matters
The piece closes with a practical audit suggestion: any team running API route handlers in production that change data based on a session cookie should verify whether those endpoints validate request origin, or whether they will accept and process a request from any source so long as a valid session cookie accompanies it. The broader lesson is that framework safeguards often protect a narrow class of attack. Server Actions and route handlers appear equally server-side to developers, yet their default security postures differ significantly — and neither relieves you of writing authorization logic yourself.
- #next-js
- #csrf
- #web-security
- #server-actions
- #api-routes