Download
60 lines 1.9 KiBGoModified 2026-10-31 raw
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
package policy

import "testing"

func TestToolRules(t *testing.T) {
	names := []string{"Commit", "Define", "Fetch", "Usage"}
	layer := func(name, text string) Layer {
		t.Helper()
		f, err := Parse([]byte(text))
		if err != nil {
			t.Fatal(err)
		}
		return Layer{name, f}
	}
	// What the safe policy allows runs without asking; what only the
	// unsafe one allows asks; the last matching rule wins in each.
	safe := layer("safe policy", "tool allow Usage\n")
	unsafe := layer("unsafe policy", "tool allow *\ntool deny Commit\n")
	access, err := ToolAccess(safe, unsafe, names)
	if err != nil {
		t.Fatal(err)
	}
	if access[3] != Allow || access[1] != Ask || access[0] != Deny {
		t.Errorf("access %v", access)
	}
	empty := layer("empty", "")
	if access, _ := ToolAccess(empty, empty, names); access[0] != Deny {
		t.Error("a tool no rule allows is not denied")
	}
	if _, err := ToolAccess(empty, layer("unsafe policy", "tool allow Comit\n"), names); err == nil {
		t.Error("a rule for a missing tool accepted")
	}
	for _, bad := range []string{"tool allow Safe_Bash\n", "tool maybe Usage\n"} {
		if _, err := Parse([]byte(bad)); err == nil {
			t.Errorf("parsed %q", bad)
		}
	}
}

func TestWithTool(t *testing.T) {
	floor := Floor{Blocklist: []string{"~/.ssh"}}
	safe := compile(t, floor, "file read .\nfile read .git\n")
	files := []FileRule{{Path: ".git", Access: Write}, {Path: "~/.ssh", Access: Read}}
	tc, err := safe.WithTool("Commit", files, []string{"example.com"})
	if err != nil {
		t.Fatal(err)
	}
	if !tc.Access("/home/u/proj/.git/index").Write || tc.Net("example.com") != Allow {
		t.Error("the tool's rules did not apply")
	}
	if tc.Access("/home/u/proj/main.go").Write {
		t.Error("the tool got more than its rules")
	}
	if safe.Access("/home/u/proj/.git/index").Write || safe.Net("example.com") == Allow {
		t.Error("the tool's rules leaked into the policy")
	}
	if tc.Access("/home/u/.ssh/id_rsa").Read {
		t.Error("a tool's rule lifted the floor")
	}
}