-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add clean environment option to Shell #21
Description
Problem
When using tkInfra.NewShell with the Username field to run commands as a different user, the parent process's environment leaks into the child process. This happens because prepareExec() inherits the parent env via execCmd.Environ() (line 140 of shell.go):
execCmd.Env = append(execCmd.Environ(), "DEBIAN_FRONTEND=noninteractive")
execCmd.Env = slices.Concat(execCmd.Env, shell.runtimeSettings.Envs)When the parent runs as root (HOME=/root) and we pass HOME=/home/username in Envs, both entries exist in the env slice. Since getenv() returns the first match, the parent's HOME=/root takes precedence — the appended value is never seen.
This breaks rootless podman (and likely other user-scoped tools) because they resolve config paths from HOME:
faccessat /root/.config/containers/storage.conf: permission denied
Proposed Solution
Add a ShouldUseCleanEnv boolean to ShellSettings. When set to true, skip the execCmd.Environ() inheritance and build execCmd.Env solely from ShellSettings.Envs (plus the automatic DEBIAN_FRONTEND=noninteractive):
if shell.runtimeSettings.ShouldUseCleanEnv {
execCmd.Env = []string{"DEBIAN_FRONTEND=noninteractive"}
} else {
execCmd.Env = append(execCmd.Environ(), "DEBIAN_FRONTEND=noninteractive")
}
execCmd.Env = slices.Concat(execCmd.Env, shell.runtimeSettings.Envs)This is backward-compatible — the default (false) preserves the current behavior.
Context
Discovered while migrating EZ's RunCmdAsUser to use tkInfra.NewShell. The function runs commands as a different system user and needs a clean environment with explicit HOME, XDG_RUNTIME_DIR, DBUS_SESSION_BUS_ADDRESS, etc. Without a clean-env option, we can't use tk Shell for this use case.