mirror of
https://github.com/Twigpine/zero.git
synced 2026-11-10 05:01:28 -10:00
* feat(sandbox): unify command execution and enforcement * test(sandbox): make platform contracts portable * fix(sandbox): close execution lifecycle races Bound retained interactive output, preserve interruption state, and start workspace observation before process launch. Protect active runtime roots with cross-platform leases, capture transient protected-path creation events, and restore process attributes after PTY fallback. * fix(sandbox): restore strict macOS isolation Remove Seatbelt host-local network allowances after native validation showed localhost filters can reach host interfaces. Track process reap completion so retained sessions cannot signal a stale numeric PID.
68 lines
2.0 KiB
Go
68 lines
2.0 KiB
Go
//go:build linux
|
|
|
|
package sandbox
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestProtectedCreateMonitorStopsCommandAndRemovesTarget(t *testing.T) {
|
|
target := filepath.Join(t.TempDir(), ".zero")
|
|
var stderr bytes.Buffer
|
|
started := time.Now()
|
|
code := runLinuxSandboxWithProtectedCreateMonitor("/bin/sh", linuxSandboxBwrapPlan{
|
|
Args: []string{"-c", "mkdir " + shellQuote(target) + "; while :; do :; done"},
|
|
ProtectedCreateTargets: []string{target},
|
|
}, "", &stderr)
|
|
|
|
if code != 1 {
|
|
t.Fatalf("exit code = %d, want policy failure 1; stderr=%s", code, stderr.String())
|
|
}
|
|
if elapsed := time.Since(started); elapsed > 2*time.Second {
|
|
t.Fatalf("protected creation did not stop command promptly; elapsed=%s", elapsed)
|
|
}
|
|
if !strings.Contains(stderr.String(), "blocked creation of protected workspace metadata path") {
|
|
t.Fatalf("missing denial reason: %s", stderr.String())
|
|
}
|
|
if _, err := os.Lstat(target); !os.IsNotExist(err) {
|
|
t.Fatalf("protected target remained after denial: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestProtectedCreateMonitorRecordsTransientCreateEvent(t *testing.T) {
|
|
target := filepath.Join(t.TempDir(), ".zero")
|
|
var stderr bytes.Buffer
|
|
monitor, err := newProtectedCreateMonitor([]string{target}, &stderr)
|
|
if err != nil {
|
|
t.Fatalf("newProtectedCreateMonitor: %v", err)
|
|
}
|
|
if monitor.inotifyFD < 0 {
|
|
monitor.close()
|
|
t.Skip("inotify is unavailable")
|
|
}
|
|
if err := os.Mkdir(target, 0o700); err != nil {
|
|
monitor.close()
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.Remove(target); err != nil {
|
|
monitor.close()
|
|
t.Fatal(err)
|
|
}
|
|
triggered := make(chan struct{}, 1)
|
|
monitor.start(func() { triggered <- struct{}{} })
|
|
violated, gotTarget := monitor.stopAndCleanup()
|
|
if !violated || gotTarget != target {
|
|
t.Fatalf("transient creation = violated %t target %q, want true %q; stderr=%s", violated, gotTarget, target, stderr.String())
|
|
}
|
|
select {
|
|
case <-triggered:
|
|
default:
|
|
t.Fatal("transient create event did not invoke violation callback")
|
|
}
|
|
}
|