package sandbox import ( "strings" "testing" "github.com/safedep/pmg/sandbox/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) // TestProfileEnvContract pins the env protection contract as a regression // test: npm-restrictive and pypi-restrictive are pure bases that allow // nothing, each package manager's leaf profile re-allows only its own auth // variables (plus the shared config conventions of its ecosystem), and // sibling tokens stay scrubbed alongside other ecosystems' and cloud // credentials. Every probe entry is on the built-in deny list, so anything // not explicitly expected as kept must be scrubbed. This catches accidental // over-broad environment.allow entries. func TestProfileEnvContract(t *testing.T) { r, err := newDefaultProfileRegistry() require.NoError(t, err) env := []string{ "NPM_TOKEN=x", "NODE_AUTH_TOKEN=x", "YARN_NPM_AUTH_TOKEN=x", "BUN_AUTH_TOKEN=x", "TWINE_PASSWORD=x", "UV_PUBLISH_TOKEN=x", "POETRY_PYPI_TOKEN_PYPI=x", "AWS_SECRET_ACCESS_KEY=x", "GOOGLE_APPLICATION_CREDENTIALS=x", "GITHUB_TOKEN=x", "OP_SERVICE_ACCOUNT_TOKEN=x", "CLOUDFLARE_API_TOKEN=x", } tests := []struct { profile string wantKept []string }{ {profile: "npm-restrictive", wantKept: []string{}}, {profile: "pypi-restrictive", wantKept: []string{}}, {profile: "npm", wantKept: []string{"NPM_TOKEN", "NODE_AUTH_TOKEN"}}, {profile: "yarn", wantKept: []string{"NPM_TOKEN", "NODE_AUTH_TOKEN", "YARN_NPM_AUTH_TOKEN"}}, {profile: "bun", wantKept: []string{"NPM_TOKEN", "NODE_AUTH_TOKEN", "BUN_AUTH_TOKEN"}}, {profile: "pnpm", wantKept: []string{"NPM_TOKEN", "NODE_AUTH_TOKEN"}}, {profile: "npx", wantKept: []string{"NPM_TOKEN", "NODE_AUTH_TOKEN"}}, {profile: "pip", wantKept: []string{}}, {profile: "pipx", wantKept: []string{}}, {profile: "uv", wantKept: []string{"UV_PUBLISH_TOKEN"}}, {profile: "uvx", wantKept: []string{"UV_PUBLISH_TOKEN"}}, {profile: "poetry", wantKept: []string{"POETRY_PYPI_TOKEN_PYPI"}}, {profile: "go", wantKept: []string{}}, } for _, tt := range tests { t.Run(tt.profile, func(t *testing.T) { policy, err := r.ResolveProfile(tt.profile, ResolveOptions{}) require.NoError(t, err) result := util.ScrubEnv(env, util.EnvScrubOptions{ Allow: policy.Environment.Allow, Deny: policy.Environment.Deny, }) kept := map[string]bool{} for _, name := range tt.wantKept { kept[name] = true } for _, entry := range env { name, _, _ := strings.Cut(entry, "=") if kept[name] { assert.Contains(t, result.Env, entry, "%s should keep %s", tt.profile, name) } else { assert.Contains(t, result.Removed, name, "%s should scrub %s", tt.profile, name) } } }) } }