Most Next.js Server Actions we scanned had no auth check. The rate is falling with each version.
A Next.js Server Action is a public POST endpoint, and the page's session check does not extend to it. So a mutating action that does not authorize the caller inside the handler can be run by anyone who reaches the URL, directly, with no login and no UI in the way. The mechanism is well documented, and broad "AI ships broken access control" prevalence has now been measured too. What was not: how often the check is missing on Server Actions specifically, and whether that is getting better or worse by version. We scanned public Next.js repositories and counted.
The setup, with receipts
A function marked 'use server' compiles to an HTTP endpoint that anyone can call directly with
any payload. Next.js says this in its own Data Security guide:
Server Actions "are exposed as public HTTP endpoints" and "you should treat them with the same
security considerations as public-facing API endpoints," verifying whether the user is allowed to
perform the action. Independent write-ups say it more bluntly: MakerKit's
five Server Action vulnerabilities
opens with "Server Actions are public endpoints. Full stop," and Vidoc Security Lab's
Next.js security teardown shows the
same auth-bypass shape end to end.
The reason it is easy to miss is structural. The check used to live at the route, where a
framework could guard it; Server Actions moved it into the function body, where only the author
guards it. And relying on the layer above the action is itself unsafe: the March 2025
x-middleware-subrequest bypass, CVE-2025-29927,
let a header skip Next.js middleware entirely, which is exactly why the guidance is to authorize
inside each action rather than lean on middleware.
So the mechanism is known. Practitioners even title their posts after it, like DEV's "the auth check most developers miss." The broad prevalence has since been measured, so we do not claim it. Deng, Fan and Meng (arXiv 2606.23130, June 2026) audited 200 vibe-coded apps and found Broken Access Control in 75.5% of repositories, their single largest category, with the same stated cause: models generate functional endpoints without access control unless told otherwise. Two things here are narrower and, as far as we found, still unmeasured: the rate for Next.js Server Actions specifically (one idiom, not the broad OWASP A01 bucket), and how that rate moves across framework versions. Both are below.
The number
We scanned 983 public repositories, of which 160 use a Server Action mutation. Across those, the large majority ship at least one mutating action with no session or authorization guard in the handler. We counted it two ways, and at this N they agree.
Read the claim precisely, because the precise version is the defensible one. We measured a code
pattern, a mutating 'use server' handler with no in-handler guard, not a confirmed vulnerability.
Some actions are unauthenticated on purpose, a sign-up or a contact form. The next number is what
separates the two.
The bars above are what the detector measured. What the detector measured is not automatically what is true, so the honest figure is a band, not a point. Our precision audit below puts the detector's floor near three quarters, and applying that floor to the measured 74% gives a true rate of roughly 55% to 74% of repositories. We report the band because it is the defensible object, and because the headline survives its own worst case: at the precision floor it is still most of them.
It is dropping as the framework matures
The rate is not constant. Broken out by Next.js major version, it falls with each release.
Why it is not just fixed
The obvious question, given that Next.js documents the risk itself, is why the framework does not
just enforce the check. The answer is that authorization is the one thing the framework cannot
know. Who may call deleteAccount is the account's owner; who may edit a post is that post's
author. Those rules live in your user model, not in Next.js, so there is no correct check for the
framework to insert. It also cannot tell an action meant to be public (a newsletter signup) from
one that is not (a role change). Only the author can.
What Vercel can enforce, it does. Server Actions ship with automatic CSRF and origin checks, and
the action IDs are hashed so they cannot be trivially enumerated. Those protections are
app-agnostic, so the framework owns them. Authorization is app-specific, so it was handed to
documentation, to libraries like next-safe-action, and to better defaults over time.
That is why the rate erodes instead of dropping to zero. A code bug gets patched and the rate cliffs; a footgun gets discouraged and the rate declines slowly, version by version, as the guidance spreads and the ergonomic path gets safer. The version curve above is what a cultural fix looks like, not a shipped one.
The stronger fix would be default-deny: make every mutating action declare an authorization policy,
with public as an explicit opt-out. next-safe-action's authActionClient is effectively that at
the library level. Next.js has not made it the default because it would break the write-a-function
ergonomics that made Server Actions popular, and every app already built on them. Secure-by-default
is hardest exactly when the secure behavior is the part only the developer can specify.
The flagged actions are mostly the sensitive kind
If the unguarded actions were all public forms, the pattern would not matter. They are not. Of the flagged files we classified whether the action touches user-scoped or privileged data (account, profile, role, admin, payment, order) or reads like a public form (register, contact, newsletter).
Methodology
The pipeline is a static read over a public sample, characterized before it was trusted. Each step and its known bias:
- Sample. Public GitHub repositories found by code-searching for the
'use server'directive, kept only if they carrynextin package.json and contain at least one Server Action mutation. Read-only actions are excluded from the denominator. - Detector. A static read: for each
'use server'handler that mutates (create/update/delete/upsert, orINSERT/UPDATE/DELETE), we check for a session or authorization guard in the same handler window. No guard in the window, and it counts. - Precision audit. Planted fixtures only prove the regex works on clean examples, so we read a sample of flagged files from real repos for auth that sits outside the handler, in a wrapper or an action-client library like next-safe-action. In that sample none used a centralized wrapper; about three quarters had no auth signal in the file at all; the rest referenced a guard elsewhere in the file. Precision floor near three quarters, so we report the rate as a range rather than a single percentage.
- We checked our own. The withseatbelt site is a static export, which disables Server Actions, so it cannot carry this pattern. We ran the detector on it anyway and it came back clean.
- Browse only. Public source, read in memory and discarded, aggregate counts only. No repo, path, or content is retained; nothing is probed live.
What this is not
- A vulnerability rate. We measured a code pattern. The sensitivity split argues most flagged actions are the kind that should be guarded, but it does not prove any single one is exploitable.
- A framework bug. The missing check is the author's to add, not a Next.js default. The decline across versions is consistent with better guidance and defaults arriving over time, but the framework still does not enforce the check, which is the whole reason the rate is what it is.
- A per-repo claim about who wrote the code. We do not tag individual repos as AI-written,
and deliberately so: the config that would mark it (
.cursor,CLAUDE.md) is usually gitignored, and in 2026 there is no meaningful non-AI control group to compare against. Roughly 84% of developers use or plan to use AI coding tools, and JetBrains' January 2026 survey of 10,000+ developers puts regular use at 90%. So read this as the prevalence in how Next.js is written now, which is overwhelmingly with AI assistance. As a check we did split by tooling markers anyway, and the marked repos were if anything slightly lower (63% versus 77%), which is noisy at that sample and cuts against a simple "AI writes it worse" reading. We make no causal claim in either direction. We measured the pattern, not its cause. - A census. Public GitHub skews toward demos and boilerplate, which likely raises the rate versus production apps, and code search caps at a fixed result window (we hit it at 983).
- The last word. The rate here, roughly 55% to 74% across 160 repos that use a Server Action mutation, is solid enough to report and stated as a band for the reason given above. A fork-deduplicated sample and a blind expert audit of the flagged files would narrow it and settle the precision-floor question.
Why a single-repo scanner could not measure this
A missing check in one repo is a bug. A missing check in most repos is a property of how the code gets written, and that property does not exist inside any one repository. Single-repo tools find the missing check in your app. They cannot tell you it is common, because "common" lives in the rate across many apps, not in any one of them. The auth check on a Server Action is the kind of cross-surface invariant that is easy to drop: the endpoint is written in one place, the check belongs in another, and nothing fails when it is absent until someone calls the action directly. In the public Next.js repos we sampled, it is absent more often than not.
Sources
Sources
- Understanding the (In)Security of Vibe-Coded Applications · Audited 200 vibe-coded apps; Broken Access Control in 75.5% of repos, their largest category. The broad prevalence we do not re-claim; our work narrows to the Next.js Server Action idiom and the version trend.
- Data Security in Next.js (Server Actions) · States Server Actions are exposed as public HTTP endpoints and must verify the caller's authorization, like any public API.
- Secure Next.js Server Actions: 5 Vulnerabilities You Must Fix · 'Server Actions are public endpoints. Full stop.' Practitioner statement of the mechanism.
- Next.js 14 Security: Server Actions Auth Bypass & Data Leaks · Walks the missing-authorization bypass end to end.
- CVE-2025-29927: Next.js Middleware Authorization Bypass · The x-middleware-subrequest header skipped middleware entirely. Why leaning on the layer above the action is unsafe, and why the check belongs inside each action.
- Next.js 16 Server Actions Security: The Auth Check Most Developers Miss · The mechanism is documented well enough that posts are titled after it.
- next-safe-action · The centralized action-client pattern our precision audit checked for and did not find in the flagged sample.
- Vibe Coding Vulnerabilities · ~80% of AI-built apps miss auth rate-limiting. Adjacent control, different surface; not the same measurement.
- Stack Overflow Developer Survey 2025 · Basis for treating current code as overwhelmingly AI-assisted rather than attributing per repo.
- Which AI Coding Tools Do Developers Actually Use at Work? · 90% regularly use at least one AI tool; the survey avoided AI-mention self-selection bias.
ResearchConnorSeatbelt