fix(06): CR-01 validate recurrenceUntil as YYYY-MM-DD to close RRULE injection
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -107,8 +107,11 @@ const eventFieldsSchema = z.object({
|
||||
recurrence: z.enum(['none', 'daily', 'weekly', 'monthly', 'yearly']).optional(),
|
||||
calendarUrl: z.string().url().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: validate the exact 'YYYY-MM-DD' shape (reusing eventsQuerySchema's regex) so a
|
||||
// ≤10-char non-date string cannot survive .replace(/-/g,'') and inject extra ';'-delimited
|
||||
// RRULE parts when spliced into the UNTIL template (outboxWorker.assembleRruleString).
|
||||
// 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
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user