Security hardening for OpenClaw
OpenClaw runs with your full system privileges. If someone gets in, they have everything: your files, your credentials, your connected services. This guide covers how to lock it down.
Most of this takes under an hour. Skipping it means your agent is one misconfiguration away from being someone else's agent.
Difficulty: Intermediate | Cost: Free | Time: ~45 minutes
Prerequisites
- A working OpenClaw installation (any deployment method)
- Terminal access to the machine running OpenClaw
- Docker installed if you want containerized isolation (recommended)
- Tailscale account (free tier works) for secure remote access
Step 1: Never expose the gateway to the internet
OpenClaw's gateway runs on port 18789. By default it only accepts localhost connections. Get this wrong and nothing else in this guide matters.
Bitsight found over 30,000 exposed OpenClaw instances in twelve days of scanning. Many were over plain HTTP. Researchers pulled API keys, chat histories, and Slack tokens from these instances.
Check if your gateway is exposed:
# From a different machine, try to reach the gateway
curl -s http://YOUR_SERVER_IP:18789/api/health
# If you get a response, your gateway is exposed
Bind to localhost only. In your OpenClaw config (~/.openclaw/config.yaml):
gateway:
host: 127.0.0.1
port: 18789
Do not set host to 0.0.0.0. Do not set allowInsecureAuth: true.
If you use a reverse proxy (nginx, Caddy), be careful. A reverse proxy forwards requests to localhost, so OpenClaw sees them as local traffic and trusts them. If you must use one, add authentication at the proxy layer:
# nginx — require HTTP basic auth before proxying to OpenClaw
server {
listen 443 ssl;
server_name openclaw.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/openclaw.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/openclaw.yourdomain.com/privkey.pem;
# Restrict to specific IPs if possible
allow 203.0.113.10; # your IP
deny all;
auth_basic "OpenClaw Gateway";
auth_basic_user_file /etc/nginx/.htpasswd;
location / {
proxy_pass http://127.0.0.1:18789;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
Generate the htpasswd file:
sudo apt-get install apache2-utils
sudo htpasswd -c /etc/nginx/.htpasswd openclaw
# Enter a strong password when prompted
The better option is to skip the reverse proxy entirely and use Tailscale. It creates a private network between your devices. Your gateway stays bound to localhost, and you access it through the Tailscale network.
# Install Tailscale on the OpenClaw machine
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
# Note the Tailscale IP (100.x.y.z)
tailscale ip -4
# Install Tailscale on your laptop/phone too
# Access OpenClaw at http://100.x.y.z:18789 through the Tailscale network
With Tailscale, port 18789 never touches the public internet. No firewall rules to mess up, no proxy to misconfigure.
If Tailscale isn't an option, use UFW to lock down the port:
# Block all external access to the gateway port
sudo ufw deny 18789
# Allow only from specific IPs on your LAN
sudo ufw allow from 192.168.1.0/24 to any port 18789
# Verify
sudo ufw status
Run the built-in security audit:
openclaw security audit
This checks for exposed ports, weak auth tokens, and common misconfigurations. Run it after every config change.
Step 2: Run OpenClaw in Docker with restricted permissions
Running OpenClaw directly on your host means a compromised agent can touch everything your user account can. Docker puts a wall between the agent and the rest of your system.
Create a docker-compose.yml with security restrictions:
version: "3.8"
services:
openclaw:
image: openclaw/openclaw:latest
container_name: openclaw-hardened
restart: unless-stopped
# Bind to localhost only
ports:
- "127.0.0.1:18789:18789"
# Drop all capabilities, add back only what's needed
cap_drop:
- ALL
# Read-only root filesystem
read_only: true
# Don't allow privilege escalation
security_opt:
- no-new-privileges:true
# Limit resources
deploy:
resources:
limits:
memory: 2G
cpus: "2.0"
# Minimal writable volumes
volumes:
- ./config:/app/config:ro # Config is read-only
- ./data:/app/data # Agent data (writable)
- ./tmp:/tmp # Temp files
# Non-root user
user: "1000:1000"
environment:
- OPENCLAW_GATEWAY_HOST=0.0.0.0
- OPENCLAW_GATEWAY_PORT=18789
# Load API keys from .env file, not hardcoded
env_file:
- .env
What each of these does:
cap_drop: ALL— removes Linux capabilities (mounting filesystems, changing file ownership, binding privileged ports)read_only: true— the agent can't write outside of explicitly mounted volumesno-new-privileges— blocks privilege escalation through setuid binariesuser: "1000:1000"— runs as non-root inside the container- Memory and CPU limits — a runaway agent can't eat your whole machine
Create the .env file with your credentials:
# .env — keep this file locked down (chmod 600)
ANTHROPIC_API_KEY=sk-ant-...
chmod 600 .env
Start it up:
docker compose up -d
# Verify it's running
docker compose logs -f openclaw-hardened
If you need the agent to run commands on the host (file operations, git, etc.), mount only the directories it actually needs:
volumes:
- ./config:/app/config:ro
- ./data:/app/data
- /home/you/projects:/projects # Only this directory, not all of /home
- ./tmp:/tmp
Step 3: Keep exec approvals on
OpenClaw asks for confirmation before the agent runs shell commands. Don't turn this off.
CVE-2026-25253 showed how an attacker with API access could set exec.approvals to "off" and run arbitrary commands. If approvals are already off, there's no safety check to bypass — the attacker gets code execution immediately.
Verify approvals are enabled:
openclaw config get exec.approvals
# Should return: "on" or "always"
If it's off, fix it:
openclaw config set exec.approvals on
In your config file (~/.openclaw/config.yaml), make sure you have:
exec:
approvals: on
If you're running in Docker, make the config read-only so even a compromised agent can't flip this setting:
volumes:
- ./config:/app/config:ro # read-only mount
Step 4: Disable remote execution on paired Mac nodes
When you pair a macOS machine, the gateway can invoke system.run on that node — remote code execution on your Mac.
If you're not using this, turn it off.
# Check current node pairing status
openclaw nodes list
# Remove a paired node
openclaw nodes remove <node-id>
Set the security policy to deny remote execution in your config:
nodes:
security: deny
tools:
exec:
host: local # Never "gateway"
tools.exec.host: gateway was part of the CVE-2026-25253 exploit chain. It let attackers escape Docker containers and execute on the host. Keep it on local.
Step 5: Lock down credentials and file permissions
OpenClaw stores credentials in config files and environment variables, readable by any process running as your user.
Restrict permissions on the OpenClaw directory:
# Only your user can read/write
chmod 700 ~/.openclaw
chmod 600 ~/.openclaw/config.yaml
chmod -R 600 ~/.openclaw/agents/ # Session transcripts with sensitive data
# Verify
ls -la ~/.openclaw/
Don't reuse your production Anthropic API key or primary GitHub token. Create dedicated keys with minimal permissions:
- Anthropic: create a separate API key in your dashboard, set a spending limit
- GitHub: create a fine-grained personal access token scoped to specific repos
- Slack: create a dedicated bot token with minimal channel access
- Email: use a burner email account, not your primary
For messaging apps, use burner accounts. If your agent's Slack token leaks, you want the damage limited to a throwaway account, not your work identity.
Rotate API keys monthly. Set a calendar reminder. If you suspect compromise, rotate everything immediately.
Step 6: Restrict input channels
Every channel your agent reads is an attack surface. An email, a Slack message, a Discord post — any of these can contain hidden instructions that the agent follows without question.
Use DM pairing and allowlists:
# Only accept messages from specific users
messaging:
allowlist:
- user_id_1
- user_id_2
dm_pairing: true # Require DM pairing before accepting commands
Don't connect your agent to:
- Open Slack channels where anyone can post
- Public Discord servers
- Email inboxes that receive mail from unknown senders
- Moltbook or other agent social networks (unless fully isolated)
If you must connect to email, create a dedicated inbox that only accepts mail from whitelisted senders. Reject everything else at the provider level.
Step 7: Audit skills before installing
26% of agent skills analyzed by Cisco contained at least one vulnerability. Some were outright malware.
Before installing any skill:
- Check the download count and community reviews on ClawHub
- Read the skill's source code — look for
curl,wget,fetch, or any outbound network calls - Check if it asks the agent to run shell commands
- Run Cisco's open-source Skill Scanner:
# Install the scanner
pip install openclaw-skill-scanner
# Scan a skill before installing
openclaw-skill-scanner scan <skill-name>
After installing a skill, watch what your agent does:
# Watch agent activity in real time
openclaw logs -f
# Check for unexpected outbound connections
# (on Linux)
ss -tnp | grep openclaw
# (on macOS)
lsof -i -P | grep openclaw
Unexpected outbound connections from a newly installed skill? Uninstall it and rotate every credential the agent had access to.
Step 8: Run the security audit regularly
OpenClaw ships with a built-in audit command. Run it after config changes and put it on a schedule.
openclaw security audit
Set up a cron job to run it daily:
crontab -e
Add:
0 9 * * * /usr/local/bin/openclaw security audit >> /var/log/openclaw-audit.log 2>&1
Check the log once a week or so. The audit catches exposed ports, weak tokens, bad permissions, and known vulnerabilities.
Quick reference
| Setting | Secure value | Where to set it |
|---|---|---|
gateway.host | 127.0.0.1 | ~/.openclaw/config.yaml |
allowInsecureAuth | false (or don't set it) | ~/.openclaw/config.yaml |
exec.approvals | on | ~/.openclaw/config.yaml |
tools.exec.host | local | ~/.openclaw/config.yaml |
nodes.security | deny | ~/.openclaw/config.yaml |
~/.openclaw/ permissions | 700 | Filesystem |
config.yaml permissions | 600 | Filesystem |
.env permissions | 600 | Filesystem |
If you think you've been compromised
Pull the network cable first, ask questions later. Then:
- Rotate every credential your agent had access to. API keys, tokens, passwords — all of them, not just the ones you think were exposed.
- Read through
~/.openclaw/agents/session logs for commands you didn't authorize. - Check outbound connections for signs of data exfiltration.
- Run
openclaw security auditand go through every finding. - If you were running without Docker, assume the attacker had your full user account. Check for new SSH keys, cron jobs, and shell history.
This guide is maintained by OpenClaw Directory. For the full threat landscape, read our security breakdown.