agentsh Cross-Platform Notes
April 3, 2026 · View on GitHub
Last updated: April 2026
agentsh supports Linux and macOS natively. Linux provides the most complete feature set. macOS uses ESF+NE (90% security score, Alpha) for file, process, and network enforcement. The ESF+NE tier is functional end-to-end but should not be considered production-ready — expect rough edges and breaking changes.
macOS ESF+NE entitlements: agentsh ships with the required ESF and Network Extension entitlements. No separate Apple approval is needed to use the pre-built binary.
If you're on Windows, the recommended approach is to run agentsh inside WSL2 or a Linux container. Unix socket enforcement (seccomp user-notify) is Linux-only.
Linux Security Levels
Linux security features vary significantly depending on kernel version, runtime environment, and available privileges. agentsh automatically detects available features and selects the best security mode.
Environment Compatibility Matrix
| Environment | seccomp | eBPF | Landlock | FUSE | ptrace | Capabilities |
|---|---|---|---|---|---|---|
| Native Linux (kernel 6.7+) | ✅ | ✅ | ✅ (ABI v4) | ✅ | ✅ | ✅ |
| Native Linux (kernel 5.13-6.6) | ✅ | ✅ | ✅ (ABI v1-3) | ✅ | ✅ | ✅ |
| Native Linux (kernel < 5.13) | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ |
| Docker (privileged) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Docker (unprivileged) | ❌* | ❌ | ✅ | ❌† | ❌‡ | ✅ |
| Docker (--cap-add SYS_PTRACE) | ❌* | ❌ | ✅ | ❌† | ✅ | ✅ |
| Kubernetes (standard) | ❌* | ❌ | ✅ | ❌† | ❌‡ | ✅ |
| AWS Fargate | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ |
| Nested containers | ❌ | ❌ | ✅ | ❌ | ❌‡ | ✅ |
| gVisor/Firecracker | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
* Requires seccomp user-notify support in container runtime
† Requires /dev/fuse device and SYS_ADMIN capability
‡ Requires SYS_PTRACE capability (add via --cap-add SYS_PTRACE or securityContext)
Security Mode by Environment
Based on available features, agentsh selects one of four security modes:
| Mode | Score | Typical Environment | Key Protections |
|---|---|---|---|
full | 100% | Native Linux, privileged containers | seccomp syscall filtering, eBPF network, FUSE filesystem |
ptrace | ~90% | AWS Fargate, containers with SYS_PTRACE | ptrace execve interception, shim policy enforcement |
landlock | ~85% | Unprivileged containers with FUSE | Landlock kernel sandbox + FUSE fine-grained control |
landlock-only | ~80% | Unprivileged containers, restricted runtimes | Landlock kernel sandbox, shim policy enforcement |
minimal | ~50% | gVisor, Firecracker, highly restricted | Capability dropping, shim policy only |
Feature Availability by Kernel Version
| Kernel | Landlock ABI | Network Control | Filesystem Control |
|---|---|---|---|
| 6.10+ | v5 | TCP bind/connect | Full + IOCTL |
| 6.7+ | v4 | TCP bind/connect | Full |
| 6.2+ | v3 | None | Full + truncate |
| 5.19+ | v2 | None | Full + REFER |
| 5.13+ | v1 | None | Basic |
| < 5.13 | N/A | None (use eBPF) | None (use seccomp) |
What You Lose Without seccomp
When seccomp is unavailable (nested containers, restricted runtimes):
| Feature | With seccomp | Without seccomp | Mitigation |
|---|---|---|---|
| Signal interception | Kernel-level | ❌ | PID namespace + dropped CAP_KILL |
| Abstract Unix sockets | Blocked | ❌ | Path-based sockets blocked via Landlock |
| Syscall filtering | 400+ syscalls | ❌ | Landlock + capabilities cover most cases |
| Fine-grained execution | Per-syscall | ❌ | Landlock execute paths + shim |
What You Lose Without eBPF
When eBPF is unavailable:
| Feature | With eBPF | Without eBPF | Mitigation |
|---|---|---|---|
| Network visibility | All traffic | ❌ | Proxy-based monitoring |
| Connection tracking | Kernel-level | ❌ | Landlock TCP (kernel 6.7+) |
| DNS inspection | Deep | Proxy-level | DNS proxy |
What You Gain With ptrace
When seccomp user-notify is unavailable but SYS_PTRACE capability is present (e.g. AWS Fargate), ptrace mode provides kernel-level execve interception:
| Feature | Without ptrace | With ptrace | Notes |
|---|---|---|---|
| Execution control | Shim only | Kernel-level | Intercepts execve/execveat syscalls |
| Deny enforcement | Shim check | Syscall invalidation | Returns -EACCES before exec runs |
| Fork/clone tracking | No | Yes | Auto-attaches to child processes |
| Process tree depth | No | Yes | Tracks nesting for policy decisions |
| execveat support | No | Yes | Handles fd-based exec (AT_EMPTY_PATH) |
Typical use case: AWS Fargate tasks where seccomp user-notify and eBPF are unavailable, but SYS_PTRACE is granted via linuxParameters.capabilities.add.
Detection and Fallback
agentsh performs capability detection at startup:
INFO security capabilities detected
seccomp_user_notify=false # Not available in this container
ebpf=false # No CAP_BPF
landlock=true
landlock_abi=4 # Kernel 6.7+
landlock_network=true # Can restrict TCP
fuse=false # No /dev/fuse
ptrace=true # SYS_PTRACE available
capabilities=true # Can drop caps
INFO selected security mode
mode=ptrace
protection_score=90%
Forcing Specific Modes
Override auto-detection in configuration:
security:
# Force a specific mode (fails if requirements not met when strict=true)
mode: landlock-only
strict: true
# Or set a minimum acceptable mode
mode: auto
minimum_mode: landlock-only # Fail if only minimal is available
See Security Modes for detailed mode configuration.
What works today
- Linux (native): primary supported platform with tiered security (full → landlock → landlock-only → minimal depending on environment). See Linux Security Levels above.
- macOS ESF+NE (Alpha): Endpoint Security Framework + Network Extension for near-Linux enforcement. Install via
brew tap canyonroad/tap && brew install --cask agentsh. - Windows: run in WSL2 (recommended) or a Linux container.
- gRPC (optional): if enabled, clients connect to
server.grpc.addr(default127.0.0.1:9090). The CLI can prefer gRPC viaAGENTSH_TRANSPORT=grpc.
Feature availability (current implementation)
- FUSE workspace view: Linux (FUSE3) and Windows (WinFsp). In containers requires
/dev/fuse+SYS_ADMIN. macOS uses ESF for file monitoring. - FUSE event emission: File operation events (open, read, write, create, delete, rename) are emitted to the configured EventChannel for audit logging and monitoring.
- Process sandboxing: Linux (namespaces via unshare), macOS (sandbox-exec with SBPL profiles), Windows (AppContainer).
- Network visibility + policy enforcement: works via the per-session proxy (DNS/connect/HTTP events).
- Transparent netns interception: optional, Linux/root-only (requires privileges; proxy mode works without it).
- cgroups v2 limits: optional, Linux-only; disabled by default (requires a writable cgroup base path).
- macOS resource monitoring: native Mach API monitoring for memory, CPU, and thread count (monitoring only, no enforcement).
- Windows resource monitoring: Job Objects for memory, CPU, disk I/O, process count; Toolhelp32 for thread count (both monitoring and enforcement via Job Objects).
- Process execution stats: CPU user/system time returned in exec results on all platforms. Peak memory available on Unix (Linux/macOS) but not Windows.
- Registry monitoring + policy enforcement: Windows-only, requires mini filter driver (see below).
- seccomp syscall filtering: Linux-only via seccomp user-notify for unix socket enforcement.
- ptrace execve interception: Linux-only via PTRACE_SEIZE for execve/execveat enforcement in restricted containers (e.g. AWS Fargate with SYS_PTRACE).
- XPC/Mach IPC control: macOS-only via sandbox profiles with mach-lookup restrictions. See macOS XPC Sandbox.
- Full namespace isolation: Linux, Lima VM, and WSL2 via
unshare(user, mount, PID, network namespaces). - eBPF network enforcement: Linux-only, requires cgroups v2 and root/CAP_BPF.
Quick start
Linux
agentsh server
macOS (ESF+NE — Alpha)
brew tap canyonroad/tap
brew install --cask agentsh
After installation, approve the system extension in System Settings > General > Login Items & Extensions.
From source (requires Xcode 15+):
make build-macos-enterprise
See macOS Build Guide for detailed build instructions.
macOS (Lima VM - Full Isolation)
For full Linux isolation on macOS, Lima VM provides two deployment modes:
Inside-VM Mode (Recommended - 100% Security Score)
Run agentsh and your AI agent harness entirely inside the Lima VM. This is identical to native Linux:
# Install Lima
brew install lima
# Create and start a VM
limactl start default
# Shell into the VM
limactl shell default
# Inside the VM - install and run agentsh as normal Linux
curl -fsSL https://get.agentsh.dev | bash
agentsh server
This gives you full Linux-equivalent protection:
- Full FUSE3 filesystem interception
- Full iptables network interception
- Full Linux namespace isolation (mount, network, PID, user)
- Full seccomp-bpf syscall filtering
- Full cgroups v2 resource limits
This is the simplest approach - no special Lima platform code needed. Just treat the VM as a Linux server.
Trade-offs:
- File I/O to macOS filesystem via virtiofs (15-30% overhead)
- VM uses ~200-500MB RAM
- Interact via SSH/shell into VM
Orchestrated Mode (85% Security Score)
Run agentsh on macOS, using Lima as a remote execution sandbox:
# Install Lima
brew install lima
# Create and start a VM
limactl start default
# agentsh on macOS automatically detects Lima and uses it
agentsh server # Will use darwin-lima mode
Automatic Detection: When limactl is installed and at least one VM is running, agentsh automatically uses Lima mode which provides:
- Full Linux namespace isolation (mount, network, PID, user)
- seccomp-bpf syscall filtering
- cgroups v2 resource limits
- FUSE3 filesystem interception
- iptables network interception
Trade-offs:
- Additional latency from
limactl shellIPC - Path translation between macOS and Lima paths
- More complex architecture
Manual Mode Selection: You can force Lima mode in your config:
platform:
mode: darwin-lima # or just "lima"
Lima Implementation Details (Both Modes)
Inside the VM, both modes use standard Linux primitives:
Resource Limits (cgroups v2):
- Cgroup path:
/sys/fs/cgroup/agentsh/<session-name> - Supported limits: CPU (quota/period), memory, process count, disk I/O (read/write bandwidth)
- Stats available: memory usage, CPU time, process count, disk I/O bytes
Network Interception (iptables):
- Custom chain:
AGENTSHin the nat table - TCP traffic redirected to proxy port (localhost excluded)
- DNS (UDP port 53) redirected to DNS proxy port
Filesystem Mounting (bindfs):
- Source directory mounted to mount point using bindfs (passthrough mount)
- Automatic bindfs installation if not present (
sudo apt install bindfs) - Unmount via
fusermount -uwithsudo umountfallback - Mount tracking prevents duplicate mounts to same location
Process Isolation (namespaces):
- Full isolation: user, mount, UTS, IPC, network, and PID namespaces
- Partial isolation: mount, UTS, IPC, PID namespaces (when user namespace unavailable)
- Automatic detection of available isolation level
- Working directory support for sandboxed commands
macOS (sandbox-exec - Process Sandboxing)
For all macOS deployments (ESF+NE or Lima), agentsh uses sandbox-exec with SBPL (Sandbox Profile Language) profiles to provide process-level file and network restrictions:
# sandbox-exec is used automatically when executing commands
# No additional installation required - it's a built-in macOS tool
How It Works:
When agentsh executes a command in a session, it wraps the command with sandbox-exec -p '<SBPL profile>' <command>. The SBPL profile is dynamically generated based on the session's workspace and configuration.
Default Profile Behavior:
| Component | Policy |
|---|---|
| Default | Deny-all ((deny default)) |
| Process ops | Allow fork, exec, self-signal |
| System paths | Read-only access to /usr/lib, /System/Library, /bin, /usr/bin, etc. |
| Homebrew | Read-only access to /opt/homebrew/bin, /opt/homebrew/Cellar |
| Temp files | Full access to /tmp, /private/tmp, /var/folders |
| TTY/PTY | Full access for interactive terminal |
| Workspace | Full access (from session config) |
| Network | Denied by default, requires network capability |
| IPC | Mach messaging and POSIX IPC allowed |
Enabling Network Access:
sandbox:
capabilities:
- network # Adds (allow network*) to SBPL profile
Adding Extra Paths:
sandbox:
workspace: /path/to/workspace
allowed_paths:
- /home/user/.config/myapp # Additional full access
- /usr/local/share/data
Limitations:
sandbox-execis deprecated by Apple but functional on all macOS versions- No resource limits (CPU, memory) - use Lima for that
- No syscall filtering (unlike Linux seccomp)
- Child processes inherit the sandbox (escape not possible via fork)
- No PID namespace isolation (sandboxed processes can see all system processes)
Security Score: Contributes to the "Minimal" process isolation tier on macOS.
Implementation: See internal/platform/darwin/sandbox.go for the SBPL profile generation logic.
Windows (Native - Mini Filter Driver)
For native Windows support with kernel-level enforcement:
# Install the driver (requires Administrator)
# Driver must be test-signed for development or production-signed for release
sc create agentsh type=filesys binPath="C:\path\to\agentsh.sys"
sc start agentsh
# Run the agentsh server
agentsh server
Requirements:
- Windows 10/11 (64-bit)
- Administrator privileges for driver installation
- Test signing enabled for development, or EV-signed driver for production
Network Interception:
- WinDivert for transparent TCP/DNS proxy (requires Administrator)
- Falls back to WFP for block-only mode if WinDivert unavailable
Current Implementation Status (All 5 Phases Complete):
- ✅ Driver skeleton and filter port communication
- ✅ Process tracking (session processes and child inheritance)
- ✅ Filesystem interception (create, write, delete, rename)
- ✅ Registry interception (create/set/delete keys, high-risk path detection)
- ✅ Network interception (WinDivert TCP/DNS proxy with WFP fallback)
- ✅ Production readiness (configurable fail modes, metrics, caching)
- ✅ WinFsp filesystem mounting (FUSE-style with soft-delete support)
Registry Policy Configuration:
Registry rules in your policy file control Windows registry access:
registry_rules:
- name: allow-app-settings
paths: ['HKCU\SOFTWARE\MyApp\*']
operations: ["*"]
decision: allow
- name: block-persistence-keys
paths:
- 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run*'
- 'HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run*'
operations: [write, create, delete]
decision: deny
priority: 100
Built-in high-risk path detection automatically blocks write operations to critical registry locations (Run keys, services, Windows Defender settings, LSA) with MITRE ATT&CK technique mappings for audit logging.
WinFsp Filesystem Mounting:
For FUSE-style filesystem mounting with soft-delete support:
# Install WinFsp (required for FUSE-style mounting)
winget install WinFsp.WinFsp
# Build with CGO enabled
CGO_ENABLED=1 go build -o agentsh.exe ./cmd/agentsh
# Run the server (WinFsp mount is automatic)
agentsh server
WinFsp provides FUSE-style mounting on Windows, using a shared internal/platform/fuse/ package. Features include:
- Policy-enforced file operations (read, write, create, delete)
- Soft-delete (files moved to trash instead of permanent deletion)
- Automatic minifilter process exclusion to prevent double-interception
AppContainer Sandbox Isolation:
Windows 8+ supports AppContainer for kernel-enforced process isolation. agentsh uses a two-layer security model:
| Layer | Technology | Purpose |
|---|---|---|
| Primary | AppContainer | Kernel-enforced capability isolation |
| Secondary | Minifilter driver | Policy-based file/registry rules |
AppContainer Features:
- Full process isolation with kernel-enforced capability restrictions
- Stdout/stderr capture from sandboxed processes
- Automatic ACL cleanup on sandbox close
- Configurable network access levels (none, outbound, local, full)
Sandbox Configuration:
sandbox:
windows:
use_app_container: true # Default: true (Windows 8+ required)
use_minifilter: true # Default: true
network_access: none # none, outbound, local, full
fail_on_error: true # Default: true
Network Access Levels:
| Level | Description |
|---|---|
none | No network access (default, maximum isolation) |
outbound | Internet client connections only |
local | Private network access only |
full | All network access |
Configuration Example (Go API):
config := platform.SandboxConfig{
Name: "my-sandbox",
WorkspacePath: "/path/to/workspace",
WindowsOptions: &platform.WindowsSandboxOptions{
UseAppContainer: true,
UseMinifilter: true,
NetworkAccess: platform.NetworkNone,
FailOnAppContainerError: true,
},
}
See Windows Driver Deployment Guide for installation and configuration.
Windows (WSL2)
- Install WSL2 + a distro (e.g. Ubuntu).
- Inside WSL, install
fuse3and runagentsh server. - Keep workspaces on the Linux filesystem (e.g.
/home/...), not/mnt/c/..., for performance.
Resource Limits (cgroups v2): WSL2 uses cgroups v2 inside the Linux VM for resource enforcement:
- Cgroup path:
/sys/fs/cgroup/agentsh/<session-name> - Supported limits: CPU (quota/period), memory, process count, disk I/O (read/write bandwidth)
- Stats available: memory usage, CPU time, process count, disk I/O bytes
Network Interception (iptables): WSL2 uses iptables DNAT rules for traffic redirection:
- Custom chain:
AGENTSHin the nat table - TCP traffic redirected to proxy port (localhost excluded)
- DNS (UDP port 53) redirected to DNS proxy port
Filesystem Mounting (bindfs): WSL2 uses bindfs for FUSE-based filesystem mounting inside the VM:
- Windows paths translated to WSL paths (e.g.,
C:\Users\test→/mnt/c/Users/test) - Source directory mounted to mount point using bindfs (passthrough mount)
- Automatic bindfs installation if not present (
sudo apt install bindfs) - Unmount via
fusermount -uwithsudo umountfallback - Mount tracking prevents duplicate mounts to same location
Process Isolation (namespaces): WSL2 uses Linux namespaces via unshare for process isolation:
- Full isolation: user, mount, UTS, IPC, network, and PID namespaces
- Partial isolation: mount, UTS, IPC, PID namespaces (when user namespace unavailable)
- Automatic detection of available isolation level
- Working directory support for sandboxed commands
Docker (any host)
FUSE requires extra privileges inside containers:
docker run --rm -it \
--cap-add SYS_ADMIN \
--device /dev/fuse \
--security-opt apparmor=unconfined \
-p 18080:18080 \
-v "$(pwd)":/workspace \
ghcr.io/agentsh/agentsh:latest
Detecting Available Capabilities
Use agentsh detect to probe your environment and see what security features are available:
# Show capabilities in table format (default)
agentsh detect
# Output as JSON for scripting
agentsh detect --output json
# Output as YAML
agentsh detect --output yaml
Generating Optimized Configuration
Use agentsh detect config to generate a configuration snippet optimized for your environment:
# Print to stdout
agentsh detect config
# Write to file
agentsh detect config --output security.yaml
# Redirect to file
agentsh detect config > my-config.yaml
The generated config includes only security-related sections (security:, landlock:, capabilities:) that you can merge into your main configuration file.
Troubleshooting
- FUSE mount fails (Linux): ensure FUSE3 is installed (host/VM) and, in Docker,
/dev/fuseis present andSYS_ADMINis allowed. - No file events on macOS: ensure the system extension is approved in System Settings > General > Login Items & Extensions.
- bindfs mount fails (Lima/WSL2): ensure bindfs is installed in the VM (
sudo apt install bindfs) and/dev/fuseis available. - System Extension not loading (macOS ESF+NE): check System Settings > General > Login Items & Extensions. User must approve the System Extension.
- XPC connection fails (macOS ESF+NE): verify the System Extension is approved and running. Check Console.app for XPC errors.
- ESF client initialization fails: ensure the app is signed with valid ESF entitlement from Apple (requires approval).
- Transparent network mode fails: run as root / with NET_ADMIN capabilities; otherwise rely on proxy mode.
- cgroups errors: keep
sandbox.cgroups.enabled: falseunless you have a writable cgroup v2 base path configured. - gRPC connection fails: confirm
server.grpc.enabled: true, the address/port are reachable, and (if auth is enabled) send the API key via gRPC metadatax-api-key.