From 7724488227d200540a81a7732178e41a4f9fefd4 Mon Sep 17 00:00:00 2001 From: Agent Date: Thu, 2 Apr 2026 20:16:21 +0000 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20fix:=20dispatcher=20cannot=20launch?= =?UTF-8?q?=20runner=20=E2=80=94=20docker=20compose=20context=20not=20avai?= =?UTF-8?q?lable=20in=20edge=20container=20(#153)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/edge/dispatcher.sh | 49 ++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/docker/edge/dispatcher.sh b/docker/edge/dispatcher.sh index 569e307..1c097f5 100755 --- a/docker/edge/dispatcher.sh +++ b/docker/edge/dispatcher.sh @@ -9,7 +9,7 @@ # 3. Verify TOML arrived via merged PR with admin merger (Forgejo API) # 4. Validate TOML using vault-env.sh validator # 5. Decrypt .env.vault.enc and extract only declared secrets -# 6. Launch: docker compose run --rm runner +# 6. Launch: docker run --rm disinto-agents:latest # 7. Write .result.json with exit code, timestamp, logs summary # # Part of #76. @@ -298,10 +298,8 @@ launch_runner() { local secrets_array secrets_array="${VAULT_ACTION_SECRETS:-}" - # Build command array (safe from shell injection) - local -a cmd=(docker compose run --rm runner) - - # Add environment variables for secrets (if any declared) + # Build secret flags from TOML secrets array + local secret_flags="" if [ -n "$secrets_array" ]; then for secret in $secrets_array; do secret=$(echo "$secret" | xargs) @@ -312,42 +310,39 @@ launch_runner() { write_result "$action_id" 1 "Secret not found in vault: ${secret}" return 1 fi - cmd+=(-e "$secret") + secret_flags="${secret_flags} -e ${secret}=${!secret}" fi done else log "Action ${action_id} has no secrets declared — runner will execute without extra env vars" fi - # Add formula and action id as arguments (after service name) - local formula="${VAULT_ACTION_FORMULA:-}" - cmd+=("$formula" "$action_id") + # Build docker run command + # Uses the disinto-agents image (same as agent containers) + # Mounts Docker socket to spawn sibling containers + local docker_cmd="docker run --rm \ + --name \"vault-runner-${action_id}\" \ + --network disinto_disinto-net \ + -e FORGE_URL=\"${FORGE_URL}\" \ + -e FORGE_TOKEN=\"${FORGE_TOKEN}\" \ + -e FORGE_REPO=\"${FORGE_REPO}\" \ + -e FORGE_OPS_REPO=\"${FORGE_OPS_REPO}\" \ + -e PRIMARY_BRANCH=\"${PRIMARY_BRANCH}\" \ + -e DISINTO_CONTAINER=1 \ + ${secret_flags} \ + disinto-agents:latest \ + bash -c \"cd /home/agent/disinto && bash formulas/${VAULT_ACTION_FORMULA}.sh ${action_id}\"" - # Log command skeleton (hide all -e flags for security) - local -a log_cmd=() - local skip_next=0 - for arg in "${cmd[@]}"; do - if [[ $skip_next -eq 1 ]]; then - skip_next=0 - continue - fi - if [[ "$arg" == "-e" ]]; then - log_cmd+=("$arg" "") - skip_next=1 - else - log_cmd+=("$arg") - fi - done - log "Running: ${log_cmd[*]}" + log "Running: docker run (secrets redacted)" # Create temp file for logs local log_file log_file=$(mktemp /tmp/dispatcher-logs-XXXXXX.txt) trap 'rm -f "$log_file"' RETURN - # Execute with array expansion (safe from shell injection) + # Execute docker run command # Capture stdout and stderr to log file - "${cmd[@]}" > "$log_file" 2>&1 + eval "$docker_cmd" > "$log_file" 2>&1 local exit_code=$? # Read logs summary -- 2.49.1 From ff58fcea654cda4601f8729a913d89c24d7fdae1 Mon Sep 17 00:00:00 2001 From: Agent Date: Thu, 2 Apr 2026 20:28:43 +0000 Subject: [PATCH 2/2] fix: use safe array-based docker run command in dispatcher (#153) --- docker/edge/dispatcher.sh | 57 ++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/docker/edge/dispatcher.sh b/docker/edge/dispatcher.sh index 1c097f5..8c6d72e 100755 --- a/docker/edge/dispatcher.sh +++ b/docker/edge/dispatcher.sh @@ -298,8 +298,19 @@ launch_runner() { local secrets_array secrets_array="${VAULT_ACTION_SECRETS:-}" - # Build secret flags from TOML secrets array - local secret_flags="" + # Build command array (safe from shell injection) + local -a cmd=(docker run --rm + --name "vault-runner-${action_id}" + --network disinto_disinto-net + -e "FORGE_URL=${FORGE_URL}" + -e "FORGE_TOKEN=${FORGE_TOKEN}" + -e "FORGE_REPO=${FORGE_REPO}" + -e "FORGE_OPS_REPO=${FORGE_OPS_REPO}" + -e "PRIMARY_BRANCH=${PRIMARY_BRANCH}" + -e DISINTO_CONTAINER=1 + ) + + # Add environment variables for secrets (if any declared) if [ -n "$secrets_array" ]; then for secret in $secrets_array; do secret=$(echo "$secret" | xargs) @@ -310,39 +321,43 @@ launch_runner() { write_result "$action_id" 1 "Secret not found in vault: ${secret}" return 1 fi - secret_flags="${secret_flags} -e ${secret}=${!secret}" + cmd+=(-e "${secret}=${!secret}") fi done else log "Action ${action_id} has no secrets declared — runner will execute without extra env vars" fi - # Build docker run command - # Uses the disinto-agents image (same as agent containers) - # Mounts Docker socket to spawn sibling containers - local docker_cmd="docker run --rm \ - --name \"vault-runner-${action_id}\" \ - --network disinto_disinto-net \ - -e FORGE_URL=\"${FORGE_URL}\" \ - -e FORGE_TOKEN=\"${FORGE_TOKEN}\" \ - -e FORGE_REPO=\"${FORGE_REPO}\" \ - -e FORGE_OPS_REPO=\"${FORGE_OPS_REPO}\" \ - -e PRIMARY_BRANCH=\"${PRIMARY_BRANCH}\" \ - -e DISINTO_CONTAINER=1 \ - ${secret_flags} \ - disinto-agents:latest \ - bash -c \"cd /home/agent/disinto && bash formulas/${VAULT_ACTION_FORMULA}.sh ${action_id}\"" + # Add formula and action id as arguments (safe from shell injection) + local formula="${VAULT_ACTION_FORMULA:-}" + cmd+=(disinto-agents:latest bash -c + "cd /home/agent/disinto && bash formulas/${formula}.sh ${action_id}") - log "Running: docker run (secrets redacted)" + # Log command skeleton (hide all -e flags for security) + local -a log_cmd=() + local skip_next=0 + for arg in "${cmd[@]}"; do + if [[ $skip_next -eq 1 ]]; then + skip_next=0 + continue + fi + if [[ "$arg" == "-e" ]]; then + log_cmd+=("$arg" "") + skip_next=1 + else + log_cmd+=("$arg") + fi + done + log "Running: ${log_cmd[*]}" # Create temp file for logs local log_file log_file=$(mktemp /tmp/dispatcher-logs-XXXXXX.txt) trap 'rm -f "$log_file"' RETURN - # Execute docker run command + # Execute with array expansion (safe from shell injection) # Capture stdout and stderr to log file - eval "$docker_cmd" > "$log_file" 2>&1 + "${cmd[@]}" > "$log_file" 2>&1 local exit_code=$? # Read logs summary -- 2.49.1