@@ -356,11 +356,12 @@ validate_config_value() {
356356process_volume_config () {
357357 local value=" $1 "
358358 local errors_var=" $2 "
359+ declare -n errors_ref=" $errors_var "
359360
360361 value=" ${value// \" / } "
361362
362363 if ! validate_config_value " VOLUME" " $value " ; then
363- eval " $errors_var +=(\ " Invalid volume: \ $ value\" ) "
364+ errors_ref +=(" Invalid volume: $value " )
364365 return 1
365366 fi
366367
@@ -372,18 +373,19 @@ process_volume_config() {
372373 EXTRA_VOLUMES+=(" -v" " $value " )
373374 DOCKER_ONLY_WARNINGS+=(" Config volume mount: $value (ignored in local mode)" )
374375 else
375- eval " $errors_var +=(\ " Volume validation failed: \ $ value\" ) "
376+ errors_ref +=(" Volume validation failed: $value " )
376377 fi
377378}
378379
379380process_env_config () {
380381 local value=" $1 "
381382 local errors_var=" $2 "
383+ declare -n errors_ref=" $errors_var "
382384
383385 value=" ${value// \" / } "
384386
385387 if ! validate_config_value " ENV" " $value " ; then
386- eval " $errors_var +=(\ " Invalid env: \ $ value\" ) "
388+ errors_ref +=(" Invalid env: $value " )
387389 return 1
388390 fi
389391
@@ -394,8 +396,7 @@ process_env_config() {
394396 EXTRA_ENV_VARS+=(" -e" " $name =$val " )
395397 DOCKER_ONLY_WARNINGS+=(" Config environment variable: $name =$val (ignored in local mode)" )
396398 else
397- eval " $errors_var +=(\" Invalid env name: \$ name\" )"
398- fi
399+ errors_ref+=(" Invalid env name: $name " )
399400 else
400401 # Shorthand pass-through: ENV=${VAR} or ENV=$VAR
401402 if [[ " $value " =~ ^\$\{ ([A-Za-z_][A-Za-z0-9_]* )\} $ ]] || [[ " $value " =~ ^\$ ([A-Za-z_][A-Za-z0-9_]* )$ ]]; then
@@ -417,16 +418,17 @@ process_var_config() {
417418 local name=" $1 "
418419 local value=" $2 "
419420 local errors_var=" $3 "
421+ declare -n errors_ref=" $errors_var "
420422
421423 if ! [[ " $name " =~ ^[A-Z][A-Z0-9_]* $ ]]; then
422- eval " $errors_var +=(\ " Invalid variable name: \ $ name\" ) "
424+ errors_ref +=(" Invalid variable name: $name " )
423425 return 1
424426 fi
425427
426428 value=" ${value// \" / } "
427429
428430 if ! validate_config_value " $name " " $value " ; then
429- eval " $errors_var +=(\ " Validation failed for \ $ name=\ $ value\" ) "
431+ errors_ref +=(" Validation failed for $name =$value " )
430432 return 1
431433 fi
432434
@@ -439,14 +441,14 @@ process_var_config() {
439441 CONFIG_DIR=" $value "
440442 if [ ! -d " $CONFIG_DIR " ]; then
441443 mkdir -p " $CONFIG_DIR " 2> /dev/null || {
442- eval " $errors_var +=(\ " Cannot create CONFIG_DIR: \ $ CONFIG_DIR\" ) "
444+ errors_ref +=(" Cannot create CONFIG_DIR: $CONFIG_DIR " )
443445 CONFIG_DIR=" "
444446 return 1
445447 }
446448 fi
447449 if [ -n " $CONFIG_DIR " ] && [ ! -f " $CONFIG_DIR /.claude.json" ]; then
448450 echo ' {}' > " $CONFIG_DIR /.claude.json" 2> /dev/null || {
449- eval " $errors_var +=(\ " Cannot create \ $ CONFIG_DIR/.claude.json\" ) "
451+ errors_ref +=(" Cannot create $CONFIG_DIR /.claude.json" )
450452 }
451453 fi
452454 ;;
@@ -479,7 +481,7 @@ process_var_config() {
479481 if [[ " $name " =~ ^(DISABLE_| MAX_| ANTHROPIC_| CLAUDE_| AWS_| GOOGLE_) ]]; then
480482 export " $name " =" $value "
481483 else
482- eval " $errors_var +=(\ " Unknown config variable: \ $ name\" ) "
484+ errors_ref +=(" Unknown config variable: $name " )
483485 fi
484486 ;;
485487 esac
@@ -489,6 +491,11 @@ load_config_file() {
489491 local config_file=" $1 "
490492 [ -f " $config_file " ] || return 1
491493
494+ # Note: There's a potential TOCTOU race condition here where the config file
495+ # could be modified between validation and loading. For a fully atomic solution,
496+ # we would need to read the file once into memory and process from there.
497+ # However, given the nature of config files (user-controlled, local),
498+ # the security impact is minimal and the current approach is pragmatic.
492499 local errors=()
493500
494501 while IFS= read -r line || [ -n " $line " ]; do
0 commit comments