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

EnvironmentseccompeBPFLandlockFUSEptraceCapabilities
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:

ModeScoreTypical EnvironmentKey Protections
full100%Native Linux, privileged containersseccomp syscall filtering, eBPF network, FUSE filesystem
ptrace~90%AWS Fargate, containers with SYS_PTRACEptrace execve interception, shim policy enforcement
landlock~85%Unprivileged containers with FUSELandlock kernel sandbox + FUSE fine-grained control
landlock-only~80%Unprivileged containers, restricted runtimesLandlock kernel sandbox, shim policy enforcement
minimal~50%gVisor, Firecracker, highly restrictedCapability dropping, shim policy only

Feature Availability by Kernel Version

KernelLandlock ABINetwork ControlFilesystem Control
6.10+v5TCP bind/connectFull + IOCTL
6.7+v4TCP bind/connectFull
6.2+v3NoneFull + truncate
5.19+v2NoneFull + REFER
5.13+v1NoneBasic
< 5.13N/ANone (use eBPF)None (use seccomp)

What You Lose Without seccomp

When seccomp is unavailable (nested containers, restricted runtimes):

FeatureWith seccompWithout seccompMitigation
Signal interceptionKernel-levelPID namespace + dropped CAP_KILL
Abstract Unix socketsBlockedPath-based sockets blocked via Landlock
Syscall filtering400+ syscallsLandlock + capabilities cover most cases
Fine-grained executionPer-syscallLandlock execute paths + shim

What You Lose Without eBPF

When eBPF is unavailable:

FeatureWith eBPFWithout eBPFMitigation
Network visibilityAll trafficProxy-based monitoring
Connection trackingKernel-levelLandlock TCP (kernel 6.7+)
DNS inspectionDeepProxy-levelDNS 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:

FeatureWithout ptraceWith ptraceNotes
Execution controlShim onlyKernel-levelIntercepts execve/execveat syscalls
Deny enforcementShim checkSyscall invalidationReturns -EACCES before exec runs
Fork/clone trackingNoYesAuto-attaches to child processes
Process tree depthNoYesTracks nesting for policy decisions
execveat supportNoYesHandles 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 (default 127.0.0.1:9090). The CLI can prefer gRPC via AGENTSH_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:

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 shell IPC
  • 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: AGENTSH in 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 -u with sudo umount fallback
  • 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:

ComponentPolicy
DefaultDeny-all ((deny default))
Process opsAllow fork, exec, self-signal
System pathsRead-only access to /usr/lib, /System/Library, /bin, /usr/bin, etc.
HomebrewRead-only access to /opt/homebrew/bin, /opt/homebrew/Cellar
Temp filesFull access to /tmp, /private/tmp, /var/folders
TTY/PTYFull access for interactive terminal
WorkspaceFull access (from session config)
NetworkDenied by default, requires network capability
IPCMach 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-exec is 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:

LayerTechnologyPurpose
PrimaryAppContainerKernel-enforced capability isolation
SecondaryMinifilter driverPolicy-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:

LevelDescription
noneNo network access (default, maximum isolation)
outboundInternet client connections only
localPrivate network access only
fullAll 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 fuse3 and run agentsh 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: AGENTSH in 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 -u with sudo umount fallback
  • 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/fuse is present and SYS_ADMIN is 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/fuse is 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: false unless 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 metadata x-api-key.