Runtime security governance for AI agents using agentsh v0.16.9 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. |
System path file I/O: agentsh v0.16.9 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. The policy includes rules for common system files needed by commands (ld.so.cache, nsswitch.conf, etc.). Some edge cases may still hit limitations — the file I/O tests use run_limit_test to document these gracefully.
- 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. Current results:
| Capability | Status | Notes |
|---|---|---|
| seccomp | ✓ | Full seccomp-bpf with user-notify |
| ptrace | ✓ | Active backend — execve, file, network, signal tracing |
| FUSE | ✓ | Workspace file I/O interception |
| capabilities drop | ✓ | Privilege reduction |
| cgroups v2 | ✓ | Resource limits |
| eBPF | - | Requires CAP_BPF and elevated privileges |
| Landlock | - | Requires kernel 6.7+ for network ABI |
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.16.9 also 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 | 22 | Policy engine queries for paths, operations, credentials |
| Non-PTY Shim | 5 | --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 | 7 | 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