permissions_test.go RawHistoryFolder
1package tools
2
3import (
4 "path/filepath"
5 "strings"
6 "testing"
7)
8
9func TestPermissionSetEmptyScopesDenyAccess(t *testing.T) {
10 s := NewSandbox(t.TempDir())
11 s.SetPermissions(&PermissionSet{})
12 if err := s.CheckReadPath(filepath.Join(s.Root, "a")); err == nil {
13 t.Fatal("empty read scope allowed access")
14 }
15 if err := s.CheckWritePath(filepath.Join(s.Root, "a")); err == nil {
16 t.Fatal("empty write scope allowed access")
17 }
18}
19
20func TestPermissionSetScopedAccess(t *testing.T) {
21 root := t.TempDir()
22 var p PermissionSet
23 p.FS.Read = []string{"${workspace}/src"}
24 p.FS.Write = []string{"${agent_data}"}
25 expanded := p.Expand(root, filepath.Join(root, "data"))
26 s := NewSandbox(root)
27 s.SetPermissions(&expanded)
28 if err := s.CheckReadPath(filepath.Join(root, "src", "a.go")); err != nil {
29 t.Fatalf("read inside scope: %v", err)
30 }
31 if err := s.CheckReadPath(filepath.Join(root, "secret")); err == nil {
32 t.Fatal("read outside scope was allowed")
33 }
34 if err := s.CheckWritePath(filepath.Join(root, "data", "state.json")); err != nil {
35 t.Fatalf("write inside scope: %v", err)
36 }
37}
38
39func TestPermissionExpandDoesNotMutateManifest(t *testing.T) {
40 var p PermissionSet
41 p.FS.Read = []string{"${workspace}"}
42 _ = p.Expand("/first", "/data")
43 if got := p.FS.Read[0]; got != "${workspace}" {
44 t.Fatalf("manifest mutated to %q", got)
45 }
46}
47
48func TestBashAllowlistRejectsShellEscapes(t *testing.T) {
49 var p PermissionSet
50 p.Bash.Mode = "allowlist"
51 p.Bash.Allow = []string{"echo"}
52 s := NewSandbox(t.TempDir())
53 s.SetPermissions(&p)
54 for _, cmd := range []string{"echo $(uname)", "echo hi > /tmp/out", "echo `uname`", "echo ok\nrm -rf /"} {
55 if err := s.CheckBashPermission(cmd); err == nil || !strings.Contains(err.Error(), "does not permit") {
56 t.Errorf("command %q was not rejected: %v", cmd, err)
57 }
58 }
59 if err := s.CheckBashPermission("echo ok"); err != nil {
60 t.Fatalf("allowed command rejected: %v", err)
61 }
62 if err := s.CheckBashPermission("rm file"); err == nil {
63 t.Fatal("unlisted command was allowed")
64 }
65}
66
67func TestBashModeNoneDenies(t *testing.T) {
68 var p PermissionSet
69 p.Bash.Mode = "none"
70 s := NewSandbox(t.TempDir())
71 s.SetPermissions(&p)
72 if err := s.CheckBashPermission("echo ok"); err == nil {
73 t.Fatal("none mode allowed bash")
74 }
75}
76
77func TestBashModeAskAllows(t *testing.T) {
78 var p PermissionSet
79 p.Bash.Mode = "ask"
80 s := NewSandbox(t.TempDir())
81 s.SetPermissions(&p)
82 if err := s.CheckBashPermission("rm -rf /tmp/x"); err != nil {
83 t.Fatalf("ask mode rejected command: %v", err)
84 }
85}