← Back to Blog

Go Hard on Agents, Not on Your Filesystem: The Complete OpenClaw Sandbox Guide

Go Hard on Agents, Not on Your Filesystem: The Complete OpenClaw Sandbox Guide

Yesterday, a thread titled "Go hard on agents, not on your filesystem" hit HN with 539 points and 300 comments. The discussion tore through .claude/settings.json filesystem sandboxing, bubblewrap, capabilities-based security models, and one uncomfortable realization: most people running AI agents on their machines have given those agents far more filesystem access than they realize.

Nobody wrote the definitive how-to guide. This is it — applied to OpenClaw.

Why Filesystem Access Is the Real Risk

Most agent security conversations focus on prompt injection or malicious tool calls. Those matter, but the deeper risk is simpler: your agent can read (and in some configs, write) nearly any file on your server unless you explicitly restrict it.

Think about what lives on a typical server:

  • SSH private keys in ~/.ssh/
  • .env files with database passwords and API tokens
  • AWS credential files at ~/.aws/credentials
  • Private certificates and TLS keys
  • Your other agents' workspace files, including their SOUL.md memory

A prompt injection attack that exfiltrates ~/.ssh/id_rsa doesn't need shell access. It just needs your agent to read a file and include its contents in a response.

The fix is structural, not behavioral. You can't instruct an agent to "be careful" about what it reads. You restrict what it can read at the OS level.

Step 1: Create a Dedicated OS User for Your Agent

The most important thing you can do costs zero dollars and takes three minutes.

# Create a restricted user for your agent
sudo useradd -m -s /bin/bash openclaw-agent

# Create the agent's workspace directory
sudo mkdir -p /home/openclaw-agent/workspace
sudo chown -R openclaw-agent:openclaw-agent /home/openclaw-agent

Run OpenClaw as this user, not as your main user or root. The agent's working directory becomes /home/openclaw-agent/workspace. It cannot read /home/yourname/, your SSH keys, or any other user's files without an explicit sudo escalation — which you will not grant.

This single change eliminates the majority of credential theft vectors described in the HN thread.

Step 2: Scope AGENTS.md Tool Permissions to Exactly What You Need

OpenClaw's file-based configuration gives you a concrete place to declare what your agent is allowed to do. Your AGENTS.md should include an explicit tool permissions section:

## Tool Permissions

Allowed:
- read: /home/openclaw-agent/workspace/** (workspace only)
- exec: allowlist only (no unrestricted shell)
- exec allowlist: ["curl", "python3 /home/openclaw-agent/workspace/scripts/*.py"]

Denied:
- read: /home/** (no access to other users)
- read: /etc/**, /root/**, /var/** (no system files)
- exec: unrestricted shell commands
- exec: sudo, su, chmod, chown, ssh, scp

This isn't enforced by OpenClaw alone — you need OS-level restrictions to back it up. But it serves a critical function: it's your declared intent, auditable in git, and reviewed by you on every config change. If a future update broadens these permissions, your diff shows it.

This is exactly what the security checklist approach recommends: declare permissions explicitly, then enforce them at the infrastructure level.

Step 3: Apply OS-Level Filesystem Restrictions with bubblewrap

bubblewrap (bwrap) is a low-privilege sandboxing tool originally built for Flatpak. It lets you run a process with a constrained filesystem view — no kernel exploits required, no Docker overhead.

# Install bubblewrap
sudo apt install bubblewrap

# Launch OpenClaw inside a bubblewrap sandbox
bwrap \
  --ro-bind /usr /usr \
  --ro-bind /lib /lib \
  --ro-bind /lib64 /lib64 \
  --ro-bind /bin /bin \
  --ro-bind /etc/resolv.conf /etc/resolv.conf \
  --bind /home/openclaw-agent/workspace /home/openclaw-agent/workspace \
  --tmpfs /tmp \
  --proc /proc \
  --dev /dev \
  --unshare-pid \
  --die-with-parent \
  openclaw start

What this does:

  • Mounts /usr, /lib, /bin as read-only — the agent can use system binaries but can't modify them
  • Binds only the workspace directory as read-write
  • Provides a fresh /tmp that disappears when the process dies
  • Gives the process its own PID namespace so it can't inspect or signal other processes
  • Kills the sandbox if the parent process dies

The agent sees a stripped filesystem. It cannot navigate to /home/yourname/, /root/, /etc/ssh/, or anywhere outside its declared mounts.

Security Guardrails

  • Never bind-mount your home directory. Use the dedicated agent user's workspace only.
  • Mount /usr and /bin read-only. The agent should use tools, not replace them.
  • Use --unshare-pid in production. Prevents the agent from seeing other running processes.
  • Test with --dry-run first. Ensure your agent starts cleanly before applying in production.

Step 4: Handle the Python Subprocess Bypass

The HN thread flagged a real gotcha: Python can bypass filesystem restrictions by spawning subprocesses that inherit permissions from the parent, not the sandbox. If your agent can call python3 -c "import os; os.system('cat ~/.ssh/id_rsa')", the OS user permissions matter more than the sandbox.

Two defenses:

Block unrestricted exec in AGENTS.md. The allowlist approach from Step 2 means your agent can only exec whitelisted commands. python3 /home/openclaw-agent/workspace/scripts/my_script.py can run. python3 -c "import os; ..." cannot.

Use OpenClaw's exec sandboxing mode. In your OpenClaw config, set exec.security to "allowlist". This ensures exec calls must match a declared allowlist — any unlisted command is rejected before it reaches the shell.

{
  "exec": {
    "security": "allowlist",
    "allowlist": [
      "curl",
      "python3 /home/openclaw-agent/workspace/scripts/*.py"
    ]
  }
}

A Python subprocess spawned by an allowed script still runs as the restricted openclaw-agent user inside the bubblewrap sandbox. Its filesystem view is limited to what the sandbox allows — it cannot reach your SSH keys even if the script tries.

Step 5: Test That Your Sandbox Actually Holds

Don't assume the sandbox works. Test it.

# As the openclaw-agent user, try to read a file outside the workspace
su -s /bin/bash openclaw-agent -c "cat /home/yourname/.ssh/id_rsa"
# Should fail: Permission denied

# Inside bubblewrap, try to access a restricted path
bwrap [your flags] --ro-bind /usr /usr --bind /home/openclaw-agent/workspace /home/openclaw-agent/workspace \
  cat /etc/shadow
# Should fail: No such file or directory

# Confirm workspace is writable
bwrap [your flags] touch /home/openclaw-agent/workspace/test.txt
# Should succeed

If any of the restriction tests succeed, something is misconfigured. Fix it before deploying.

Step 6: Limit What Secrets the Agent Ever Sees

Even with filesystem isolation, your agent's context window is a data surface. If you paste an API key into a message to your agent, it lives in the session context until the session ends.

The "no raw credentials in agent context" rule applies here:

  • Store API keys in environment variables loaded at OpenClaw startup, not in workspace files
  • Never write credentials to MEMORY.md or daily memory files
  • Use tool-level credential injection (gog CLI, curl with env var $API_KEY) rather than passing keys as strings in prompts
# In your agent's systemd unit or launch script
Environment="OPENAI_API_KEY=sk-..."
Environment="TELEGRAM_BOT_TOKEN=..."

# Not in AGENTS.md or SOUL.md

The agent tools can use $OPENAI_API_KEY without the key ever appearing in the context window.

Common Mistakes

  • Running OpenClaw as root or your main user. The dedicated OS user is non-negotiable.
  • Bind-mounting your entire home directory. Only mount the workspace.
  • Skipping the exec allowlist. Unrestricted shell access negates filesystem sandboxing.
  • Storing API keys in workspace markdown files. Use environment variables only.
  • Assuming AGENTS.md restrictions are enforced without OS backing. Declarations need infrastructure enforcement.

What This Looks Like End-to-End

Here's the full chain of defense for a production OpenClaw agent:

  1. OS user: openclaw-agent with no home directory access to other users
  2. bubblewrap: Restricted filesystem view — workspace only, system binaries read-only
  3. AGENTS.md: Declared tool permissions (readable, auditable, git-diffable)
  4. exec allowlist: Only whitelisted commands can run, Python subprocesses included
  5. Env vars: API keys never touch the context window
  6. Test harness: Verified that restriction bypass attempts fail

This is the security-first defaults approach applied rigorously. None of these steps require advanced Linux knowledge — they're all documented tools running standard commands.

Why File-Based Configs Make This Auditable

One thing the HN thread got right: the sandboxing conversation is impossible when your agent configuration is opaque. If you can't read what permissions your agent has, you can't verify the sandbox matches them.

OpenClaw's AGENTS.md is your ground truth. You can open it, read it in 10 minutes, diff it against last week's version, and confirm that the exec allowlist matches what your bubblewrap sandbox permits. No vendor dashboard, no trust-but-verify compliance badge — just a file in your git repo.

That's the structural advantage of file-based agent configuration. Not just ownership — auditable ownership.

Build a Sandboxed Agent from the Start

OpenAgents.mom generates workspace bundles with security-first defaults built in — explicit tool permissions, no broad file access, and AGENTS.md structured for auditing. Skip the config archaeology.

Generate Your Sandboxed Agent

Share