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.
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.
BeforeMerge scans your pull requests against this rule and 4+ others. Get actionable feedback before code ships.
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:
NaN to propagate through calculations[object Object] to be stored in the databaseInput 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.
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: no validation — trusts the client completely
export 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);
}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);
}Search for route handlers and server actions that use request body without validation:
grep -n "request.json()\|req.body" --include="*.ts" --include="*.tsx" -r app/api/Check if the parsed body goes through a schema validator before being used.