loom-data-validation
Installation
SKILL.md
Data Validation
Overview
Validate untrusted data at trust boundaries before it flows into your system. This skill covers schema libraries (Zod/Pydantic/Joi/JSON Schema), coercion pitfalls, context-dependent output encoding, injection/XSS/DoS defenses, and pipeline/ML feature validation.
Core principles (read first)
- Parse, don't validate. A validator that returns
boolthrows away work — the caller re-parses or trusts blindly. Return a typed value (Result<User>,User | errors) so downstream code cannot receive unvalidated data. Schema libraries (Zod.parse, Pydantic.model_validate) do this by construction. - Validate at the boundary, once, then trust the typed value inward. Boundaries: HTTP handlers, queue consumers, file/CLI parsers, pipeline ingestion, cross-service calls.
- Server-side is authoritative; client-side validation is UX only. Never rely on it for security — attackers bypass the client entirely.
- Allowlist > denylist. Enumerate what's permitted (
enum, char classes, known hosts). Denylists (blocking<script>,../,') are always incomplete — encodings, Unicode, and case defeat them. - Canonicalize before validating. Normalize Unicode (NFC), lowercase host, resolve
./..in paths, decode percent-encoding — then check. Validating raw input lets%2e%2e%2for.(fullwidth) slip past. - Encoding ≠ validation. Validation decides accept/reject; encoding makes a value safe for a specific sink (HTML vs attribute vs JS vs URL vs shell vs SQL). A value can be valid and still need encoding at every sink.
- Limits are validation. Cap length, array size, object depth, and total payload bytes to stop DoS (JSON bombs, deeply nested payloads, ReDoS amplification).
Zod (TypeScript)
safeParse returns a discriminated result (no throw); parse throws ZodError. Prefer safeParse at boundaries.