Validate and sanitize all request input (body, query params, headers) before processing. Unvalidated input is the root cause of injection attacks, data corruption, and crashes from malformed data.
Why This Matters
Every piece of user input that reaches your server without validation is an attack surface. Unvalidated input enables SQL injection, XSS, command injection, prototype pollution, and denial-of-service through oversized payloads. Even without malicious intent, malformed input causes unhandled exceptions, corrupted database records, and cascading failures. Input validation is the first and most important line of defense.
Every HTTP request is untrusted input — body fields, query parameters, headers, and cookies can all be modified by an attacker. Without validation, your server processes whatever it receives:
A string where a number is expected causes a NaN to propagate through calculations
An object where a string is expected causes [object Object] to be stored in the database
A 50MB JSON body exhausts server memory
A carefully crafted string triggers SQL injection, XSS, or command injection
Input validation is not about being defensive — it is the minimum viable security measure. OWASP consistently ranks injection and improper input validation in the top 10 web application vulnerabilities.
The rule
Validate every piece of input at the boundary — where external data enters your system. Use a schema validation library (Zod, Yup, Joi) to define the expected shape, and reject requests that don't match before any business logic runs.
Bad example
// BAD: no validation — trusts the client completelyexport async function POST(request: Request) { const body = await request.json(); // Directly using unvalidated input const user = await db.user.create({ email: body.email, // Could be anything — number, object, null name: body.name, // Could contain XSS: <script>alert(1)</script> age: body.age, // Could be "DROP TABLE users" role: body.role, // Could be "admin" — privilege escalation! }); return Response.json(user);}
Good example
import { z } from "zod";const CreateUserSchema = z.object({ email: z.string().email().max(255), name: z.string().min(1).max(100).trim(), age: z.number().int().min(0).max(150).optional(), // role is NOT accepted from the client — set server-side});export async function POST(request: Request) { const body = await request.json(); // Validate and parse — throws ZodError if invalid const validated = CreateUserSchema.parse(body); const user = await db.user.create({ email: validated.email, name: validated.name, age: validated.age, role: "user", // Server-controlled — never from client input }); return Response.json(user);}
How to detect
Search for route handlers and server actions that use request body without validation: