package config import ( "os/user" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func withEuid(t *testing.T, euid int) { t.Helper() orig := configGeteuid configGeteuid = func() int { return euid } t.Cleanup(func() { configGeteuid = orig }) } func poisonUserEnv(t *testing.T) { t.Helper() t.Setenv("PMG_CONFIG_DIR", "") t.Setenv("PMG_CACHE_DIR", "") t.Setenv("HOME", "/home/victim") t.Setenv("XDG_CONFIG_HOME", "/home/victim/.config") t.Setenv("XDG_CACHE_HOME", "/home/victim/.cache") } func TestConfigDirUnderSudoIgnoresPreservedHome(t *testing.T) { poisonUserEnv(t) withEuid(t, 0) t.Setenv("SUDO_USER", "victim") dir, err := configDir() require.NoError(t, err) rootUser, err := user.LookupId("0") require.NoError(t, err) assert.True(t, strings.HasPrefix(dir, rootUser.HomeDir), "expected %s under root home %s", dir, rootUser.HomeDir) assert.NotContains(t, dir, "/home/victim") } func TestConfigDirGenuineRootHonorsEnv(t *testing.T) { // Root without sudo (SUDO_USER unset) is the intended user, e.g. a golden // Docker image that deliberately sets XDG_CONFIG_HOME. It must not divert. poisonUserEnv(t) withEuid(t, 0) t.Setenv("SUDO_USER", "") dir, err := configDir() require.NoError(t, err) assert.Contains(t, dir, "/home/victim") } func TestConfigDirAsNonRootUsesEnvHome(t *testing.T) { poisonUserEnv(t) withEuid(t, 1000) dir, err := configDir() require.NoError(t, err) assert.Contains(t, dir, "/home/victim") } func TestConfigDirEnvOverrideWinsUnderSudo(t *testing.T) { poisonUserEnv(t) t.Setenv("PMG_CONFIG_DIR", "/custom/pmg") withEuid(t, 0) t.Setenv("SUDO_USER", "victim") dir, err := configDir() require.NoError(t, err) assert.Equal(t, "/custom/pmg", dir) } func TestCacheDirUnderSudoIgnoresPreservedHome(t *testing.T) { poisonUserEnv(t) withEuid(t, 0) t.Setenv("SUDO_USER", "victim") dir, err := cacheDir() require.NoError(t, err) rootUser, err := user.LookupId("0") require.NoError(t, err) assert.True(t, strings.HasPrefix(dir, rootUser.HomeDir), "expected %s under root home %s", dir, rootUser.HomeDir) assert.NotContains(t, dir, "/home/victim") } func TestCacheDirGenuineRootHonorsEnv(t *testing.T) { poisonUserEnv(t) withEuid(t, 0) t.Setenv("SUDO_USER", "") dir, err := cacheDir() require.NoError(t, err) assert.Contains(t, dir, "/home/victim") } func TestCacheDirAsNonRootUsesEnvHome(t *testing.T) { poisonUserEnv(t) withEuid(t, 1000) dir, err := cacheDir() require.NoError(t, err) assert.Contains(t, dir, "/home/victim") } func TestRootDirsFallBackToEnvWhenPasswdUnavailable(t *testing.T) { poisonUserEnv(t) withEuid(t, 0) t.Setenv("SUDO_USER", "victim") origConfig, origCache := rootConfigDirResolver, rootCacheDirResolver rootConfigDirResolver = func() (string, error) { return "", assert.AnError } rootCacheDirResolver = func() (string, error) { return "", assert.AnError } t.Cleanup(func() { rootConfigDirResolver, rootCacheDirResolver = origConfig, origCache }) dir, err := configDir() require.NoError(t, err) assert.Contains(t, dir, "/home/victim") dir, err = cacheDir() require.NoError(t, err) assert.Contains(t, dir, "/home/victim") }