Your Next.js App Is Not 'Static' — and That’s a Security Problem

"It's just static files on a CDN."
This was the golden promise of the JAMstack era. Gatsby, Jekyll, and early Next.js versions sold us on the idea that if you pre-build your site, it is unhackable. You can't hack an HTML file.
That era is dead.
With the advent of the App Router, React Server Components (RSC), and Server Actions, your "static" Next.js app is barely static at all.
The "Hybrid" Trap
Modern Next.js applications are hybrid. They can serve static content, but the moment you use a <form action={serverAction}>, you have spun up an API endpoint.
[!CAUTION] Even if you export as "static" (SSG), most Vercel deployments default to serverless functions for handling ISR (Incremental Static Regeneration) and image optimization.
The Attack Surface Has Shifted
In the old days (Pages router), API routes were explicit: /pages/api/hello.ts. You knew that file was a backend.
In the App Router:
page.tsxis a server.actions.tsis a server.layout.tsxis a server.
The default mental model is "I am writing UI". But efficient RCEs like React2Shell exploit exactly this confusion. Developers think they are writing frontend components, but they are actually configuring a deserialization endpoint on a Node.js server.
Vercel ≠ Safe by Default
Vercel provides excellent infrastructure, but they cannot protect you from application-level logic flaws.
If your code says "Deserialize this input and execute it" (which is effectively what vulnerable RSC parsers did), Vercel's WAF (Web Application Firewall) will dutifully pass that request through to your function.
The "Serverless" Myth
"But it's serverless, the container dies after execution!"
- Persistence: Containers are reused for performance (warm starts). A polluted global scope persists across requests.
- Environment Variables: An attacker only needs one execution to read
process.env. - Lateral Movement: From that one execution, they can query your database or access your internal VPC.
Reclaiming Security
We need to treat Next.js apps with the same paranoia as we treat Express.js or Rails apps.
- Assume it is a Server: Audit every file as if it's a backend endpoint.
- Sanitize Inputs: Zod is your best friend. Validate every argument passed to a Server Action.
- Content Security Policy (CSP): It’s annoying to set up, but it stops a lot of attacks.
Your app is not static. Stop pretending it is.
Did you enjoy this post?
Give it a like to let me know!


