diff --git a/ssh/tailssh/incubator.go b/ssh/tailssh/incubator.go index f1d61ffe3..70f2582a6 100644 --- a/ssh/tailssh/incubator.go +++ b/ssh/tailssh/incubator.go @@ -220,7 +220,11 @@ func (ss *sshSession) launchProcess() error { cmd := ss.cmd cmd.Dir = ss.conn.localUser.HomeDir cmd.Env = append(cmd.Env, envForUser(ss.conn.localUser)...) - cmd.Env = append(cmd.Env, ss.Environ()...) + for _, kv := range ss.Environ() { + if acceptEnvPair(kv) { + cmd.Env = append(cmd.Env, kv) + } + } ci := ss.conn.info cmd.Env = append(cmd.Env, @@ -493,3 +497,14 @@ func updateStringInSlice(ss []string, a, b string) { } } } + +// acceptEnvPair reports whether the environment variable key=value pair +// should be accepted from the client. It uses the same default as OpenSSH +// AcceptEnv. +func acceptEnvPair(kv string) bool { + k, _, ok := strings.Cut(kv, "=") + if !ok { + return false + } + return k == "TERM" || k == "LANG" || strings.HasPrefix(k, "LC_") +} diff --git a/ssh/tailssh/tailssh_test.go b/ssh/tailssh/tailssh_test.go index b3560430c..f6feb8b18 100644 --- a/ssh/tailssh/tailssh_test.go +++ b/ssh/tailssh/tailssh_test.go @@ -431,3 +431,22 @@ func TestExpandPublicKeyURL(t *testing.T) { t.Errorf("on empty: got %q; want %q", got, want) } } + +func TestAcceptEnvPair(t *testing.T) { + tests := []struct { + in string + want bool + }{ + {"TERM=x", true}, + {"term=x", false}, + {"TERM", false}, + {"LC_FOO=x", true}, + {"LD_PRELOAD=naah", false}, + {"TERM=screen-256color", true}, + } + for _, tt := range tests { + if got := acceptEnvPair(tt.in); got != tt.want { + t.Errorf("for %q, got %v; want %v", tt.in, got, tt.want) + } + } +}