diff --git a/sh/e2e/lib/provision.sh b/sh/e2e/lib/provision.sh index 39553fdc..cba1760a 100644 --- a/sh/e2e/lib/provision.sh +++ b/sh/e2e/lib/provision.sh @@ -324,24 +324,35 @@ CLOUD_ENV # Piping via stdin is NOT used because Sprite's exec driver replaces stdin # with the command pipe, causing piped data to be lost. - # Step 1: Create a temp file and write base64 data to it on the remote host. - # env_b64 is validated above to contain only [A-Za-z0-9+/=] (base64 alphabet), - # which cannot break out of single quotes or cause shell injection. - # The remote command re-validates the data as defense-in-depth. + # Step 1: Create a temp file on the remote host for the base64 payload. local b64_tmp b64_tmp=$(cloud_exec "${app_name}" "mktemp -t spawnrc.b64.XXXXXX" 2>/dev/null | tr -d '[:space:]') if [ -z "${b64_tmp}" ]; then log_err "Failed to create remote temp file for .spawnrc payload" return 1 fi - # Assign to remote variable and re-validate base64 on remote side before writing. - if ! cloud_exec "${app_name}" "_B64='${env_b64}'; printf '%s' \"\$_B64\" | grep -qE '^[A-Za-z0-9+/=]+$' && printf '%s' \"\$_B64\" > '${b64_tmp}' || exit 1" >/dev/null 2>&1; then + + # Validate b64_tmp contains only safe path characters (defense-in-depth). + # A compromised remote could return a crafted mktemp path with shell + # metacharacters that would be interpolated into subsequent cloud_exec calls. + if ! printf '%s' "${b64_tmp}" | grep -qE '^[A-Za-z0-9_./ -]+$'; then + log_err "SECURITY: Remote mktemp returned suspicious path — aborting" + return 1 + fi + + # Write env_b64 to the remote temp file. Defense-in-depth: escape any single + # quotes in env_b64 before interpolation (base64 cannot contain them, but this + # prevents injection if the validation above is ever bypassed or weakened). + # The remote command also re-validates the data before writing. + local env_b64_escaped + env_b64_escaped=$(printf '%s' "${env_b64}" | sed "s/'/'\\\\''/g") + if ! cloud_exec "${app_name}" "_B64='${env_b64_escaped}'; printf '%s' \"\$_B64\" | grep -qE '^[A-Za-z0-9+/=]+\$' && printf '%s' \"\$_B64\" > '${b64_tmp}' || exit 1" >/dev/null 2>&1; then log_err "Failed to write .spawnrc payload to remote temp file" return 1 fi # Step 2: Decode from the temp file and set up shell rc sourcing. - # The only interpolated variable is b64_tmp (a mktemp path, safe characters only). + # b64_tmp is validated above to contain only safe path characters. if cloud_exec "${app_name}" "base64 -d < '${b64_tmp}' > ~/.spawnrc && chmod 600 ~/.spawnrc && rm -f '${b64_tmp}' && \ for _rc in ~/.bashrc ~/.profile ~/.bash_profile; do \ grep -q 'source ~/.spawnrc' \"\$_rc\" 2>/dev/null || printf '%s\n' '[ -f ~/.spawnrc ] && source ~/.spawnrc' >> \"\$_rc\"; done" >/dev/null 2>&1; then