From 3d7b15d6bb8ea8afecf782d356488a17f9d86f2f Mon Sep 17 00:00:00 2001 From: Gmer4Lfe Date: Sat, 4 Jul 2026 23:19:42 -0400 Subject: [PATCH] =?UTF-8?q?Fix=20vv=5Fpush=5Fmaster=5Fconf()=20=E2=80=94?= =?UTF-8?q?=20remote=20command=20was=20expanding=20locally,=20not=20on=20t?= =?UTF-8?q?he=20remote=20host?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The readiness probe wrapped the remote command in raw double quotes with manually backslash-escaped inner quotes. shell_exec() runs its command through an extra local `sh -c` layer beyond the ssh invocation itself, and because the remote command was double-quoted (not single-quoted/opaque), that extra local layer expanded the $(...)/${...} substitutions using HOST1's own environment before ssh ever sent anything to the remote host. Confirmed live: the exact same command run directly (one shell layer) returned the correct remote SCRIPTS_DIR; run through an extra sh -c layer (matching shell_exec's real behavior) it silently evaluated everything against HOST1's local varaverk.cfg instead, producing an empty probe result every time — so every push silently reported "plugin not installed" even though HOST2 was fully installed and reachable. Fix: build the remote command as a plain string and escapeshellarg() it as a whole, same pattern vv_pt_ssh() already used safely elsewhere. Verified live — probe now returns HOST2's real SCRIPTS_DIR and the master.conf push lands with a matching checksum on both hosts. --- Plugin/unraid/include/config.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/Plugin/unraid/include/config.php b/Plugin/unraid/include/config.php index 93a35f9..8ebf9b3 100644 --- a/Plugin/unraid/include/config.php +++ b/Plugin/unraid/include/config.php @@ -110,15 +110,18 @@ function vv_push_master_conf(): array { // Single SSH call: get remote SCRIPTS_DIR and verify plugin is installed, // Configurations/ exists, and master.conf is already present. // Any missing piece means the remote isn't ready — skip rather than push blind. + // Remote command built as one PHP string and escapeshellarg()'d whole — shell_exec() + // adds its own `sh -c` layer locally, so a bare double-quoted string here would let + // the $(...)/${...} substitutions expand on HOST1 before ssh ever sees them, instead + // of on the remote host. escapeshellarg() keeps it opaque until the remote shell runs it. $sshBase = 'ssh -i ' . escapeshellarg($sshKey) . ' -o ConnectTimeout=10 -o StrictHostKeyChecking=no root@' . $ip; - $probe = trim(shell_exec( - $sshBase . ' "cfg=$(grep SCRIPTS_DIR /boot/config/plugins/varaverk/varaverk.cfg 2>/dev/null)' - . ' && sd=$(echo \"$cfg\" | grep -oP \'(?<=SCRIPTS_DIR=\")[^\"]+\')' - . ' && test -d \"${sd}/Configurations\"' - . ' && test -f \"${sd}/Configurations/master.conf\"' - . ' && echo \"$sd\""' - ) ?: ''); + $remoteCmd = 'cfg=$(grep SCRIPTS_DIR /boot/config/plugins/varaverk/varaverk.cfg 2>/dev/null)' + . ' && sd=$(echo "$cfg" | grep -oP \'(?<=SCRIPTS_DIR=")[^"]+\')' + . ' && test -d "${sd}/Configurations"' + . ' && test -f "${sd}/Configurations/master.conf"' + . ' && echo "$sd"'; + $probe = trim(shell_exec($sshBase . ' ' . escapeshellarg($remoteCmd)) ?: ''); if ($probe === '') { $results[] = ['host' => $hostKey, 'ok' => false, 'ready' => false,