Security [MEDIUM]: Systematic Zod .max() audit — 202 unbounded z.string() sites
#51
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
Grep finds 200+
z.string()without.max()across 59 router files. Arrays and records similarly unbounded in many places. Amplifies DoS surface via DB queries, JSON parsing, and regex scans. No lint rule prevents new unbounded inputs.Evidence
packages/api/src/router/resource-mutations.ts:391 — batchHardDelete ids no .max()packages/api/src/router/import-export-procedure-support.ts:17 — rows array unboundedapps/web/src/app/api/reports/allocations/route.ts:26-27 — date params unvalidatedpackages/api/src/router/audit-log-inputs.ts:3-14 — search/filter strings unboundedpackages/api/src/router/user-procedure-support.ts:11 — name no .max() (but Update caps at 200)packages/api/src/router/timeline-read-schema-support.ts:6-23 — 12 filter arrays unboundedpackages/api/src/router/resource-skill-import.ts:7-122 — entries + portfolioUrl unboundedpackages/api/src/router/staffing-suggestions-read.ts:411-412 — requiredSkills unboundedpackages/api/src/router/notification-procedure-base.ts:217-259 — date without year boundspackages/api/src/router/webhook-support.ts:10,18 — secret no min/maxapps/web/src/app/api/sse/timeline/route.ts:59-96 — no per-user SSE connection capapps/web/src/app/api/trpc/[trpc]/route.ts:1-89 — no request-size limitImpact
Distributed DoS surface. Individual findings are LOW each, but sum is MEDIUM-HIGH. Any authenticated user can amplify a request by 1000× via unbounded arrays/strings.
Proposed Fix
(1) Write a coding standard in
docs/zod-conventions.md:z.string()defaults to.max(500), arrays default.max(100), records need explicit schema. (2) Add ESLint rule (custom) flaggingz.string(),z.array(...),z.record(...)without.max/.min. (3) Batch-PR fixing the 12 listed call-sites above. (4) Add per-user SSE connection cap (8). (5) Configure Next.js body-size limit globally.Acceptance Criteria
Parent Epic: #1
Source: Full-Codebase Security Audit 2026-04-16 (B-4, B-5, B-6, B-10, B-13, B-16, B-17, B-18, B-19, B-20, B-21, B-22, H1)