From c3a4b79e6ee398668484573d3410f034187bbe36 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Sun, 11 Oct 2026 04:33:08 -0400 Subject: [PATCH 1/3] fix: preserve arguments such as --version and -n when running commands over ssh xargs without a command runs /bin/echo per word, which interprets --version, --help, -n, -e and -E as its own options. Use printf with a NUL delimiter instead. Closes #9120 --- dokku | 2 +- tests/unit/core_2.bats | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/dokku b/dokku index 4c3609258..c11550b80 100755 --- a/dokku +++ b/dokku @@ -118,7 +118,7 @@ if [[ -n "$SSH_ORIGINAL_COMMAND" ]]; then exit_code=$? set +f else - readarray -t -O "${#ssh_arg_array[@]}" ssh_arg_array < <(printf '%s' "$SSH_ORIGINAL_COMMAND" | xargs -n 1) + readarray -d '' -O "${#ssh_arg_array[@]}" ssh_arg_array < <(printf '%s' "$SSH_ORIGINAL_COMMAND" | xargs -r printf '%s\0') set -f $0 "${ssh_arg_array[@]}" exit_code=$? diff --git a/tests/unit/core_2.bats b/tests/unit/core_2.bats index a0f7a4591..2efe0e25c 100644 --- a/tests/unit/core_2.bats +++ b/tests/unit/core_2.bats @@ -37,6 +37,14 @@ teardown() { assert_success } +@test "(core) ssh arguments are passed through unchanged" { + run ssh "dokku@$DOKKU_DOMAIN" fakecommand --version --help -n -e -E + echo "output: $output" + echo "status: $status" + assert_failure + assert_output_contains '`fakecommand --version --help -n -e -E` is not a dokku command.' +} + @test "(core) urls (non-ssl)" { assert_urls "http://${TEST_APP}.${DOKKU_DOMAIN}" From 316dafcb9f6f6c23f35fd82c0072472eb142c5b6 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Sun, 11 Oct 2026 04:40:34 -0400 Subject: [PATCH 2/3] tests: add issue #9120 reproduction steps for run over ssh --- tests/unit/run_2.bats | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/unit/run_2.bats b/tests/unit/run_2.bats index 9d07b6075..3b378a551 100644 --- a/tests/unit/run_2.bats +++ b/tests/unit/run_2.bats @@ -30,6 +30,26 @@ teardown() { assert_failure } +@test "(run) run over ssh preserves echo-like arguments" { + run deploy_app + echo "output: $output" + echo "status: $status" + assert_success + + run /bin/bash -c "ssh dokku@$DOKKU_DOMAIN run $TEST_APP /bin/echo --version 2>/dev/null" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "--version" + + # bats strips trailing newlines from $output, so count bytes to verify -n was honored + run /bin/bash -c "ssh dokku@$DOKKU_DOMAIN run $TEST_APP /bin/echo -n hello 2>/dev/null | wc -c" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "5" +} + @test "(run) run:detached" { run deploy_app echo "output: $output" From a7539a54a0fc340eba44c071a0a95473f6e50a46 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Mon, 12 Oct 2026 13:13:31 -0400 Subject: [PATCH 3/3] tests: pass two option words to /bin/echo so GNU echo prints them literally --- tests/unit/run_2.bats | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/run_2.bats b/tests/unit/run_2.bats index 3b378a551..aab7f9168 100644 --- a/tests/unit/run_2.bats +++ b/tests/unit/run_2.bats @@ -36,11 +36,11 @@ teardown() { echo "status: $status" assert_success - run /bin/bash -c "ssh dokku@$DOKKU_DOMAIN run $TEST_APP /bin/echo --version 2>/dev/null" + run /bin/bash -c "ssh dokku@$DOKKU_DOMAIN run $TEST_APP /bin/echo --version --help 2>/dev/null" echo "output: $output" echo "status: $status" assert_success - assert_output "--version" + assert_output "--version --help" # bats strips trailing newlines from $output, so count bytes to verify -n was honored run /bin/bash -c "ssh dokku@$DOKKU_DOMAIN run $TEST_APP /bin/echo -n hello 2>/dev/null | wc -c"