mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-04-28 03:49:31 +00:00
fix(security): harden remote command construction in provision.sh (#2886)
* fix(security): harden remote command construction in provision.sh Split the .spawnrc upload fallback into two separate cloud_exec calls to separate data from commands. Step 1 writes the validated base64 payload to a remote temp file. Step 2 decodes from that file and sets up shell rc sourcing using a static command string with no interpolated variables. This eliminates command injection risk in the control-flow portion of the remote command (for loop, grep, etc.) even if the base64 validation were ever bypassed, since user-controlled data never appears in the same command string as shell control flow. Fixes #2882 Agent: complexity-hunter Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: correct error handling + use mktemp for temp file - Return 1 (not 0) when step 1 fails to avoid masking provisioning failures - Use mktemp -t spawnrc.b64 to avoid race conditions on concurrent provisions Agent: pr-maintainer Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: propagate step 2 failure in provision.sh (return 1) The else branch for step 2 (decode + shell rc setup) logged an error but the function still returned 0, masking the failure. Now returns 1 so provisioning failures are correctly propagated. Agent: pr-maintainer Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> --------- Co-authored-by: B <6723574+louisgv@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b0593952df
commit
4d08dbe2a7
1 changed files with 27 additions and 7 deletions
|
|
@ -300,18 +300,38 @@ CLOUD_ENV
|
|||
return 1
|
||||
fi
|
||||
|
||||
# SECURITY: env_b64 is embedded directly in the command string. This is safe
|
||||
# because env_b64 is validated above to contain only [A-Za-z0-9+/=] — the
|
||||
# standard base64 alphabet — which cannot break out of single quotes or
|
||||
# cause shell injection. Piping via stdin is NOT used because Sprite's exec
|
||||
# driver replaces stdin with the command pipe, causing piped data to be lost.
|
||||
# The \$ escapes below are for remote shell variables, not local ones.
|
||||
if cloud_exec "${app_name}" "printf '%s' '${env_b64}' | base64 -d > ~/.spawnrc && chmod 600 ~/.spawnrc && \
|
||||
# SECURITY: Split into two cloud_exec calls to separate data from commands.
|
||||
# Step 1 writes the validated base64 payload to a remote temp file.
|
||||
# Step 2 decodes from that file and sets up .spawnrc + shell rc sourcing.
|
||||
# This avoids embedding variable data in a shell command string that contains
|
||||
# control flow (for loops, conditionals), eliminating command injection risk
|
||||
# even if the base64 validation were ever bypassed.
|
||||
# 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.
|
||||
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
|
||||
if ! cloud_exec "${app_name}" "printf '%s' '${env_b64}' > '${b64_tmp}'" >/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).
|
||||
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
|
||||
log_ok "Manual .spawnrc created successfully"
|
||||
else
|
||||
log_err "Failed to create manual .spawnrc"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue