1. Server Actions authorization testing
Server Actions are async functions defined with the 'use server' directive. When called from a Client Component, Next.js exposes them as HTTP POST endpoints with a generated URL. The key finding we look for is Server Actions that perform data mutations without verifying the current user's authorization:
// VULNERABLE Server Action: no authorization check
'use server'
export async function updateUserTier(userId: string, tier: number) {
// Flaw: any authenticated user can upgrade any other user's tier
await db.user.update({ where: { id: userId }, data: { tier } });
} We call every Server Action directly using HTTP POST requests crafted in Burp Suite, bypassing the React component UI. This confirms whether authorization is enforced at the action layer or only in the client-side component logic that invokes it (which is trivially bypassed).
2. Next.js middleware bypass
Next.js middleware runs at the edge before a request reaches a page or API route. It is commonly used to check session cookies and redirect unauthenticated users. A critical class of bypass occurs when the middleware matches routes using string patterns that do not cover all routes that need protection. We have found cases where middleware protected /dashboard but not /dashboard.json, /dashboard/ (trailing slash), or API routes under the dashboard path that return the same sensitive data.
3. Environment variable exposure in client bundles
We inspect every Next.js production build's client-side JavaScript chunks for NEXT_PUBLIC_ prefixed variables. Finding a variable like NEXT_PUBLIC_PAYSTACK_SECRET_KEY in a production bundle is a critical finding that requires immediate remediation. We also inspect next.config.js for the env block, which can inadvertently expose server-only variables to the client runtime if the configuration is authored incorrectly.
4. API Route authorization
Next.js API routes (under pages/api/ or app/api/) are HTTP endpoints. We test every API route for: missing authentication middleware, Broken Object Level Authorization (where one user can fetch another user's data by changing an ID parameter), HTTP method restrictions (does a GET-only route accept POST requests?), and rate limiting enforcement on high-frequency sensitive endpoints.
5. Incremental Static Regeneration (ISR) cache poisoning
ISR allows Next.js pages to regenerate statically in the background. If a page's static regeneration path includes user-controlled data (such as a user profile slug that renders into a statically cached page), an attacker may be able to manipulate a cached page's content. We test ISR-enabled pages for paths where the cached output includes data derived from untrusted input sources.
Unauthenticated Server Action accessing admin database operations
During a penetration test of a Nigerian SaaS platform built on Next.js App Router, we enumerated Server Action endpoints using network traffic analysis. One action, intended to be triggered only from the admin dashboard, performed a bulk wallet balance reset operation. The action contained no session check. We called it directly via POST request without being logged in and successfully triggered the operation against our test accounts. Fix priority: critical. Remediated by adding a session check at the top of the Server Action and wrapping it in a role validation against the authenticated session.
Shipping a Next.js application handling real user data? Get a practitioner-led security assessment.
Book a Next.js PentestFrequently asked questions
What is the biggest security risk in Next.js App Router?
The biggest risk in App Router is the trust boundary between Server Components and Client Components. Server Components have direct database and file system access. If user-controlled input reaches a Server Component without authorization checks, the entire server-side data layer is exposed.
Can Server Actions be called directly by an attacker?
Yes. Next.js Server Actions are exposed as HTTP POST endpoints that can be called directly using a tool like curl or Burp Suite, bypassing the React UI entirely. We test every Server Action for authorization, input validation, and business logic bypass.
How do environment variables leak into Next.js client bundles?
Any environment variable prefixed with NEXT_PUBLIC_ is embedded into the client-side JavaScript bundle at build time. Developers sometimes accidentally prefix internal API keys, JWT signing secrets, or database connection strings with NEXT_PUBLIC_, making them visible in the browser.
Related reading
Blog: Next.js Server Actions deep dive · React SPA security testing · API data leaks
Services: Penetration testing · API security testing