NeuroStrike

7 Vulns in Every AI-Generated Next.js App

NeuroStrike Research

Security Research Team

|4 min read
7 Vulnerabilities We Find in Every AI-Generated Next.js App

We've scanned over 500 Next.js applications built with AI coding assistants — primarily Cursor with Claude/GPT-4 and Vercel's v0. The same vulnerability classes show up with remarkable consistency. This isn't a top-10 list padded with theoretical risks. These are seven issues we exploit successfully in the majority of apps we test.

1. Server Actions Without Authorization Checks

Next.js Server Actions are the number one source of critical vulnerabilities in AI-generated apps. The AI generates a 'use server' function, wires it to a form, and never adds an auth check. The result is an unauthenticated mutation endpoint.

// Vulnerable: no auth check in server action
"use server";

export async function deleteUser(userId: string) {
  await db.user.delete({ where: { id: userId } });
  revalidatePath("/admin/users");
}

Anyone can call this function directly. The fix is simple but the AI almost never generates it:

// Fixed: verify session and role
"use server";
import { auth } from "@/server/auth";

export async function deleteUser(userId: string) {
  const session = await auth();
  if (!session?.user || session.user.role !== "admin") {
    throw new Error("Unauthorized");
  }
  await db.user.delete({ where: { id: userId } });
  revalidatePath("/admin/users");
}

Your AI-built app might have vulnerabilities

Get a full breach simulation with proof-of-concept exploits — not just a header check.

Run a Vibe Scan

2. Exposed Environment Variables via Route Handlers

Next.js bundles any variable prefixed with NEXT_PUBLIC_ into client JavaScript. AI assistants frequently suggest using NEXT_PUBLIC_ for variables that should stay server-side, or they create API route handlers that return internal configuration.

We found route handlers that returned full database connection strings, Stripe secret keys, and JWT signing secrets. In one case, a v0-generated app had a /api/config endpoint that returned every environment variable in process.env.

3. Missing CSRF Protection on Mutations

Next.js Server Actions include CSRF protection by default — but only when used through the form action binding. When AI generates client-side fetch calls to Route Handlers for mutations, there's no CSRF token. We successfully forged cross-origin POST requests against 67% of apps that used Route Handlers for state-changing operations.

// Vulnerable: Route Handler with no CSRF protection
export async function POST(req: Request) {
  const { email, role } = await req.json();
  await db.invitation.create({ data: { email, role } });
  return Response.json({ success: true });
}

4. Prisma Raw Queries with User Input

When AI can't express a query through Prisma's type-safe API — full-text search, complex joins, window functions — it drops to $queryRaw or $queryRawUnsafe. The difference matters: $queryRawUnsafe doesn't parameterize.

// Vulnerable: string interpolation in raw query
const results = await prisma.$queryRawUnsafe(
  `SELECT * FROM "Product" WHERE name ILIKE '%${searchTerm}%'`
);
// Fixed: use tagged template for parameterization
const results = await prisma.$queryRaw`
  SELECT * FROM "Product" WHERE name ILIKE ${`%${searchTerm}%`}
`;

BaxBench's 2024 evaluation found that LLMs produce SQL injection vulnerabilities in 15-38% of generated database queries, depending on the model and prompt complexity.

Your AI-built app might have vulnerabilities

Get a full breach simulation with proof-of-concept exploits — not just a header check.

Run a Vibe Scan

5. Insecure Direct Object References in API Routes

This is the most predictable finding. Every app with user-specific data has at least one endpoint where changing the ID parameter returns another user's data. The AI generates the lookup but not the ownership check. We covered this pattern in depth in our vibe coding security cost article, but it bears repeating: 83% of multi-tenant apps have at least one IDOR.

6. Missing Security Headers

Not a single AI-generated app in our dataset set security headers correctly. No Content-Security-Policy. No Strict-Transport-Security (even on HTTPS). No X-Content-Type-Options. Next.js provides a headers() config in next.config.js, but the AI never generates it unless you specifically ask.

// next.config.js — minimum security headers
const securityHeaders = [
  { key: "Strict-Transport-Security", value: "max-age=63072000; includeSubDomains; preload" },
  { key: "X-Content-Type-Options", value: "nosniff" },
  { key: "X-Frame-Options", value: "DENY" },
  { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
  { key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=()" },
];

module.exports = {
  async headers() {
    return [{ source: "/(.*)", headers: securityHeaders }];
  },
};

7. Unvalidated Redirect After Authentication

OAuth and magic-link flows need a callback URL. AI-generated auth implementations typically accept any URL in the redirect parameter, enabling open redirect attacks. Attackers use these to phish credentials by redirecting users from a legitimate domain to a lookalike.

// Vulnerable: accepts any redirect URL
const callbackUrl = searchParams.get("callbackUrl") || "/";
redirect(callbackUrl);
// Fixed: validate redirect is internal
function safeRedirect(url: string, fallback = "/"): string {
  if (!url || !url.startsWith("/") || url.startsWith("//")) {
    return fallback;
  }
  return url;
}
const callbackUrl = safeRedirect(searchParams.get("callbackUrl"));

What To Do About It

These seven issues account for roughly 80% of the critical and high-severity findings in our dataset. The good news: they're all fixable with straightforward code changes. The bad news: the AI won't fix them for you unless you know to ask — and if you knew to ask, you probably wouldn't have the vulnerability in the first place.

Automated security scanning that understands these patterns is the bridge. Run it before every deployment, catch the predictable mistakes, and spend your manual review time on business logic issues the scanner can't understand.

Your AI-built app might have vulnerabilities

Get a full breach simulation with proof-of-concept exploits — not just a header check.

Run a Vibe Scan

Related Posts

7 Vulns in Every AI-Generated Next.js App | NeuroStrike | NeuroStrike