94 lines
2.2 KiB
Go
94 lines
2.2 KiB
Go
package exec
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
func newFileSandbox(t *testing.T, roots ...string) *FileSandbox {
|
|
t.Helper()
|
|
fs, err := NewFileSandbox(roots, discardLogger())
|
|
if err != nil {
|
|
t.Fatalf("NewFileSandbox: %v", err)
|
|
}
|
|
return fs
|
|
}
|
|
|
|
func TestFileSandbox_Resolve_Allowed(t *testing.T) {
|
|
t.Parallel()
|
|
root := t.TempDir()
|
|
realRoot := root
|
|
if r, err := filepath.EvalSymlinks(root); err == nil {
|
|
realRoot = r
|
|
}
|
|
fs := newFileSandbox(t, root)
|
|
|
|
got, err := fs.Resolve(filepath.Join(root, "a.txt"))
|
|
if err != nil {
|
|
t.Fatalf("Resolve: %v", err)
|
|
}
|
|
if want := filepath.Join(realRoot, "a.txt"); got != want {
|
|
t.Errorf("Resolve = %q, want %q", got, want)
|
|
}
|
|
}
|
|
|
|
func TestFileSandbox_Resolve_OutsideRejected(t *testing.T) {
|
|
t.Parallel()
|
|
fs := newFileSandbox(t, t.TempDir())
|
|
outside := filepath.Join(os.TempDir(), "cyrene-outside-file.txt")
|
|
_, err := fs.Resolve(outside)
|
|
if !errors.Is(err, ErrPathOutsideRoot) {
|
|
t.Fatalf("err = %v, want ErrPathOutsideRoot", err)
|
|
}
|
|
}
|
|
|
|
func TestFileSandbox_Resolve_SymlinkEscape(t *testing.T) {
|
|
t.Parallel()
|
|
root := t.TempDir()
|
|
outside := t.TempDir()
|
|
link := filepath.Join(root, "escape")
|
|
if err := os.Symlink(outside, link); err != nil {
|
|
t.Skipf("symlink not supported: %v", err)
|
|
}
|
|
fs := newFileSandbox(t, root)
|
|
|
|
_, err := fs.Resolve(filepath.Join(link, "secret.txt"))
|
|
if !errors.Is(err, ErrSymlinkEscape) {
|
|
t.Fatalf("err = %v, want ErrSymlinkEscape", err)
|
|
}
|
|
}
|
|
|
|
func TestFileSandbox_WriteReadList(t *testing.T) {
|
|
t.Parallel()
|
|
fs := newFileSandbox(t, t.TempDir())
|
|
|
|
if err := fs.WriteFile("a.txt", []byte("content"), 0o600); err != nil {
|
|
t.Fatalf("WriteFile: %v", err)
|
|
}
|
|
data, err := fs.ReadFile("a.txt")
|
|
if err != nil {
|
|
t.Fatalf("ReadFile: %v", err)
|
|
}
|
|
if string(data) != "content" {
|
|
t.Errorf("ReadFile = %q, want content", data)
|
|
}
|
|
entries, err := fs.List(".")
|
|
if err != nil {
|
|
t.Fatalf("List: %v", err)
|
|
}
|
|
if len(entries) != 1 {
|
|
t.Errorf("len(entries) = %d, want 1", len(entries))
|
|
}
|
|
}
|
|
|
|
func TestFileSandbox_NoRoot(t *testing.T) {
|
|
t.Parallel()
|
|
fs := newFileSandbox(t, "")
|
|
_, err := fs.Resolve("a.txt")
|
|
if !errors.Is(err, ErrNoAllowedRoot) {
|
|
t.Fatalf("err = %v, want ErrNoAllowedRoot", err)
|
|
}
|
|
}
|