From de48dad9673e2ef6df73082115e54dc56b9541d8 Mon Sep 17 00:00:00 2001 From: S Date: Mon, 2 Mar 2026 08:52:25 -0500 Subject: [PATCH] fix: enhance .env loading to safely parse key-value pairs and handle special characters --- lib/common.sh | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/lib/common.sh b/lib/common.sh index 4b89a43..209e62d 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -80,10 +80,31 @@ load_env() { log_error "Copy .env.example to .env and populate values." return 1 fi - set -a # auto-export all vars defined below - # shellcheck source=/dev/null - source "$env_file" - set +a # stop auto-exporting + # Parse KEY=VALUE lines safely without executing them as bash. + # Using 'source' on .env is dangerous: unquoted values with spaces + # (e.g. GITEA_INSTANCE_NAME=PID Git) cause the second word to be + # executed as a command. This parser handles comments, blank lines, + # and values with spaces, quotes, and special characters. + local line key value + while IFS= read -r line || [[ -n "$line" ]]; do + # Skip blank lines and comments + [[ -z "$line" || "$line" == \#* ]] && continue + # Must contain = to be a valid assignment + [[ "$line" == *=* ]] || continue + key="${line%%=*}" + value="${line#*=}" + # Strip inline comments: remove everything from '# ' onward (hash + space). + # The space after # distinguishes comments from # in URLs/passwords/tokens. + # Handles both 'value # comment' and 'value# comment' formats. + value="${value%%# *}" + # Strip surrounding quotes (single or double) if present + if [[ "$value" =~ ^\"(.*)\"$ ]] || [[ "$value" =~ ^\'(.*)\'$ ]]; then + value="${BASH_REMATCH[1]}" + fi + # Strip trailing whitespace + value="${value%"${value##*[! ]}"}" + export "$key=$value" + done < "$env_file" } save_env_var() { @@ -430,7 +451,7 @@ ssh_exec() { # ConnectTimeout: fail fast if host is unreachable (don't hang for 60s) # StrictHostKeyChecking=accept-new: auto-accept new hosts but reject changed keys # BatchMode=yes: never prompt for password (fail if key auth doesn't work) - # ${key:+-i "$key"}: pass -i only when SSH_KEY is set (otherwise use ssh-agent default) + # ${key:+-i "$key"}: pass -i only when SSH_KEY is set (otherwise SSH uses default keys from ~/.ssh/id_*) ssh ${key:+-i "$key"} \ -o ConnectTimeout=10 \ -o StrictHostKeyChecking=accept-new \