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/notification-procedure-base.ts:217-259 — date without year bounds
packages/api/src/router/webhook-support.ts:10,18 — secret no min/max
apps/web/src/app/api/sse/timeline/route.ts:59-96 — no per-user SSE connection cap
apps/web/src/app/api/trpc/[trpc]/route.ts:1-89 — no request-size limit
Impact
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) flagging z.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.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
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)