@@ -96,32 +96,49 @@ const roundToClosestPowerOf2 = (num: number): number | undefined => {
9696} ;
9797
9898/**
99- * Replaces `{{variable}}` placeholders in an expression string with `runOptions.variable`.
100- *
101- * This function also validates that the variable is one of the allowed 'runOptions' keys.
99+ * Replaces `{{variable}}` placeholders in an expression string with the variable name.
100+ * Enforces strict validation to only allow `input.*` paths or whitelisted `runOptions.*` keys.
102101 *
103102 * @example
104103 * // Returns "runOptions.memoryMbytes + 1024"
105- * preprocessDefaultMemoryExpression("{{memoryMbytes}} + 1024");
104+ * preprocessDefaultMemoryExpression("{{runOptions. memoryMbytes}} + 1024");
106105 *
107- * @param defaultMemoryMbytes The raw string expression, e.g., "{{memoryMbytes}} * 2".
106+ * @param defaultMemoryMbytes The raw string expression, e.g., "{{runOptions. memoryMbytes}} * 2".
108107 * @returns A safe, processed expression for evaluation, e.g., "runOptions.memoryMbytes * 2".
109108 */
110109const preprocessDefaultMemoryExpression = ( defaultMemoryMbytes : string ) : string => {
111- // This regex captures the variable name inside {{...}}
112- const variableRegex = / { { \s * ( [ a - z A - Z 0 - 9 _ ] + ) \s * } } / g;
110+ const variableRegex = / { { \s * ( [ a - z A - Z 0 - 9 _ . ] + ) \s * } } / g;
113111
114112 const processedExpression = defaultMemoryMbytes . replace (
115113 variableRegex ,
116114 ( _ , variableName : string ) => {
117- // Check if the captured variable name is in our allowlist
118- if ( ! ALLOWED_RUN_OPTION_KEYS . has ( variableName as keyof ActorRunOptions ) ) {
115+ // 1. Validate that the variable starts with either 'input.' or 'runOptions.'
116+ if ( ! variableName . startsWith ( 'runOptions.' ) && ! variableName . startsWith ( 'input.' ) ) {
119117 throw new Error (
120- `Invalid variable '{{${ variableName } }}' in expression.` ,
118+ `Invalid variable '{{${ variableName } }}' in expression. Variables must start with 'input.' or 'runOptions.'. ` ,
121119 ) ;
122120 }
123121
124- return `runOptions.${ variableName } ` ;
122+ // 2. Check if the variable is accessing Input (e.g. {{input.someValue}})
123+ // We do not validate the specific property name because input is dynamic.
124+ if ( variableName . startsWith ( 'input.' ) ) {
125+ return variableName ;
126+ }
127+
128+ if ( variableName . startsWith ( 'runOptions.' ) ) {
129+ const key = variableName . slice ( 'runOptions.' . length ) ;
130+ if ( ! ALLOWED_RUN_OPTION_KEYS . has ( key as keyof ActorRunOptions ) ) {
131+ throw new Error (
132+ `Invalid variable '{{${ variableName } }}' in expression. Only the following runOptions are allowed: ${ Array . from ( ALLOWED_RUN_OPTION_KEYS ) . map ( ( k ) => `runOptions.${ k } ` ) . join ( ', ' ) } .` ,
133+ ) ;
134+ }
135+ return variableName ;
136+ }
137+
138+ // 3. Throw error for unrecognized variables (e.g. {{process.env}})
139+ throw new Error (
140+ `Invalid variable '{{${ variableName } }}' in expression.` ,
141+ ) ;
125142 } ,
126143 ) ;
127144
0 commit comments