From e2d6aa144468b20a71fe87dc3bb0650bd478d630 Mon Sep 17 00:00:00 2001 From: A <258483684+la14-1@users.noreply.github.com> Date: Thu, 19 Feb 2026 08:23:27 -0800 Subject: [PATCH] fix: use json_escape in save_vm_connection to prevent malformed JSON (#1470) save_vm_connection built JSON via direct string interpolation, which produces malformed output if any value contains quotes, backslashes, or other JSON-special characters. This breaks spawn list/delete/history. Changes: - Use json_escape for all string fields in save_vm_connection - Use json_escape for GCP zone/project metadata values - Switch AWS, GCP, Daytona get_server_name to get_validated_server_name for consistency with Hetzner, DigitalOcean, Fly, OVH Agent: code-health Co-authored-by: B <6723574+louisgv@users.noreply.github.com> Co-authored-by: Claude Sonnet 4.6 --- aws/lib/common.sh | 2 +- daytona/lib/common.sh | 2 +- gcp/lib/common.sh | 7 +++++-- shared/common.sh | 10 +++++----- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/aws/lib/common.sh b/aws/lib/common.sh index ab079408..97e27d56 100644 --- a/aws/lib/common.sh +++ b/aws/lib/common.sh @@ -130,7 +130,7 @@ ensure_ssh_key() { } get_server_name() { - get_resource_name "LIGHTSAIL_SERVER_NAME" "Enter Lightsail instance name: " + get_validated_server_name "LIGHTSAIL_SERVER_NAME" "Enter Lightsail instance name: " } get_cloud_init_userdata() { diff --git a/daytona/lib/common.sh b/daytona/lib/common.sh index b6e12762..7f83778f 100644 --- a/daytona/lib/common.sh +++ b/daytona/lib/common.sh @@ -139,7 +139,7 @@ ensure_daytona_token() { } get_server_name() { - get_resource_name "DAYTONA_SANDBOX_NAME" "Enter sandbox name: " + get_validated_server_name "DAYTONA_SANDBOX_NAME" "Enter sandbox name: " } _is_snapshot_conflict() { diff --git a/gcp/lib/common.sh b/gcp/lib/common.sh index d8393ae0..79f368ce 100644 --- a/gcp/lib/common.sh +++ b/gcp/lib/common.sh @@ -238,7 +238,7 @@ ensure_ssh_key() { } get_server_name() { - get_resource_name "GCP_INSTANCE_NAME" "Enter instance name: " + get_validated_server_name "GCP_INSTANCE_NAME" "Enter instance name: " } get_cloud_init_userdata() { @@ -379,7 +379,10 @@ create_server() { log_info "Instance created: IP=${GCP_SERVER_IP}" - save_vm_connection "${GCP_SERVER_IP}" "${SSH_USER:-$(whoami)}" "" "$name" "gcp" "{\"zone\":\"${zone}\",\"project\":\"${GCP_PROJECT}\"}" + local _zone_escaped _project_escaped + _zone_escaped=$(json_escape "${zone}") + _project_escaped=$(json_escape "${GCP_PROJECT}") + save_vm_connection "${GCP_SERVER_IP}" "${SSH_USER:-$(whoami)}" "" "$name" "gcp" "{\"zone\":${_zone_escaped},\"project\":${_project_escaped}}" } verify_server_connectivity() { ssh_verify_connectivity "$@"; } diff --git a/shared/common.sh b/shared/common.sh index 5f261526..78e9e301 100644 --- a/shared/common.sh +++ b/shared/common.sh @@ -3582,16 +3582,16 @@ save_vm_connection() { local conn_file="${spawn_dir}/last-connection.json" - # Build JSON (handle optional fields) - local json="{\"ip\":\"${ip}\",\"user\":\"${user}\"" + # Build JSON using json_escape to prevent injection via special characters + local json="{\"ip\":$(json_escape "${ip}"),\"user\":$(json_escape "${user}")" if [[ -n "${server_id}" ]]; then - json="${json},\"server_id\":\"${server_id}\"" + json="${json},\"server_id\":$(json_escape "${server_id}")" fi if [[ -n "${server_name}" ]]; then - json="${json},\"server_name\":\"${server_name}\"" + json="${json},\"server_name\":$(json_escape "${server_name}")" fi if [[ -n "${cloud}" ]]; then - json="${json},\"cloud\":\"${cloud}\"" + json="${json},\"cloud\":$(json_escape "${cloud}")" fi if [[ -n "${metadata}" ]]; then json="${json},\"metadata\":${metadata}"