From ac62380c0df00d98f3ddb39b38e141437450379d Mon Sep 17 00:00:00 2001 From: xuans Date: Wed, 30 Sep 2026 16:48:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DSSH=E8=84=9A=E6=9C=AC?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E5=8F=82=E6=95=B0=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/deployment/ssh.go | 4 ++-- backend/internal/deployment/ssh_test.go | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/backend/internal/deployment/ssh.go b/backend/internal/deployment/ssh.go index c602eb7..69bc560 100644 --- a/backend/internal/deployment/ssh.go +++ b/backend/internal/deployment/ssh.go @@ -420,8 +420,8 @@ func (c *sshClientAdapter) Close() error { } func validateCommand(command []string) error { - for _, token := range command { - if strings.TrimSpace(token) == "" || strings.ContainsAny(token, "\x00\r\n") { + for index, token := range command { + if strings.TrimSpace(token) == "" || strings.ContainsRune(token, '\x00') || (strings.ContainsAny(token, "\r\n") && !(len(command) == 3 && index == 2 && command[0] == "sh" && command[1] == "-c")) { return errors.New("远程命令参数无效") } } diff --git a/backend/internal/deployment/ssh_test.go b/backend/internal/deployment/ssh_test.go index 8151b9d..194197c 100644 --- a/backend/internal/deployment/ssh_test.go +++ b/backend/internal/deployment/ssh_test.go @@ -59,6 +59,13 @@ func TestValidateCommandRejectsShellControlLines(t *testing.T) { } } +func TestValidateCommandAllowsShellScriptArgument(t *testing.T) { + command := []string{"sh", "-c", "set -eu\nprintf '%s\\n' 'ok'"} + if err := validateCommand(command); err != nil { + t.Fatalf("shell script argument should be accepted: %v", err) + } +} + func TestJoinShellArgsQuotesArguments(t *testing.T) { command := []string{"nginx", "-c", "/etc/nginx/my config.conf", "reload'check"} joined := joinShellArgs(command)