-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprocess_env_test.go
More file actions
95 lines (85 loc) · 3.64 KB
/
Copy pathprocess_env_test.go
File metadata and controls
95 lines (85 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package main
import (
"slices"
"testing"
)
// The reference daemon's environ contains CLAUDE_SSH_DAEMON_CHILD=1 after the
// self-daemonize re-exec, and that marker is propagated verbatim into every
// process.spawn child (observed in the real spawned agent's /proc/<pid>/environ).
// claustrum sets the same marker (daemonChildMarker) on its re-exec in
// daemonizeWithToken and buildEnv uses os.Environ() as the base, so it must leak
// to children too. Pin that behavior: a regression that swapped buildEnv's base
// for an empty []string or a curated allow-list — or that dropped the marker
// when the internal CLAUSTRUM_DAEMON_CHILD sentinel was split out — would diverge
// silently: no wire frame mentions the marker, but downstream tooling can detect
// the absence by inspecting its own environment.
func TestReplaceOrAppendEnv(t *testing.T) {
// Existing key is replaced in place.
got := replaceOrAppendEnv([]string{"A=1", "B=2"}, "A", "9")
if want := []string{"A=9", "B=2"}; !slices.Equal(got, want) {
t.Errorf("replace: got %v, want %v", got, want)
}
// New key is appended.
got = replaceOrAppendEnv([]string{"A=1"}, "C", "3")
if want := []string{"A=1", "C=3"}; !slices.Equal(got, want) {
t.Errorf("append: got %v, want %v", got, want)
}
// Prefix match must be exact ("A=" not a prefix of "AB=").
got = replaceOrAppendEnv([]string{"AB=2"}, "A", "1")
if want := []string{"AB=2", "A=1"}; !slices.Equal(got, want) {
t.Errorf("prefix safety: got %v, want %v", got, want)
}
}
func TestBuildEnvMergesOverEnviron(t *testing.T) {
t.Setenv("CLAUSTRUM_TEST_KEEP", "base")
t.Setenv("CLAUSTRUM_TEST_OVERRIDE", "old")
env := buildEnv(map[string]string{
"CLAUSTRUM_TEST_OVERRIDE": "new",
"CLAUSTRUM_TEST_ADDED": "added",
})
if !slices.Contains(env, "CLAUSTRUM_TEST_KEEP=base") {
t.Error("inherited environ entry was dropped")
}
if !slices.Contains(env, "CLAUSTRUM_TEST_OVERRIDE=new") {
t.Error("caller override was not applied")
}
if slices.Contains(env, "CLAUSTRUM_TEST_OVERRIDE=old") {
t.Error("stale value survived the override")
}
if !slices.Contains(env, "CLAUSTRUM_TEST_ADDED=added") {
t.Error("new caller key was not appended")
}
}
func TestSpawnInheritsDaemonChildMarker(t *testing.T) {
t.Setenv("CLAUDE_SSH_DAEMON_CHILD", "1")
m := newTestProcManager(t)
t.Cleanup(m.killAll)
c, frames := pipeConn(t)
printenv, env := helperCommand(t, "printenv")
if _, err := m.spawn(c, "envcheck", printenv,
[]string{"CLAUDE_SSH_DAEMON_CHILD"}, "", env); err != nil {
t.Fatalf("spawn: %v", err)
}
if got := firstStdout(t, frames); got != "CLAUDE_SSH_DAEMON_CHILD=1" {
t.Errorf("child saw %q, want %q — daemon re-exec marker must propagate to spawned children for reference parity", got, "CLAUDE_SSH_DAEMON_CHILD=1")
}
}
// The reference binary strips CLAUDE_RPC_TOKEN from the env it passes to
// process.spawn children (probe-verified 2026-06-09 against linux-amd64
// 8de85faa). buildEnv must filter it out even when the daemon's own process
// environment contains it (e.g. when Desktop sets it for the bridge client).
func TestSpawnDoesNotInheritRPCToken(t *testing.T) {
t.Setenv("CLAUDE_RPC_TOKEN", "secret-must-not-leak")
m := newTestProcManager(t)
t.Cleanup(m.killAll)
c, frames := pipeConn(t)
printenv, env := helperCommand(t, "printenv")
if _, err := m.spawn(c, "tokencheck", printenv,
[]string{"CLAUDE_RPC_TOKEN"}, "", env); err != nil {
t.Fatalf("spawn: %v", err)
}
// An empty value means the var was absent; anything else means it leaked.
if got := firstStdout(t, frames); got != "CLAUDE_RPC_TOKEN=" {
t.Errorf("child saw %q, want %q — CLAUDE_RPC_TOKEN must not propagate to spawned children", got, "CLAUDE_RPC_TOKEN=")
}
}