mirror of
https://github.com/OpenRouterTeam/spawn.git
synced 2026-05-22 03:14:57 +00:00
fix: json_escape SSH key names and fix GCP metadata injection (#958)
SSH key registration in 11 cloud providers used unescaped key_name directly in JSON request bodies. If the hostname (used to generate key names) contained JSON-special characters like double-quotes, it could break out of the JSON string and inject arbitrary JSON fields. Fix: use json_escape for key_name in all providers, matching the pattern already used by Scaleway. Also fix GCP create_server which embedded the startup script inline in --metadata with comma delimiters. Commas in the script could break metadata parsing or inject additional metadata keys. Fix: use --metadata-from-file for the startup script. Affected providers: Hetzner, DigitalOcean, Vultr, BinaryLane, Hostinger, Contabo, Cherry, HOSTKEY, Civo, Linode, Genesis Cloud, GCP. Agent: security-auditor Co-authored-by: A <6723574+louisgv@users.noreply.github.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
fd80f1992c
commit
3c3c697ea5
12 changed files with 44 additions and 26 deletions
|
|
@ -72,9 +72,10 @@ binarylane_register_ssh_key() {
|
|||
local pub_path="$2"
|
||||
local pub_key
|
||||
pub_key=$(cat "$pub_path")
|
||||
local json_pub_key
|
||||
local json_pub_key json_name
|
||||
json_pub_key=$(json_escape "$pub_key")
|
||||
local register_body="{\"name\":\"$key_name\",\"public_key\":$json_pub_key}"
|
||||
json_name=$(json_escape "$key_name")
|
||||
local register_body="{\"name\":$json_name,\"public_key\":$json_pub_key}"
|
||||
local register_response
|
||||
register_response=$(binarylane_api POST "/account/keys" "$register_body")
|
||||
|
||||
|
|
|
|||
|
|
@ -87,9 +87,10 @@ cherry_register_ssh_key() {
|
|||
local pub_path="$2"
|
||||
local pub_key
|
||||
pub_key=$(cat "$pub_path")
|
||||
local json_pub_key
|
||||
local json_pub_key json_name
|
||||
json_pub_key=$(json_escape "$pub_key")
|
||||
local register_body="{\"label\":\"$key_name\",\"key\":$json_pub_key}"
|
||||
json_name=$(json_escape "$key_name")
|
||||
local register_body="{\"label\":$json_name,\"key\":$json_pub_key}"
|
||||
local register_response
|
||||
register_response=$(cherry_api POST "/ssh-keys" "$register_body")
|
||||
|
||||
|
|
|
|||
|
|
@ -64,9 +64,10 @@ civo_register_ssh_key() {
|
|||
local pub_path="$2"
|
||||
local pub_key
|
||||
pub_key=$(cat "$pub_path")
|
||||
local json_pub_key
|
||||
local json_pub_key json_name
|
||||
json_pub_key=$(json_escape "$pub_key")
|
||||
local register_body="{\"name\":\"$key_name\",\"public_key\":$json_pub_key}"
|
||||
json_name=$(json_escape "$key_name")
|
||||
local register_body="{\"name\":$json_name,\"public_key\":$json_pub_key}"
|
||||
local register_response
|
||||
register_response=$(civo_api POST "/sshkeys" "$register_body")
|
||||
|
||||
|
|
|
|||
|
|
@ -111,9 +111,10 @@ contabo_register_ssh_key() {
|
|||
local pub_path="$2"
|
||||
local pub_key
|
||||
pub_key=$(cat "$pub_path")
|
||||
local json_pub_key
|
||||
local json_pub_key json_name
|
||||
json_pub_key=$(json_escape "$pub_key")
|
||||
local register_body="{\"name\":\"$key_name\",\"type\":\"ssh\",\"value\":$json_pub_key}"
|
||||
json_name=$(json_escape "$key_name")
|
||||
local register_body="{\"name\":$json_name,\"type\":\"ssh\",\"value\":$json_pub_key}"
|
||||
local register_response
|
||||
register_response=$(contabo_api POST "/compute/secrets" "$register_body")
|
||||
|
||||
|
|
|
|||
|
|
@ -74,9 +74,10 @@ do_register_ssh_key() {
|
|||
local pub_path="$2"
|
||||
local pub_key
|
||||
pub_key=$(cat "$pub_path")
|
||||
local json_pub_key
|
||||
local json_pub_key json_name
|
||||
json_pub_key=$(json_escape "$pub_key")
|
||||
local register_body="{\"name\":\"$key_name\",\"public_key\":$json_pub_key}"
|
||||
json_name=$(json_escape "$key_name")
|
||||
local register_body="{\"name\":$json_name,\"public_key\":$json_pub_key}"
|
||||
local register_response
|
||||
register_response=$(do_api POST "/account/keys" "$register_body")
|
||||
|
||||
|
|
|
|||
|
|
@ -108,11 +108,15 @@ create_server() {
|
|||
|
||||
log_step "Creating GCP instance '${name}' (type: ${machine_type}, zone: ${zone})..."
|
||||
|
||||
local userdata
|
||||
userdata=$(get_cloud_init_userdata)
|
||||
local pub_key
|
||||
pub_key=$(cat "${HOME}/.ssh/id_ed25519.pub")
|
||||
|
||||
# Write startup script to a temp file to avoid --metadata comma delimiter issues
|
||||
local startup_script_file
|
||||
startup_script_file=$(mktemp)
|
||||
track_temp_file "${startup_script_file}"
|
||||
get_cloud_init_userdata > "${startup_script_file}"
|
||||
|
||||
local gcloud_err
|
||||
gcloud_err=$(mktemp)
|
||||
track_temp_file "${gcloud_err}"
|
||||
|
|
@ -122,7 +126,8 @@ create_server() {
|
|||
--machine-type="${machine_type}" \
|
||||
--image-family="${image_family}" \
|
||||
--image-project="${image_project}" \
|
||||
--metadata="startup-script=${userdata},ssh-keys=${GCP_USERNAME}:${pub_key}" \
|
||||
--metadata-from-file="startup-script=${startup_script_file}" \
|
||||
--metadata="ssh-keys=${GCP_USERNAME}:${pub_key}" \
|
||||
--project="${GCP_PROJECT}" \
|
||||
--quiet \
|
||||
>/dev/null 2>"${gcloud_err}"; then
|
||||
|
|
|
|||
|
|
@ -72,9 +72,10 @@ genesis_register_ssh_key() {
|
|||
local pub_path="$2"
|
||||
local pub_key
|
||||
pub_key=$(cat "$pub_path")
|
||||
local json_pub_key
|
||||
local json_pub_key json_name
|
||||
json_pub_key=$(json_escape "$pub_key")
|
||||
local register_body="{\"name\":\"$key_name\",\"value\":$json_pub_key}"
|
||||
json_name=$(json_escape "$key_name")
|
||||
local register_body="{\"name\":$json_name,\"value\":$json_pub_key}"
|
||||
local register_response
|
||||
register_response=$(genesis_api POST "/ssh-keys" "$register_body")
|
||||
|
||||
|
|
|
|||
|
|
@ -68,9 +68,10 @@ hetzner_register_ssh_key() {
|
|||
local pub_path="$2"
|
||||
local pub_key
|
||||
pub_key=$(cat "$pub_path")
|
||||
local json_pub_key
|
||||
local json_pub_key json_name
|
||||
json_pub_key=$(json_escape "$pub_key")
|
||||
local register_body="{\"name\":\"$key_name\",\"public_key\":$json_pub_key}"
|
||||
json_name=$(json_escape "$key_name")
|
||||
local register_body="{\"name\":$json_name,\"public_key\":$json_pub_key}"
|
||||
local register_response
|
||||
register_response=$(hetzner_api POST "/ssh_keys" "$register_body")
|
||||
|
||||
|
|
|
|||
|
|
@ -74,9 +74,10 @@ hostinger_register_ssh_key() {
|
|||
local pub_path="$2"
|
||||
local pub_key
|
||||
pub_key=$(cat "$pub_path")
|
||||
local json_pub_key
|
||||
local json_pub_key json_name
|
||||
json_pub_key=$(json_escape "$pub_key")
|
||||
local register_body="{\"name\":\"$key_name\",\"public_key\":$json_pub_key}"
|
||||
json_name=$(json_escape "$key_name")
|
||||
local register_body="{\"name\":$json_name,\"public_key\":$json_pub_key}"
|
||||
local register_response
|
||||
register_response=$(hostinger_api POST "/ssh-keys" "$register_body")
|
||||
|
||||
|
|
|
|||
|
|
@ -79,10 +79,11 @@ hostkey_register_ssh_key() {
|
|||
local pub_path="$2"
|
||||
local pub_key
|
||||
pub_key=$(cat "$pub_path")
|
||||
local json_pub_key
|
||||
local json_pub_key json_name
|
||||
json_pub_key=$(json_escape "$pub_key")
|
||||
json_name=$(json_escape "$key_name")
|
||||
|
||||
local register_body="{\"name\":\"$key_name\",\"public_key\":$json_pub_key}"
|
||||
local register_body="{\"name\":$json_name,\"public_key\":$json_pub_key}"
|
||||
local register_response
|
||||
register_response=$(hostkey_api POST "/ssh_keys" "$register_body")
|
||||
|
||||
|
|
@ -243,7 +244,9 @@ destroy_server() {
|
|||
|
||||
log_step "Destroying instance $instance_id..."
|
||||
local response
|
||||
response=$(hostkey_api POST "/eq/terminate" "{\"id\":\"$instance_id\"}")
|
||||
local json_id
|
||||
json_id=$(json_escape "$instance_id")
|
||||
response=$(hostkey_api POST "/eq/terminate" "{\"id\":$json_id}")
|
||||
|
||||
if echo "$response" | grep -qi "error"; then
|
||||
log_error "Failed to destroy instance: $response"
|
||||
|
|
|
|||
|
|
@ -71,9 +71,10 @@ linode_register_ssh_key() {
|
|||
local pub_path="$2"
|
||||
local pub_key
|
||||
pub_key=$(cat "$pub_path")
|
||||
local json_pub_key
|
||||
local json_pub_key json_name
|
||||
json_pub_key=$(json_escape "$pub_key")
|
||||
local register_body="{\"label\":\"$key_name\",\"ssh_key\":$json_pub_key}"
|
||||
json_name=$(json_escape "$key_name")
|
||||
local register_body="{\"label\":$json_name,\"ssh_key\":$json_pub_key}"
|
||||
local register_response
|
||||
register_response=$(linode_api POST "/profile/sshkeys" "$register_body")
|
||||
|
||||
|
|
|
|||
|
|
@ -71,9 +71,10 @@ vultr_register_ssh_key() {
|
|||
local pub_path="$2"
|
||||
local pub_key
|
||||
pub_key=$(cat "$pub_path")
|
||||
local json_pub_key
|
||||
local json_pub_key json_name
|
||||
json_pub_key=$(json_escape "$pub_key")
|
||||
local register_body="{\"name\":\"$key_name\",\"ssh_key\":$json_pub_key}"
|
||||
json_name=$(json_escape "$key_name")
|
||||
local register_body="{\"name\":$json_name,\"ssh_key\":$json_pub_key}"
|
||||
local register_response
|
||||
register_response=$(vultr_api POST "/ssh-keys" "$register_body")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue