v0.0.21 4dde650

sandbox_test.go RawHistoryFolder

1package tools
2
3import (
4	"context"
5	"os"
6	"path/filepath"
7	"testing"
8)
9
10func TestSandboxLockedBlocksOutside(t *testing.T) {
11	root := t.TempDir()
12	outside := t.TempDir()
13	outsideFile := filepath.Join(outside, "a.txt")
14	os.WriteFile(outsideFile, []byte("secret"), 0o644)
15
16	sb := NewSandbox(root)
17	sb.Lock()
18
19	if err := sb.CheckPath(outsideFile); err == nil {
20		t.Fatal("expected outside path to be blocked")
21	}
22	inside := filepath.Join(root, "ok.txt")
23	if err := sb.CheckPath(inside); err != nil {
24		t.Fatalf("inside path blocked unexpectedly: %v", err)
25	}
26}
27
28func TestSandboxUnlockedAllows(t *testing.T) {
29	root := t.TempDir()
30	outside := t.TempDir()
31	sb := NewSandbox(root)
32	if err := sb.CheckPath(filepath.Join(outside, "a.txt")); err != nil {
33		t.Fatalf("unlocked should allow: %v", err)
34	}
35}
36
37func TestSandboxCommandBanned(t *testing.T) {
38	sb := NewSandbox(t.TempDir())
39	sb.Lock()
40	cases := []string{
41		"sudo apt-get install foo",
42		"rm -rf /",
43		"cd /etc && ls",
44		"cd .. && rm foo",
45	}
46	for _, c := range cases {
47		if err := sb.CheckCommand(c); err == nil {
48			t.Fatalf("expected %q to be banned", c)
49		}
50	}
51	// Allowed:
52	for _, c := range []string{"ls", "go test ./...", "cd subdir && ls"} {
53		if err := sb.CheckCommand(c); err != nil {
54			t.Fatalf("expected %q to be allowed: %v", c, err)
55		}
56	}
57}
58
59func TestReadToolRejectsOutsideWhenLocked(t *testing.T) {
60	root := t.TempDir()
61	outside := t.TempDir()
62	outsideFile := filepath.Join(outside, "a.txt")
63	os.WriteFile(outsideFile, []byte("x"), 0o644)
64
65	sb := NewSandbox(root)
66	sb.Lock()
67	tool := &ReadTool{CWD: root, Sandbox: sb}
68
69	_, err := tool.Execute(context.Background(),
70		mustJSONRaw(t, map[string]any{"path": outsideFile}), nil)
71	if err == nil {
72		t.Fatal("expected sandbox error")
73	}
74}
75
76func mustJSONRaw(t *testing.T, v any) []byte {
77	t.Helper()
78	return mustJSON(t, v)
79}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 476

↑↓ moveenter openesc close