@@ -5,6 +5,11 @@ import { log } from '../logger';
55import { ParsedConfig } from './read' ;
66import { PROP_TO_ENV } from './read/env' ;
77import { checkOutput , COMPRESS_TYPES } from '../compress' ;
8+ import ms , { StringValue } from 'ms' ;
9+
10+ // Maximum safe timeout value for JavaScript timers (32-bit signed integer limit)
11+ // Approximately 24.8 days
12+ const MAX_SAFE_TIMEOUT_MS = 2147483647 ;
813
914declare global {
1015 // eslint-disable-next-line @typescript-eslint/no-namespace
@@ -17,6 +22,23 @@ declare global {
1722 }
1823}
1924
25+ // Helper function to validate interval strings
26+ function validateInterval ( value : string ) : boolean {
27+ const intervalMs = ms ( value as StringValue ) ;
28+ // ms() returns undefined for invalid strings, not throw
29+ if ( typeof intervalMs !== 'number' ) {
30+ return false ;
31+ }
32+ return intervalMs <= MAX_SAFE_TIMEOUT_MS ;
33+ }
34+
35+ // Reusable interval schema with validation
36+ const intervalSchema = ( defaultValue : string ) =>
37+ z
38+ . string ( )
39+ . default ( defaultValue )
40+ . refine ( validateInterval , 'Interval exceeds maximum safe timeout of ~24 days (2147483647ms)' ) ;
41+
2042export const discordContent = z
2143 . object ( {
2244 webhookUrl : z . url ( ) . nullable ( ) . default ( null ) ,
@@ -104,12 +126,12 @@ export const schema = z.object({
104126 enabled : z . boolean ( ) . default ( true ) ,
105127 } ) ,
106128 tasks : z . object ( {
107- deleteInterval : z . string ( ) . default ( '30min' ) ,
108- clearInvitesInterval : z . string ( ) . default ( '30min' ) ,
109- maxViewsInterval : z . string ( ) . default ( '30min' ) ,
110- thumbnailsInterval : z . string ( ) . default ( '30min' ) ,
111- metricsInterval : z . string ( ) . default ( '30min' ) ,
112- cleanThumbnailsInterval : z . string ( ) . default ( '1d' ) ,
129+ deleteInterval : intervalSchema ( '30min' ) ,
130+ clearInvitesInterval : intervalSchema ( '30min' ) ,
131+ maxViewsInterval : intervalSchema ( '30min' ) ,
132+ thumbnailsInterval : intervalSchema ( '30min' ) ,
133+ metricsInterval : intervalSchema ( '30min' ) ,
134+ cleanThumbnailsInterval : intervalSchema ( '1d' ) ,
113135 } ) ,
114136 files : z . object ( {
115137 route : z . string ( ) . startsWith ( '/' ) . min ( 1 ) . trim ( ) . toLowerCase ( ) . default ( '/u' ) ,
0 commit comments