fix(exec): 沙箱子进程不再继承宿主完整环境(P0-7,审计 §4.3)
- buildEnv 不再以 os.Environ() 全集为基,改为「平台最小必需键白名单」裁剪后再叠加 req.Env · Windows:PATH/PATHEXT/SYSTEMROOT/WINDIR/COMSPEC/TEMP/TMP/USERPROFILE/HOMEDRIVE/HOMEPATH/APPDATA/LOCALAPPDATA/NUMBER_OF_PROCESSORS/OS/PROCESSOR_ARCHITECTURE · Unix:PATH/HOME/TMPDIR/LANG/LC_ALL/USER/SHELL - 键名匹配在 Windows 上大小写不敏感(避免宿主写 Path 时漏掉),overlay 覆盖 base 时同口径去重 - envAllowed 语义不变:调用方能显式放行的键照旧,仅改变 base 来源 - 新增 TestTerminal_Env_HostNotInherited(非并行,t.Setenv):父进程设非白名单变量,断言子进程读不到;反证=把该键加进白名单立刻 FAIL
This commit is contained in:
1 parent
09ee561aa7
commit
ed5bd92e1b
2 files changed
+130
-23
No files matched your search
@@ -296,6 +296,52 @@ func TestTerminal_Env_Whitelist(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestTerminal_Env_HostNotInherited 验证子进程不再继承宿主环境变量全集:宿主里
|
||||
// 任意非白名单变量(如真实的 API key)都不会泄漏给沙箱命令;同时运行终端所必需的
|
||||
// 基础键(PATH)仍在,否则命令无法启动。
|
||||
// 注意:t.Setenv 与 t.Parallel 互斥,本用例不得并行。
|
||||
func TestTerminal_Env_HostNotInherited(t *testing.T) {
|
||||
requireBin(t, "env")
|
||||
|
||||
const (
|
||||
secretName = "CYRENE_TEST_SECRET_XYZ"
|
||||
secretValue = "s3cr3t-do-not-leak"
|
||||
)
|
||||
t.Setenv(secretName, secretValue)
|
||||
|
||||
ex := newEnabledExecutor(t, enabledCfg("env", t.TempDir()))
|
||||
res, err := ex.Execute(context.Background(), ExecRequest{Command: []string{"env"}})
|
||||
if err != nil {
|
||||
t.Fatalf("Execute: %v", err)
|
||||
}
|
||||
if res.ExitCode != 0 {
|
||||
t.Fatalf("ExitCode = %d, want 0; stderr=%q", res.ExitCode, res.Stderr)
|
||||
}
|
||||
|
||||
if got := childEnvValue(res.Stdout, secretName); got != "" {
|
||||
t.Errorf("子进程读到了非白名单宿主变量 %s=%q,宿主全集仍被透传", secretName, got)
|
||||
}
|
||||
if got := childEnvValue(res.Stdout, "PATH"); got == "" {
|
||||
t.Errorf("子进程 PATH 为空,终端命令将无法解析可执行文件;stdout=%q", res.Stdout)
|
||||
}
|
||||
}
|
||||
|
||||
// childEnvValue 从 `env` 命令的输出里取 key 的值,未找到返回空串。键名比较走平台
|
||||
// 口径(Windows 大小写不敏感),避免把宿主的 `Path` 拼写误判成缺失。
|
||||
func childEnvValue(stdout, key string) string {
|
||||
for _, line := range strings.Split(stdout, "\n") {
|
||||
line = strings.TrimRight(line, "\r")
|
||||
k, v, ok := strings.Cut(line, "=")
|
||||
if !ok || k == "" {
|
||||
continue
|
||||
}
|
||||
if envKeyEqual(k, key) {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func TestTerminal_EmptyCommand(t *testing.T) {
|
||||
t.Parallel()
|
||||
ex := newEnabledExecutor(t, enabledCfg("echo", t.TempDir()))
|
||||
|
||||
Reference in new issue
Block a user