Next.js Server Actions security

Every Server Action is a public endpoint

A function marked "use server" can be called by anyone with a POST request, whether or not your UI ever shows the button. Hiding it behind an admin page protects nothing. Paste a Next.js repo and Wyro lists every Server Action and route handler that reaches your database without checking who is calling.

Free for public repositories. No account and nothing installed. Lovable, Bolt and v0 projects work once they are synced to GitHub.

How to secure them

  1. Authenticate inside every action that touches dataWyro checks this

    The check belongs in the action, not in the page that renders the form:

    "use server";
    export async function deletePost(id: string) {
      const session = await auth();
      if (!session) throw new Error("Unauthorized");
      await db.delete(posts).where(and(eq(posts.id, id), eq(posts.authorId, session.user.id)));
    }

    Wyro reads Server Actions as entry points and reports any that reach a table with no authentication on the way (auth-before-data).

  2. Authorize the row, not just the userWyro checks this

    if (!session) stops strangers. It does not stop a signed-in user deleting someone else's post by passing its id. Put the owner in the where clause, as above. Wyro marks actions where any signed-in user reaches the data (authenticated-no-authorization).

  3. Validate the argumentsWyro checks this

    Arguments arrive from the network, typed or not. Parse them with zod before use. TypeScript types are erased at runtime and check nothing.

  4. Middleware is not enough on its own

    A matcher that skips a path, or a refactor that moves an action, silently removes the check. Keep authentication in the action or in a data-layer function every action calls, so the guard travels with the code.

  5. Route handlers need the same careWyro checks this

    app/api/**/route.ts exports are public too. Wyro checks them with the same rules, along with Supabase calls made through a user-scoped or service-role client.

  6. Rate limit the expensive onesWyro checks this

    Sign-up, invites, email sending and anything that calls a paid API. Unlimited, each is a way to run up your bill or spam your users.

Keep it that way

A check run once goes stale the next time an agent adds a route. Sign in, press Watch this repo on its report, and Wyro emails you the day a push adds a new finding. Free.

Questions

Are Next.js Server Actions secure by default?

They get some protection by default: an unguessable action ID and an Origin check against CSRF. Neither checks who the caller is. Any logged-out visitor can still invoke an action, so authentication and authorization must be written inside it.

How does Wyro find Server Actions?

It reads every file and function marked "use server", follows the calls into your data layer, and records which tables each action reads or writes and whether an auth check sits on the path.

Does it run on private repositories?

The free web check reads public GitHub repositories. For private code, run npx wyro-check locally or in CI; the source never leaves your machine.

wyro.in/nextjs-server-actions-security