HighSecurityAuto-fixable

Missing Input Validation on API Route

A POST or PATCH route spreads the raw request body into a database write without checking that fields exist, have the right types, or are in range.

Typical error

Request body accepted without schema check

What this is

A generated API route that looks like:

export async function POST(req: Request) {
  const body = await req.json()
  const user = await db.user.create({ data: body })
  return Response.json(user)
}

Nothing stops the caller from including extra fields like isAdmin: true, role: 'owner', or credits: 999999. The database happily writes them.

Why AI tools ship this

"Spread the body" is the shortest code path that makes the endpoint work on the happy path. Validation is extra work the AI skips by default.

How to detect

Look for req.json() or await request.body being passed directly to db.*.create, db.*.update, or similar without any validation in between.

How to fix

Use Zod (or valibot) to define a schema for every API endpoint. Accept only what you declared.

import { z } from 'zod'
 
const CreateUserInput = z.object({
  email: z.string().email(),
  displayName: z.string().min(1).max(100),
})
 
export async function POST(req: Request) {
  const result = CreateUserInput.safeParse(await req.json())
  if (!result.success) {
    return new Response(
      JSON.stringify({ error: result.error.flatten() }),
      { status: 400 }
    )
  }
 
  const user = await db.user.create({
    data: {
      email: result.data.email,
      displayName: result.data.displayName,
      // explicit fields only, no spread
    },
  })
 
  return Response.json(user)
}

Never pattern data: { ...body }. Always name every column you are writing.

Commonly affected tools

Glossary

Is your app affected?

FinishKit checks for this finding and 50+ more across 8 dimensions of production readiness. Free during beta.

Scan your app