Skip to content

Commit a9e74dc

Browse files
committed
Added less broken, more secure test environment variable handling for python-uv-ci.yml
1 parent 30cac0b commit a9e74dc

File tree

1 file changed

+65
-9
lines changed

1 file changed

+65
-9
lines changed

.github/workflows/python-uv-ci.yml

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)