Skip to main content
The first line of defense against bad data, exploits, and bugs.

Three layers

1

Schema validators (Convex)

v.string(), v.number(), v.union(...) — enforced at the database level. Bad shapes are rejected before your handler runs.
2

Business rules (in mutations)

“Email must be lowercase”, “Quantity must be ≥ 1”, “Future date for due-by”. Throw with a clear message.
3

Sanitization (for user-provided HTML / markdown)

Use DOMPurify or a markdown renderer with safe defaults. Don’t render dangerouslySetInnerHTML on raw user input.

In a Convex mutation

Client-side validation

Use react-hook-form + zod for client-side. The same zod schema can be used to validate before submission and to type the form. But: server-side validation is the truth. Client-side is for UX.

Sanitization for rendered content

If users paste HTML or markdown that will be rendered:
For markdown specifically, react-markdown with default plugins is safe — it doesn’t render raw HTML by default.

Convex schema

Validators reference.

Error handling

What to do when validation fails.

XSS / CSRF

Defending against rendered attacks.
Last modified on April 18, 2026