@@ -161,16 +161,72 @@ jobs:
161161 - name : Test
162162 if : ${{ inputs.run-tests }}
163163 run : |
164- # Parse and export environment variables from JSON
165- # Handle empty or null TEST_SECRETS
166- if [ -z "$TEST_SECRETS" ] || [ "$TEST_SECRETS" = "null" ]; then
167- TEST_SECRETS='{}'
168- fi
164+ # Function to safely process and export environment variables from JSON
165+ process_env_vars() {
166+ local json_data="$1"
167+ local source_name="$2"
168+ local mask_secrets="$3"
169+ local temp_file
170+
171+ if [ -n "$json_data" ] && [ "$json_data" != "null" ] && [ "$json_data" != "{}" ]; then
172+ # Create temporary file to avoid subshell export issues
173+ temp_file=$(mktemp)
174+ trap 'rm -f "$temp_file"' RETURN
175+
176+ # Validate JSON first to prevent jq injection
177+ if ! echo "$json_data" | jq -e . >/dev/null 2>&1; then
178+ echo "Error: Invalid JSON in $source_name"
179+ rm -f "$temp_file"
180+ exit 1
181+ fi
182+
183+ # Process entries and write to temp file
184+ echo "$json_data" | jq -r 'to_entries[] | select(.value != null) | @base64 "\(.key)=\(.value)"' > "$temp_file" || {
185+ echo "Error: Failed to process JSON in $source_name"
186+ rm -f "$temp_file"
187+ exit 1
188+ }
189+
190+ # Read from temp file to avoid subshell issues
191+ local line_num=0
192+ while IFS= read -r line; do
193+ line_num=$((line_num + 1))
194+ if [ -n "$line" ]; then
195+ # Validate base64 input before decoding
196+ if [[ "$line" =~ ^[A-Za-z0-9+/]*=*$ ]]; then
197+ decoded=$(echo "$line" | base64 -d 2>/dev/null)
198+ if [ $? -eq 0 ] && [ -n "$decoded" ]; then
199+ # More robust parsing to prevent injection via key names
200+ if [[ "$decoded" =~ ^([A-Za-z_][A-Za-z0-9_]*)=(.*)$ ]]; then
201+ key="${BASH_REMATCH[1]}"
202+ value="${BASH_REMATCH[2]}"
203+
204+ # Mask secrets in GitHub Actions logs
205+ if [ "$mask_secrets" = "true" ]; then
206+ echo "::add-mask::$value"
207+ fi
208+ export "$key"="$value"
209+ else
210+ echo "Warning: Skipping malformed environment variable at entry $line_num in $source_name"
211+ fi
212+ else
213+ echo "Warning: Failed to decode base64 at entry $line_num in $source_name"
214+ fi
215+ else
216+ echo "Warning: Invalid base64 format at entry $line_num in $source_name"
217+ fi
218+ fi
219+ done < "$temp_file"
220+
221+ rm -f "$temp_file"
222+ fi
223+ }
169224
170- # Use jq to merge JSON objects, with TEST_SECRETS taking precedence
171- echo "$TEST_ENV_VARS $TEST_SECRETS" | jq -s '.[0] * .[1]' | jq -r 'to_entries[] | "export \(.key)=\(.value)"' | while IFS= read -r line; do
172- eval "$line"
173- done
225+ # Process test environment variables first
226+ process_env_vars "$TEST_ENV_VARS" "test-environment-variables" "false"
227+
228+ # Process test secrets (with precedence over env vars, and mask them in logs)
229+ process_env_vars "$TEST_SECRETS" "TEST_SECRETS" "true"
174230
175231 # Run the test script
176232 ${{ inputs.test-script }}
0 commit comments