Runtime security governance for AI agents using agentsh v0.20.2 with Sprites.dev sandboxes.
Sprites provides isolation. agentsh provides governance.
Sprites.dev sandboxes give AI agents a secure, isolated Firecracker microVM. But isolation alone doesn't prevent an agent from:
- Exfiltrating data to unauthorized endpoints
- Accessing cloud metadata (AWS/GCP/Azure credentials at
169.254.169.254) - Leaking secrets in outputs (API keys, tokens, PII)
- Running dangerous commands (
sudo,ssh,kill,nc) - Reaching internal networks (
10.x,172.16.x,192.168.x) - Escaping via Sprites CLI (
sprite console,sprite list)
agentsh adds the governance layer that controls what agents can do inside the sandbox, providing defense-in-depth:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Sprites.dev Sandbox (Firecracker VM Isolation) β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β agentsh (Governance) β β
β β βββββββββββββββββββββββββββββββββββββββββββββββ β β
β β β AI Agent β β β
β β β - Commands are policy-checked β β β
β β β - Network requests are filtered β β β
β β β - Secrets are redacted from output β β β
β β β - All actions are audited β β β
β β βββββββββββββββββββββββββββββββββββββββββββββββ β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Sprites Provides | agentsh Adds |
|---|---|
| VM-level process isolation | Command blocking (ptrace execve) |
| Firecracker filesystem isolation | File I/O policy (FUSE + ptrace file) |
| VM networking boundaries | Domain allowlist/blocklist (TCP proxy + ptrace network) |
| Full Linux capabilities | Cloud metadata blocking |
| Environment variable filtering | |
| Secret detection and redaction (DLP) | |
| Sprites CLI escape prevention | |
| Deep process tree interception (ptrace) | |
| Non-interactive policy enforcement (shim.conf) | |
| LLM request auditing | |
| Complete audit logging |
agentsh on Sprites uses multiple enforcement layers:
Command Execution Flow
βββββββββββββββββββββ
Agent runs command
β
βΌ
βββββββββββββββ ββββββββββββββββ
β Shell Shim ββββββΆβ Command βββ blocked βββΆ exit 126
β /bin/bash β β Policy β
βββββββββββββββ ββββββββ¬ββββββββ
β allowed
βΌ
ββββββββββββββββ
β ptrace βββ blocked βββΆ EPERM
β (execve, β
β file, net, β
β signal) β
ββββββββ¬ββββββββ
β allowed
ββββββββ΄ββββββββ
β β
βββββββΌβββββββ ββββββΌββββββ
β Network β β FUSE β
β Intercept β β (workspaceβ
β (all TCP) β β only) β
ββββββββββββββ ββββββββββββ
| Layer | Mechanism | What It Protects |
|---|---|---|
| Command Policy | Shell shim + agentsh exec |
Blocks sudo, ssh, kill, nc, sprite, etc. |
| Ptrace (execve) | ptrace syscall tracer | Intercepts child process execution across the entire process tree β env sudo, python -c subprocess.run(["sudo"]), find -exec sudo are all caught |
| Ptrace (network) | ptrace connect/bind/sendto | Kernel-level network enforcement with DNS redirect and SNI rewrite, complementing the TCP intercept proxy |
| Ptrace (file) | ptrace openat/unlinkat | Syscall-level file access interception alongside FUSE and seccomp file_monitor |
| Network | TCP intercept proxy | Domain allowlist/blocklist, cloud metadata blocking, private network blocking |
| FUSE | Workspace FUSE mount | File I/O policy on workspace directory (read/write/soft-delete) |
| Seccomp (file_monitor) | seccomp-bpf user-notify | Intercepts file syscalls (openat, mkdirat, unlinkat) to enforce file_rules on system paths outside FUSE mounts |
| DLP | Pattern matching on output | Redacts API keys, tokens, PII, credentials from command output |
| Env Filtering | Variable allowlist/denylist | Blocks AWS_*, *_SECRET*, *_TOKEN, DATABASE_URL, etc. |
The full demo.sh suite runs 100 policy checks against a fresh sprite. On v0.20.2, 99 pass with 0 failures; the single documented limitation below uses run_limit_test so the suite reports it gracefully rather than failing.
System path file I/O β enforced. agentsh v0.20.2 enables seccomp file_monitor with enforce_without_fuse: true, which intercepts file syscalls (openat, mkdirat, unlinkat, and legacy non-at variants on x86_64) and enforces file_rules on system paths. Writes to /etc, /usr/bin, and similar β via cp, touch, mkdir, tee, or a python3 subprocess β are all blocked. This integration enforces through agentsh exec and the shell shim with sandbox.unix_sockets.enabled: false; the wrap-init gate added in v0.20.0/v0.20.1 (#362/#364) ensures the shim no longer engages agentsh-unixwrap in that configuration, which previously broke non-PTY exec on Firecracker runtimes. The policy includes rules for common system files needed by commands (ld.so.cache, nsswitch.conf, etc.).
Outbound package registries β enforced. Outbound HTTPS to allowed registries (pypi.org, registry.npmjs.org) is allowed reliably through the eBPF network backend (cgroup_sock_addr), which agentsh detect reports as the active network layer on Sprites. The v0.20.1 DNS-redirect latency artifact β where the ptrace network path occasionally added enough latency that the request missed the test window β no longer recurs.
Multi-context top-level command check (known limitation). Command-rule evaluation matches the top-level command of an agentsh exec invocation, so a blocked command launched directly by a wrapper such as env sudo whoami is not caught (the top-level env is evaluated, not the nested sudo). Directly blocked commands (sudo whoami) are denied, and ptrace execve interception still catches blocked commands spawned deeper in the process tree β via xargs, find -exec, a nested script, or a python3 subprocess.
- Sprites CLI installed and authenticated (
sprite list)
# Create a Sprite
sprite create my-agent-env
sprite console -s my-agent-env
# Install agentsh (inside the sprite)
curl -sSL https://raw.githubusercontent.com/canyonroad/agentsh-sprites/main/install.sh | sudo bash
# Checkpoint to persist the setup
exit
sprite checkpoint create -s my-agent-envgit clone https://github.com/canyonroad/agentsh-sprites.git
cd agentsh-sprites
# Create and setup a new sprite
./scripts/setup-sprite.sh --create my-agent-env
# Or setup an existing sprite
./scripts/setup-sprite.sh my-existing-sprite# Full demo (creates sprite, runs 100 tests, cleans up)
./scripts/demo.sh
# Keep the sprite after demo for manual testing
./scripts/demo.sh --keepagentsh replaces /bin/bash with a shell shim (--bash-only; /bin/sh is left untouched) that routes every interactive command through the policy engine:
AI agent runs: bash -c "sudo whoami"
β
βΌ
ββββββββββββββββ
β Shell Shim β /bin/bash β agentsh-shell-shim
β (intercepts) β /bin/sh β untouched
ββββββββ¬ββββββββ
β
βββββββββ΄ββββββββ
β TTY stdin? β
βββββ¬ββββββββ¬ββββ
yes no
β β
βΌ βΌ
ββββββββββββ ββββββββββββββββ
β agentsh β β Real shell β
β exec β β (bypass) β
β (policy) β β No policy. β
ββββββ¬ββββββ β Binary-safe. β
β ββββββββββββββββ
βββββββ΄ββββββ
βΌ βΌ
ββββββββββ ββββββββββ
β ALLOW β β BLOCK β
β exit: 0β β exit:126β
ββββββββββ ββββββββββ
Non-interactive bypass: The shim automatically detects non-TTY stdin and bypasses policy. This means sprite exec operator commands work without interference, and binary data piped through the shell is preserved byte-for-byte. Set AGENTSH_SHIM_FORCE=1 or use /etc/agentsh/shim.conf to override this for sandbox APIs that need policy enforcement on non-interactive commands.
The install script runs agentsh detect to probe the Sprites environment. On v0.20.2 the probe reports Security Mode: full and Protection Score: 85/100 β File Protection 25/25, Command Control 25/25, Network 20/20, Isolation 15/15, and Resource Limits 0/15.
v0.20.2's honest-detect change (#392/#389) reports the backend that detect's default mode would actually install, rather than overstating it. The detected active backends are below; note that this integration's deployed config.yaml additionally enables ptrace mode for deep process-tree interception (see Enforcement Layers), which the Multi-Context tests confirm at runtime.
| Capability | Status | Notes |
|---|---|---|
| seccomp | β | seccomp-bpf with user-notify β seccomp-execve is the detected command backend; file_monitor enforces openat/stat on system paths |
| FUSE | β | Detected file backend β workspace file I/O interception (fusermount3), soft-delete, redirect |
| eBPF | β | Detected network backend β cgroup_sock_addr monitoring (available since the v0.18.0 probe fix) |
| ptrace | β | Available; enabled in this integration's config.yaml for execve/file/network/signal tracing across the process tree (detect's default mode lists it as available, not active) |
| capabilities drop | β | Detected isolation backend β 25/41 dropped (permitted + bounding) |
| cgroups v2 | - | Unavailable β Firecracker VM cannot write cgroup.subtree_control |
| Landlock | - | Requires kernel 6.7+ for network ABI |
| PID namespace | - | Agent runs in host namespace inside the sprite |
Security policy is defined in two files:
config.yamlβ Server configuration: network interception, DLP patterns, LLM proxy, FUSE settings, ptrace, seccomppolicies/default.yamlβ Policy rules: command rules, network rules, file rules, environment policy
Key environment variables (set in /etc/profile.d/agentsh.sh):
| Variable | Default | Description |
|---|---|---|
AGENTSH_CLIENT_TIMEOUT |
5m |
HTTP client timeout for agentsh exec |
AGENTSH_SHIM_FORCE |
Unset | Set 1 to enforce policy for non-interactive commands |
AGENTSH_SHIM_DEBUG |
Unset | Set 1 for shim debug output to stderr |
Non-interactive enforcement: v0.20.2 supports /etc/agentsh/shim.conf as a file-based alternative to AGENTSH_SHIM_FORCE. This is useful for sandbox APIs that execute commands without a PTY and need policy enforcement without relying on environment variables.
See the agentsh documentation for the full policy reference.
agentsh-sprites/
βββ install.sh # Main installation script
βββ config.yaml # agentsh server configuration
βββ policies/
β βββ default.yaml # Security policy (Sprites-optimized)
βββ scripts/
β βββ setup-sprite.sh # Automated sprite setup
β βββ demo.sh # Policy enforcement demo (100 tests)
β βββ verify.sh # Post-install verification
β βββ uninstall.sh # Cleanup script
βββ examples/
βββ test-policy.py # Policy test suite
./scripts/demo.sh # Full demo (100 tests, creates + destroys sprite)
./scripts/demo.sh --keep # Keep sprite after demo for manual testing
./scripts/demo.sh --skip-setup # Run tests on existing sprite with agentsh
./scripts/verify.sh # Post-install verification (run inside sprite)| Category | Tests | Description |
|---|---|---|
| Safe Commands | 5 | ls, echo, pwd, date, hostname allowed |
| Privilege Escalation | 5 | sudo, su, chroot, nsenter, unshare blocked |
| Sprites CLI | 2 | sprite list, sprite console blocked |
| Network Tools | 5 | nc, ssh, telnet, scp, rsync blocked |
| System Commands | 8 | systemctl, kill, shutdown, mount, dd, etc. blocked |
| File Operations | 3 | ls /, cat /etc/hosts allowed, touch /tmp allowed |
| Recursive Delete | 3 | rm -rf, rm -r, rm --recursive blocked |
| Single File Delete | 1 | rm -f /tmp/file allowed |
| Package Install | 2 | npm install, pip install require approval (denied without) |
| File Policy | 31 | Policy engine queries for paths, operations, credentials |
| Non-PTY Shim | 7 | --bash-only verification, non-interactive bypass, SHIM_FORCE |
| Binary Passthrough | 1 | Binary data preserved through /bin/sh (unshimmed) |
| Env Filtering | 7 | Allowed vars visible, secret vars filtered |
| Network Policy | 6 | Localhost allowed, metadata/private blocked, registries allowed |
| Multi-Context | 8 | Deep process tree: env sudo, python subprocess, find -exec |
| File I/O | 6 | System path write blocking via seccomp file_monitor |
- agentsh β Runtime security for AI agents
- Sprites.dev β Stateful sandboxes from Fly.io
MIT