mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
Path resolution trusted HOME (and XDG_*), which sudo and su can preserve from the invoking user (GitHub runners, sudo -E, su without -). Any pmg run as root then created root-owned ~/.config/safedep inside that user's home, and event-log init fail-closed every later non-root pmg/npm/pip run for them. System install made sudo pmg the documented flow, turning this latent bug into the happy path. When euid is 0, configDir and cacheDir now resolve from root's passwd home instead of the environment, so root state lands under /root and user homes are never touched. PMG_CONFIG_DIR/PMG_CACHE_DIR still win, non-root resolution is unchanged, and Windows is unaffected (no euid). Event-log init stays fatal on failure; sudo-run package events are attributed via SUDO_USER and synced by the exit auto-sync as usual. E2E: GitHub runners preserve HOME under sudo, so assert that no sudo pmg run leaks state into the runner's home, and that the managed-config refusal fails for the documented reason rather than a permission brick.
81 lines
1.8 KiB
Go
81 lines
1.8 KiB
Go
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 TestConfigDirAsRootIgnoresPreservedHome(t *testing.T) {
|
|
poisonUserEnv(t)
|
|
withEuid(t, 0)
|
|
|
|
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 TestConfigDirAsNonRootUsesEnvHome(t *testing.T) {
|
|
poisonUserEnv(t)
|
|
withEuid(t, 1000)
|
|
|
|
dir, err := configDir()
|
|
require.NoError(t, err)
|
|
assert.Contains(t, dir, "/home/victim")
|
|
}
|
|
|
|
func TestConfigDirEnvOverrideWinsForRoot(t *testing.T) {
|
|
poisonUserEnv(t)
|
|
t.Setenv("PMG_CONFIG_DIR", "/custom/pmg")
|
|
withEuid(t, 0)
|
|
|
|
dir, err := configDir()
|
|
require.NoError(t, err)
|
|
assert.Equal(t, "/custom/pmg", dir)
|
|
}
|
|
|
|
func TestCacheDirAsRootIgnoresPreservedHome(t *testing.T) {
|
|
poisonUserEnv(t)
|
|
withEuid(t, 0)
|
|
|
|
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 TestCacheDirAsNonRootUsesEnvHome(t *testing.T) {
|
|
poisonUserEnv(t)
|
|
withEuid(t, 1000)
|
|
|
|
dir, err := cacheDir()
|
|
require.NoError(t, err)
|
|
assert.Contains(t, dir, "/home/victim")
|
|
}
|