5 min read

CSRF protection on Next.js Server Actions

Server Actions accept cross-origin POSTs by default. Add origin check or token validation.

Server Actions = cross-origin-by-default RPC. Without origin check, an attacker's site can trigger your app's actions on a logged-in user.

What it is

Server Actions are Next.js's RPC mechanism for invoking server code from client. By default they accept POST from any origin, making them CSRF-vulnerable.

Vulnerable example

// app/account/actions.ts
"use server";
export async function deleteAccount() {
  const session = await auth();
  if (!session) throw new Error("unauth");
  await db.users.delete(session.user.id);
  // Vulnerable: any cross-origin site can trigger this if user is logged in
}

Fixed example

// app/account/actions.ts
"use server";
import { headers } from "next/headers";
async function requireSameOrigin() {
  const h = await headers();
  const origin = h.get("origin");
  const host = h.get("host");
  if (!origin || new URL(origin).host !== host) throw new Error("origin mismatch");
}
export async function deleteAccount() {
  await requireSameOrigin();
  const session = await auth();
  if (!session) throw new Error("unauth");
  await db.users.delete(session.user.id);
}

How Securie catches it

Securie findinghigh
apps/web/app/api/route.ts:22

CSRF protection on Next.js Server Actions

CsrfSpecialist catches Server Actions without origin check at PR time. AuthAuthz specialist catches missing session check.

Suggested fix — ready as a PR
// app/account/actions.ts
"use server";
import { headers } from "next/headers";
async function requireSameOrigin() {
  const h = await headers();
  const origin = h.get("origin");
  const host = h.get("host");
  if (!origin || new URL(origin).host !== host) throw new Error("origin mismatch");
}
export async function deleteAccount() {
  await requireSameOrigin();
  const session = await auth();
  if (!session) throw new Error("unauth");
  await db.users.delete(session.user.id);
}
Catch this in my repo →Securie scans every PR · ships the fix as a one-click merge · free during early access

Checklist

  • Origin check at top of every state-changing Server Action
  • Session check after origin check
  • Re-MFA for high-risk actions (delete account, change password, change email, change payout)
  • Audit-log every state-changing action
  • Securie's CsrfSpecialist reviews every PR

FAQ

Does Next.js have built-in CSRF protection?

Limited. Modern Next.js checks Origin/Host alignment but only on Server Actions (not API routes). Add explicit checks.

What about Form actions?

Same pattern — use the requireSameOrigin helper.

Related guides