返回 DeepSeek-Reasonix
serve_scrollback_test.go
根目录 / internal / cli / serve_scrollback_test.go
1 package cli
2
3 import (
4 "os"
5 "os/exec"
6 "path/filepath"
7 "runtime"
8 "strings"
9 "testing"
10 "time"
11
12 "reasonix/internal/boot"
13 "reasonix/internal/config"
14 "reasonix/internal/control"
15 "reasonix/internal/sandbox"
16 "reasonix/internal/serve"
17 )
18
19 // The line serve prints goes into a tmux pane, and a sandboxed command (network
20 // on, the default) reads the pane and the named file back without the token.
21 func TestSandboxCannotReadServeTokenFromScrollback(t *testing.T) {
22 if runtime.GOOS == "windows" || !sandbox.Available() {
23 t.Skip("no sandbox")
24 }
25 tmux, err := exec.LookPath("tmux")
26 if err != nil {
27 t.Skip("no tmux")
28 }
29 t.Setenv("REASONIX_HOME", t.TempDir())
30 for _, mode := range []string{"none", "token"} {
31 ctrl := newOwnedTestController(t, control.Options{SessionDir: t.TempDir()})
32 srv := serve.New(ctrl, serve.NewBroadcaster(), config.ServeConfig{AuthMode: mode})
33 res := &serveFrontendResources{}
34 opts := serveFrontendOptions{command: "serve"}
35 if opts.launchTokenPath, err = launchTokenLocation(srv.AuthToken(), opts, res); err != nil {
36 t.Fatal(err)
37 }
38 var b strings.Builder
39 reportServeAuth(&b, srv, "127.0.0.1:8787", opts)
40 line := filepath.Join(t.TempDir(), "line.txt")
41 _ = os.WriteFile(line, []byte(b.String()), 0o600)
42 sock := "rv83jp" + mode
43 if out, err := exec.Command(tmux, "-L", sock, "new-session", "-d", "-x", "400", "-s", "s", "cat "+line+"; sleep 20").CombinedOutput(); err != nil {
44 t.Fatalf("tmux: %v %s", err, out)
45 }
46 time.Sleep(400 * time.Millisecond)
47 work := t.TempDir()
48 spec := sandbox.Spec{Mode: "enforce", WriteRoots: []string{work}, ForbidReadRoots: boot.RuntimeForbidReadRoots(config.Default(), work), Network: true}
49 cmd := tmux + " -L " + sock + " capture-pane -p -J -t s"
50 if opts.launchTokenPath != "" {
51 cmd += "; echo ---; cat " + opts.launchTokenPath
52 }
53 argv, _ := sandbox.Command(spec, sandbox.Shell{Kind: sandbox.ShellBash, Path: "bash"}, cmd)
54 out, _ := exec.Command(argv[0], argv[1:]...).CombinedOutput()
55 _ = exec.Command(tmux, "-L", sock, "kill-server").Run()
56 res.release(false)
57 ctrl.Close()
58 if strings.Contains(string(out), srv.AuthToken()) {
59 t.Errorf("mode=%s: sandboxed command recovered the launch token", mode)
60 }
61 }
62 }
63
63 lines GO