Home/Blog/Vulnerability Research
Vulnerability ResearchPublished ยท Updated โšก 15 min read

Stop shipping vulnerabilities in Next.js 16 Server Actions and RSCs.

A deep dive into Next.js App Router vulnerabilities, SSRF, insecure deserialization, and how to secure Server Actions.

VG
Vladyslav Gusarov
DevSecOps Lead at Bryxe
Next.js 16 Security: The Ultimate App Router Guide [2026 Audit]

Look, everyone loves Next.js 16. It's the golden child. You get Server Actions, React Server Components (RSC), and some janky bleeding-edge hydration tricks. But under the hood? It's a massive attack surface. If you blindly ship to prod without understanding how the App Router actually handles data, you are basically handing out root access.

I've audited over 50 enterprise codebases this year. Next.js App Router vulnerabilities are everywhere. It's not a framework issue. It's an engineer issue. Devs treat Server Actions like old-school API endpoints. They aren't. They are hidden RPC calls wrapped in magic.

Bottom line: Next.js security isn't just about XSS anymore. We are talking SSRF, insecure deserialization, and massive data leaks via RSC payloads.

The React Server Components Security Footgun

RSCs sound great. Keep the bundle size small. Render on the server. But here is the problem. When you fetch data in a server component, you might over-fetch. If you pass an entire user object to a client component, Next.js serializes it. Even the fields you didn't render.

I'm tired of seeing this in PRs. Boom. PII leaked in the network tab.

I saw a massive data breach last month. A dev fetched a Prisma user record. Passed it down. The password hash and reset tokens went straight to the browser. You have to scrub your data before it crosses the network boundary. Use DTOs (Data Transfer Objects). Always.

Server Actions Security: The RPC Nightmare

Server Actions are the biggest footgun in Next.js 16. Devs write a function, slap 'use server' at the top, and call it a day.

They forget that anyone can hit that endpoint. It's publicly exposed. You can literally curl it.

Vulnerable Server Action Example

Look, I've seen this a hundred times. Here is what I see in every PR review. Pure garbage.

typescriptSource Code
'use server'

import { db } from '@/lib/db'

// โŒ VULNERABLE: No auth check, no input validation
export async function updateProfile(userId: string, data: any) {
  await db.user.update({
    where: { id: userId },
    data
  })
}

What happens here? IDOR (Insecure Direct Object Reference). Mass assignment. I can pass any userId and update anyone's profile. I can pass role: 'ADMIN' in the data object. You just got owned.

Secure Server Action Example

You want to survive? You need Zod for validation and NextAuth (or whatever) for session checks. Every single time.

typescriptSource Code
'use server'

import { auth } from '@/auth'
import { db } from '@/lib/db'
import { z } from 'zod'

const updateProfileSchema = z.object({
  name: z.string().min(1).max(50),
  bio: z.string().max(160).optional()
})

// โœ… SECURE: Session checked, input sanitized
export async function updateProfile(formData: FormData) {
  const session = await auth()
  
  if (!session?.user?.id) {
    throw new Error('Unauthorized')
  }

  const rawData = {
    name: formData.get('name'),
    bio: formData.get('bio')
  }

  const validated = updateProfileSchema.safeParse(rawData)

  if (!validated.success) {
    throw new Error('Invalid input')
  }

  await db.user.update({
    where: { id: session.user.id },
    data: validated.data
  })
}

Notice the difference? We pull the ID from the session, not the client. We parse exactly what we expect. Nothing else gets through.

SSR and SSRF: The Hidden Demons

Honestly, it's a nightmare. Server-Side Rendering (SSR) isn't new. But with Next.js 16 pushing everything to the edge or the server, SSRF (Server-Side Request Forgery) is spiking.

When your server fetches an image from a user-provided URL to optimize it, or hits a webhook, you are vulnerable. If I pass http://localhost:3000/internal-api or http://169.254.169.254/latest/meta-data/ to your image component, your server makes the request.

You just leaked AWS credentials.

To fix this, you have to lock down outbound requests. Use an egress proxy. Validate URLs. Never blindly trust user input in fetch() calls on the server.

Real CVE Impact and ROI

I'm tired of seeing this in PRs. Let's look at the numbers. Fixing these issues post-breach costs millions.

Attack VectorFrequencyAverage CostPrevention Time
RSC Data LeakHigh$150k2 hours (DTOs)
IDOR in ActionsVery High$400k5 hours (Zod/Auth)
SSRF via SSRMedium$800k10 hours (Egress Proxy)

You think it's expensive to do it right? Try explaining a data breach to your board. Nuke the bad patterns now.

AUTOMATED DEFENSE

Don't wait for an exploit to audit your codebase

Review supported code risks, exposed secrets and dependency findings with Bryxe Shield. Verify the fixes in your application before release.

Need a practical next step? Explore the security field guides or read our editorial and sourcing policy.

Recommended Security Research