advanced

Input validation, output encoding, and file upload security

Validate untrusted input at boundaries, encode output for its context, and isolate uploads with type checks, size limits, scanning, and private storage.

Validate at trust boundaries: HTTP body, query, headers, webhooks, and file uploads. Use schema validators (Zod, Joi, TypeBox) and reject unknown fields — fail closed.

					import { z } from 'zod';

const CreateUser = z.object({
  email: z.string().email().max(320),
  name: z.string().min(1).max(120),
}).strict();

const input = CreateUser.parse(req.body);
				

Output encoding matches context — HTML, attribute, URL, JavaScript string. Validation does not replace encoding on output.

File uploads: enforce size limits, allowlist MIME via magic bytes (not extension alone), store outside web root, generate random object keys, scan with antivirus/async pipeline, serve via signed URLs not direct paths.

On interviews: allowlist vs blocklist validation; why `multipart` needs streaming limits in Node; path traversal in archive uploads.

Common pitfalls: trusting `Content-Type` from client; serving uploads from `/public`; SVG uploads with embedded script.

The trade-off is balancing simplicity, performance, safety, and operability — name which axis you optimized and what cost you accepted.

Checklist:

  • Schema validation on every external input.
  • Encode on output per sink context.
  • Private storage + signed download URLs.
  • Stream uploads with backpressure and size caps.