fix(06): CR-01 validate recurrenceUntil as YYYY-MM-DD to close RRULE injection

This commit is contained in:
Lucas Berger
2026-06-10 16:51:06 -04:00
parent 924d8e2347
commit d101aa899d
2 changed files with 10 additions and 4 deletions
+5 -2
View File
@@ -79,8 +79,11 @@ const outboxPayloadSchema = z
calendarUrl: z.string().url().max(1024).optional(),
_preservedRrule: z.string().max(1024).optional(),
// D-06: recurrence bounding (RRULE UNTIL / COUNT)
// T-06-02: max(10) bounds 'YYYY-MM-DD'; int().min(1) prevents zero/negative counts
recurrenceUntil: z.string().max(10).optional(), // 'YYYY-MM-DD' → RRULE UNTIL
// CR-01: defense-in-depth — validate the exact 'YYYY-MM-DD' shape here too (the route
// schema validates on ingress, but the outbox payload is re-parsed from stored JSON).
// Guarantees .replace(/-/g,'') in assembleRruleString emits digits-only, closing the
// RRULE-part injection vector. int().min(1) prevents zero/negative counts.
recurrenceUntil: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(), // 'YYYY-MM-DD' → RRULE UNTIL
recurrenceCount: z.number().int().min(1).optional(), // integer ≥ 1 → RRULE COUNT
})
.passthrough()