mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-05-22 03:14:57 +00:00
fix: secure upload_file functions against command injection in 5 clouds (#453)
Replace unsafe printf '%q'-escaped unquoted variables with validated
single-quoted embedding in upload_file() for fly, northflank, daytona,
e2b, and koyeb. The previous pattern used unquoted $escaped_content and
$escaped_path in command strings passed to bash -c or run_server, which
could allow command injection via crafted filenames.
The fix:
- Validates remote_path rejects unsafe chars (', $, `, newlines)
- Uses base64 content directly (alphanumeric + /+= is shell-safe)
- Single-quotes both content and path in the command string
- Uses printf '%s' instead of echo for safer output
Matches the pattern already used by render, modal, and railway.
Agent: security-auditor
Co-authored-by: A <6723574+louisgv@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
55fd4022e8
commit
f1e8d946df
5 changed files with 49 additions and 34 deletions
|
|
@ -164,15 +164,18 @@ run_server() {
|
|||
upload_file() {
|
||||
local local_path="${1}"
|
||||
local remote_path="${2}"
|
||||
# Upload via base64 encoding through exec (no native CLI file upload)
|
||||
|
||||
# SECURITY: Validate remote_path to prevent command injection via single-quote breakout
|
||||
if [[ "$remote_path" == *"'"* || "$remote_path" == *'$'* || "$remote_path" == *'`'* || "$remote_path" == *$'\n'* ]]; then
|
||||
log_error "Invalid remote path (contains unsafe characters): $remote_path"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# base64 output is safe (alphanumeric + /+=) so no injection risk
|
||||
local content
|
||||
content=$(base64 -w0 "${local_path}" 2>/dev/null || base64 "${local_path}")
|
||||
# SECURITY: Properly escape paths and content
|
||||
local escaped_path
|
||||
escaped_path=$(printf '%q' "${remote_path}")
|
||||
local escaped_content
|
||||
escaped_content=$(printf '%q' "${content}")
|
||||
daytona exec "${DAYTONA_SANDBOX_ID}" -- bash -c "printf '%s' ${escaped_content} | base64 -d > ${escaped_path}"
|
||||
|
||||
daytona exec "${DAYTONA_SANDBOX_ID}" -- bash -c "printf '%s' '${content}' | base64 -d > '${remote_path}'"
|
||||
}
|
||||
|
||||
# Daytona has true SSH support — much better than exec-only providers
|
||||
|
|
|
|||
|
|
@ -115,15 +115,18 @@ run_server() {
|
|||
upload_file() {
|
||||
local local_path="${1}"
|
||||
local remote_path="${2}"
|
||||
# Upload via base64 encoding through exec
|
||||
|
||||
# SECURITY: Validate remote_path to prevent command injection via single-quote breakout
|
||||
if [[ "$remote_path" == *"'"* || "$remote_path" == *'$'* || "$remote_path" == *'`'* || "$remote_path" == *$'\n'* ]]; then
|
||||
log_error "Invalid remote path (contains unsafe characters): $remote_path"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# base64 output is safe (alphanumeric + /+=) so no injection risk
|
||||
local content
|
||||
content=$(base64 -w0 "${local_path}" 2>/dev/null || base64 "${local_path}")
|
||||
# SECURITY: Properly escape the remote path
|
||||
local escaped_path
|
||||
escaped_path=$(printf '%q' "${remote_path}")
|
||||
local escaped_content
|
||||
escaped_content=$(printf '%q' "${content}")
|
||||
e2b sandbox exec "${E2B_SANDBOX_ID}" -- bash -c "echo ${escaped_content} | base64 -d > ${escaped_path}"
|
||||
|
||||
e2b sandbox exec "${E2B_SANDBOX_ID}" -- bash -c "printf '%s' '${content}' | base64 -d > '${remote_path}'"
|
||||
}
|
||||
|
||||
interactive_session() {
|
||||
|
|
|
|||
|
|
@ -311,13 +311,18 @@ run_server() {
|
|||
upload_file() {
|
||||
local local_path="$1"
|
||||
local remote_path="$2"
|
||||
local content=$(base64 -w0 "$local_path" 2>/dev/null || base64 "$local_path")
|
||||
# SECURITY: Properly escape paths and content to prevent injection
|
||||
local escaped_path
|
||||
escaped_path=$(printf '%q' "$remote_path")
|
||||
local escaped_content
|
||||
escaped_content=$(printf '%q' "$content")
|
||||
run_server "echo $escaped_content | base64 -d > $escaped_path"
|
||||
|
||||
# SECURITY: Validate remote_path to prevent command injection via single-quote breakout
|
||||
if [[ "$remote_path" == *"'"* || "$remote_path" == *'$'* || "$remote_path" == *'`'* || "$remote_path" == *$'\n'* ]]; then
|
||||
log_error "Invalid remote path (contains unsafe characters): $remote_path"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# base64 output is safe (alphanumeric + /+=) so no injection risk
|
||||
local content
|
||||
content=$(base64 -w0 "$local_path" 2>/dev/null || base64 "$local_path")
|
||||
|
||||
run_server "printf '%s' '${content}' | base64 -d > '${remote_path}'"
|
||||
}
|
||||
|
||||
# Start an interactive SSH session on the Fly.io machine
|
||||
|
|
|
|||
|
|
@ -222,16 +222,18 @@ upload_file() {
|
|||
return 1
|
||||
fi
|
||||
|
||||
# SECURITY: Validate remote_path to prevent command injection via single-quote breakout
|
||||
if [[ "$remote_path" == *"'"* || "$remote_path" == *'$'* || "$remote_path" == *'`'* || "$remote_path" == *$'\n'* ]]; then
|
||||
log_error "Invalid remote path (contains unsafe characters): $remote_path"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# SECURITY: base64 -w0 produces single-line output (no newline injection)
|
||||
# base64 output is safe (alphanumeric + /+=) so no injection risk
|
||||
local content
|
||||
content=$(base64 -w0 "$local_path" 2>/dev/null || base64 "$local_path")
|
||||
|
||||
# SECURITY: Properly escape remote_path to prevent injection
|
||||
local escaped_path
|
||||
escaped_path=$(printf '%q' "$remote_path")
|
||||
|
||||
# base64 output is safe (alphanumeric + /+=) so no injection risk
|
||||
run_server "printf '%s' '$content' | base64 -d > $escaped_path"
|
||||
run_server "printf '%s' '${content}' | base64 -d > '${remote_path}'"
|
||||
}
|
||||
|
||||
# Wait for cloud-init or basic system readiness
|
||||
|
|
|
|||
|
|
@ -166,16 +166,18 @@ run_server() {
|
|||
upload_file() {
|
||||
local local_path="${1}"
|
||||
local remote_path="${2}"
|
||||
|
||||
# SECURITY: Validate remote_path to prevent command injection via single-quote breakout
|
||||
if [[ "$remote_path" == *"'"* || "$remote_path" == *'$'* || "$remote_path" == *'`'* || "$remote_path" == *$'\n'* ]]; then
|
||||
log_error "Invalid remote path (contains unsafe characters): $remote_path"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# base64 output is safe (alphanumeric + /+=) so no injection risk
|
||||
local content
|
||||
content=$(base64 -w0 "${local_path}" 2>/dev/null || base64 "${local_path}")
|
||||
|
||||
# SECURITY: Properly escape paths and content to prevent injection
|
||||
local escaped_path
|
||||
escaped_path=$(printf '%q' "${remote_path}")
|
||||
local escaped_content
|
||||
escaped_content=$(printf '%q' "${content}")
|
||||
|
||||
run_server "echo ${escaped_content} | base64 -d > ${escaped_path}"
|
||||
run_server "printf '%s' '${content}' | base64 -d > '${remote_path}'"
|
||||
}
|
||||
|
||||
# Start an interactive shell session on the Northflank service
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue