diff --git a/lib/env.sh b/lib/env.sh index cfaa523..92eb676 100755 --- a/lib/env.sh +++ b/lib/env.sh @@ -29,26 +29,8 @@ if [ -f "$FACTORY_ROOT/.env.enc" ] && command -v sops &>/dev/null; then set -a _saved_forge_url="${FORGE_URL:-}" _saved_forge_token="${FORGE_TOKEN:-}" - # Use temp file + validate dotenv format before sourcing (avoids eval injection) - _tmpenv=$(mktemp) || { echo "Warning: failed to create temp file for .env.enc" >&2; exit 1; } - if sops -d --output-type dotenv "$FACTORY_ROOT/.env.enc" > "$_tmpenv" 2>/dev/null; then - # Validate: non-empty, non-comment lines must match KEY=value pattern - # Filter out blank lines and comments before validation - _validated=$(grep -E '^[A-Za-z_][A-Za-z0-9_]*=' "$_tmpenv" 2>/dev/null || true) - if [ -n "$_validated" ]; then - # Write validated content to a second temp file and source it - _validated_env=$(mktemp) - printf '%s\n' "$_validated" > "$_validated_env" - # shellcheck source=/dev/null - source "$_validated_env" - rm -f "$_validated_env" - else - echo "Warning: .env.enc decryption output failed format validation" >&2 - fi - else - echo "Warning: failed to decrypt .env.enc — secrets not loaded" >&2 - fi - rm -f "$_tmpenv" + eval "$(sops -d --output-type dotenv "$FACTORY_ROOT/.env.enc" 2>/dev/null)" \ + || echo "Warning: failed to decrypt .env.enc — secrets not loaded" >&2 set +a [ -n "$_saved_forge_url" ] && export FORGE_URL="$_saved_forge_url" [ -n "$_saved_forge_token" ] && export FORGE_TOKEN="$_saved_forge_token" diff --git a/lib/issue-lifecycle.sh b/lib/issue-lifecycle.sh index 81586f9..19c422d 100644 --- a/lib/issue-lifecycle.sh +++ b/lib/issue-lifecycle.sh @@ -45,16 +45,16 @@ _ilc_log() { # Label ID caching — lookup once per name, cache in globals. # Pattern follows ci-helpers.sh (ensure_blocked_label_id). # --------------------------------------------------------------------------- -declare -A _ILC_LABEL_IDS -_ILC_LABEL_IDS["backlog"]="" -_ILC_LABEL_IDS["in-progress"]="" -_ILC_LABEL_IDS["blocked"]="" +_ILC_BACKLOG_ID="" +_ILC_IN_PROGRESS_ID="" +_ILC_BLOCKED_ID="" -# _ilc_ensure_label_id LABEL_NAME [COLOR] -# Looks up label by name, creates if missing, caches in associative array. +# _ilc_ensure_label_id VARNAME LABEL_NAME [COLOR] +# Generic: looks up label by name, creates if missing, caches in the named var. _ilc_ensure_label_id() { - local name="$1" color="${2:-#e0e0e0}" - local current="${_ILC_LABEL_IDS[$name]:-}" + local varname="$1" name="$2" color="${3:-#e0e0e0}" + local current + eval "current=\"\${${varname}:-}\"" if [ -n "$current" ]; then printf '%s' "$current" return 0 @@ -71,14 +71,14 @@ _ilc_ensure_label_id() { | jq -r '.id // empty' 2>/dev/null || true) fi if [ -n "$label_id" ]; then - _ILC_LABEL_IDS["$name"]="$label_id" + eval "${varname}=\"${label_id}\"" fi printf '%s' "$label_id" } -_ilc_backlog_id() { _ilc_ensure_label_id "backlog" "#0075ca"; } -_ilc_in_progress_id() { _ilc_ensure_label_id "in-progress" "#1d76db"; } -_ilc_blocked_id() { _ilc_ensure_label_id "blocked" "#e11d48"; } +_ilc_backlog_id() { _ilc_ensure_label_id _ILC_BACKLOG_ID "backlog" "#0075ca"; } +_ilc_in_progress_id() { _ilc_ensure_label_id _ILC_IN_PROGRESS_ID "in-progress" "#1d76db"; } +_ilc_blocked_id() { _ilc_ensure_label_id _ILC_BLOCKED_ID "blocked" "#e11d48"; } # --------------------------------------------------------------------------- # issue_claim — assign issue to bot, add "in-progress" label, remove "backlog". diff --git a/lib/mirrors.sh b/lib/mirrors.sh index 3ba561d..e6dfba1 100644 --- a/lib/mirrors.sh +++ b/lib/mirrors.sh @@ -13,16 +13,7 @@ mirror_push() { local name url for name in $MIRROR_NAMES; do - # Convert name to uppercase env var name safely (only alphanumeric allowed) - local upper_name - upper_name=$(printf '%s' "$name" | tr '[:lower:]' '[:upper:]') - # Validate: only allow alphanumeric + underscore in var name - if [[ ! "$upper_name" =~ ^[A-Z_][A-Z0-9_]*$ ]]; then - continue - fi - # Use indirect expansion safely (no eval) — MIRROR_ prefix required - local varname="MIRROR_${upper_name}" - url="${!varname:-}" + url=$(eval "echo \"\$MIRROR_$(echo "$name" | tr '[:lower:]' '[:upper:]')\"") || true [ -z "$url" ] && continue # Ensure remote exists with correct URL