How to Secure OpenClaw: 7 Steps From Exposed to Hardened
63% of OpenClaw instances are vulnerable right now.
That's not a guess. The OpenClaw security team published that number in February 2026 after scanning public-facing instances.
The scary part? Most of those instances can be fixed in 20 minutes.
This guide walks you through every step. Each one is tied to a real incident where someone skipped it and paid the price. (If you want the full picture first, read every OpenClaw security risk of 2026.)
Let's fix yours before it makes the next report.
Before You Start
You need three things:
- OpenClaw version 2026.2.25 or later. Older versions have known RCE vulnerabilities. Run
openclaw --versionto check. - Docker Engine 24+ installed on your host.
- Terminal access to the machine running OpenClaw.
If you're on an older version, update first:
openclaw update --latest
Don't skip this. Version 2026.2.25 patched CVE-2026-25253. We'll talk about that one in a minute.
Got all three? Good. Clock starts now.
Step 1: Lock Down the Network
Time: 3 minutes.
The default OpenClaw install binds to 0.0.0.0. That means every device on your network — and possibly the internet — can reach your gateway.
This is how CVE-2026-25253 burned people.
In January 2026, researchers found that exposed OpenClaw gateways accepted unauthenticated RPC calls. Attackers sent crafted payloads through the gateway port. They got shell access on the host machine.
Over 4,000 instances were hit before the patch landed.
Fix it in three commands.
First, bind to localhost only. Open your OpenClaw config:
# ~/.openclaw/config.yaml
server:
host: "127.0.0.1"
port: 3100
Second, block the port at the firewall level. Belt and suspenders.
# UFW (Ubuntu/Debian)
sudo ufw deny in 3100
sudo ufw allow from 127.0.0.1 to any port 3100
# iptables (any Linux)
sudo iptables -A INPUT -p tcp --dport 3100 -s 127.0.0.1 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 3100 -j DROP
Third, if you need remote access, use a VPN. WireGuard takes 5 minutes to set up:
# Allow access from your WireGuard subnet
sudo ufw allow from 10.0.0.0/24 to any port 3100
Never expose the gateway port to the public internet. Not with auth. Not with TLS. Not behind a reverse proxy you "trust." Just don't.
Restart OpenClaw to apply:
openclaw restart
Verify the binding:
ss -tlnp | grep 3100
# Should show 127.0.0.1:3100, NOT 0.0.0.0:3100
Step 2: Enable Authentication
Time: 2 minutes.
Out of the box, OpenClaw has no auth. Anyone who can reach the port can use it.
That's wild. But it's true.
Here's how to fix your openclaw authentication setup.
Generate a strong token. 32 characters minimum. Random.
# Generate a 48-character token
openssl rand -base64 36
Add it to your config:
# ~/.openclaw/config.yaml
auth:
token: "your-48-character-random-token-here"
require_auth: true
Set a rotation reminder. Every 90 days. Put it in your calendar right now.
To rotate without downtime:
# Generate new token
NEW_TOKEN=$(openssl rand -base64 36)
# Update config
openclaw config set auth.token "$NEW_TOKEN"
# Graceful reload (no restart needed)
openclaw reload
Update all clients with the new token. Test each one.
Pro tip: Store the token in an environment variable, not the config file. We'll cover that in the secrets section.
export OPENCLAW_AUTH_TOKEN="your-token-here"
OpenClaw reads OPENCLAW_AUTH_TOKEN automatically when require_auth is true.
Step 3: Run in Docker
Time: 5 minutes.
This is the single most impactful security improvement you can make.
Here's why.
Without Docker, OpenClaw runs as your user. A bad skill gets your home directory. Your SSH keys. Your cloud credentials. Everything.
With Docker, a bad skill gets... an empty container. That's it.
Create a Docker Compose file:
# docker-compose.yml
version: "3.8"
services:
openclaw:
image: openclaw/openclaw:2026.2.25
user: "1000:1000" # Non-root
ports:
- "127.0.0.1:3100:3100" # Localhost only
volumes:
- openclaw-data:/data
- /var/run/docker.sock:/var/run/docker.sock:ro
environment:
- OPENCLAW_AUTH_TOKEN=${OPENCLAW_AUTH_TOKEN}
security_opt:
- no-new-privileges:true
read_only: true
tmpfs:
- /tmp:noexec,nosuid,size=100m
restart: unless-stopped
volumes:
openclaw-data:
Key details here:
user: "1000:1000"— runs as non-root. A compromised process can't escalate to root inside the container.127.0.0.1:3100:3100— binds to localhost even at the Docker level.no-new-privileges— blocks SUID/SGID escalation.read_only: true— the container filesystem is immutable.tmpfswithnoexec— temp files exist but can't run as programs.
Start it:
docker compose up -d
Verify it's running as non-root:
docker exec openclaw whoami
# Should NOT print "root"
If you see "root," something went wrong. Check that the user directive is set.
Step 4: Audit Your Skills
Time: 3 minutes.
In March 2026, a supply chain attack called ClawHavoc hit the OpenClaw skill registry.
Someone uploaded 12 skills that looked like popular utilities. Markdown formatters. CSV parsers. Normal stuff.
Each one had a hidden payload. On install, they sent the host's environment variables — including API keys and tokens — to an external server.
Over 800 instances were hit before the skills got pulled. We wrote a full breakdown of the ClawHavoc campaign — including how to check if you installed a compromised skill.
Here's how to protect yourself.
First, scan every installed skill:
openclaw skills audit --scan-all
This runs the Clawdex scanner. It checks for:
- Known malicious signatures
- Suspicious network calls
- File system access outside the workspace
- Obfuscated code
Second, enable skill allowlisting:
# ~/.openclaw/config.yaml
skills:
allowlist_only: true
allowed:
- "@openclaw/core-tools"
- "@verified/markdown-utils"
- "@verified/data-parser"
With allowlist_only: true, OpenClaw rejects any skill not on the list.
Third, vet new skills before installing:
# Check a skill before adding it
openclaw skills inspect @some-author/some-skill
# Run Clawdex deep scan
openclaw skills scan @some-author/some-skill --deep
Look for these red flags:
- Network access that doesn't match the skill's purpose
- File reads outside the workspace directory
- Calls to
execorspawn - Minified or obfuscated source code
- Author with no other published skills
If anything looks off, don't install it.
Step 5: Control Egress
Time: 3 minutes.
Your OpenClaw instance talks to the internet. LLM APIs, skill registries, webhooks.
But it shouldn't talk to everywhere on the internet.
A deny-all outbound policy with domain allowlisting stops data exfiltration cold. Even if a skill is compromised, it can't phone home. (Deep dive: AI Agent Network Security: Egress Controls.)
Set up egress control:
# ~/.openclaw/config.yaml
network:
egress:
policy: "deny-all"
allowlist:
- "api.anthropic.com"
- "api.openai.com"
- "generativelanguage.googleapis.com"
- "registry.openclaw.dev"
- "api.clawdex.com"
Only add domains you actually need. Every extra domain is an extra attack surface.
Verify it works:
# This should succeed (allowed domain)
openclaw network test api.anthropic.com
# ✓ Connection allowed
# This should fail (blocked domain)
openclaw network test evil-exfiltration-server.com
# ✗ Connection blocked by egress policy
For Docker deployments, add network-level blocking too:
# docker-compose.yml addition
services:
openclaw:
# ... existing config ...
networks:
- openclaw-net
networks:
openclaw-net:
driver: bridge
internal: false # Needs internet for LLM APIs
driver_opts:
com.docker.network.bridge.enable_ip_masquerade: "true"
Then use iptables to restrict outbound at the host level:
# Allow DNS
sudo iptables -A FORWARD -p udp --dport 53 -j ACCEPT
# Allow specific domains (resolve IPs first)
for domain in api.anthropic.com api.openai.com registry.openclaw.dev; do
for ip in $(dig +short $domain); do
sudo iptables -A FORWARD -d $ip -j ACCEPT
done
done
# Block everything else from the container network
sudo iptables -A FORWARD -s 172.18.0.0/16 -j DROP
Step 6: Restrict Tools
Time: 2 minutes.
OpenClaw gives skills access to powerful tools. File writes. Shell execution. System edits.
Most skills don't need any of that.
Block dangerous functions by default:
# ~/.openclaw/config.yaml
tools:
restricted:
- "file_write"
- "file_edit"
- "shell_exec"
- "process_spawn"
- "network_raw"
- "system_config"
require_approval: true
approval_timeout: 30 # seconds
With this config, any skill that tries to write a file, run a shell command, or make a raw network call gets blocked. It shows you a prompt. You approve or deny.
Set per-skill tool grants for trusted skills:
tools:
grants:
"@openclaw/core-tools":
allow:
- "file_write"
- "file_edit"
"@verified/data-parser":
allow:
- "file_write"
This way, your core tools can still write files. But random skills can't.
30 seconds of config. Hours of breach prevention.
Step 7: Monitor and Audit
Time: 2 minutes to set up. Ongoing after that.
You can't fix what you can't see. (For the full treatment, see our AI Agent Audit Logging guide.)
Enable audit logging:
# ~/.openclaw/config.yaml
audit:
enabled: true
log_path: "/data/logs/audit.json"
retention_days: 90
log_events:
- "auth_attempt"
- "auth_failure"
- "skill_install"
- "skill_execute"
- "tool_use"
- "config_change"
- "egress_blocked"
Every auth attempt, every skill execution, every blocked egress call — it all goes in the log.
Add rate limiting for prompt injection defense:
# ~/.openclaw/config.yaml
rate_limit:
enabled: true
requests_per_minute: 30
burst: 10
input_max_length: 50000 # characters
sanitize_inputs: true
Rate limiting slows down automated attacks. Input sanitization catches basic prompt injection attempts.
Check your logs weekly:
# Failed auth attempts in the last 7 days
openclaw logs query --event auth_failure --since 7d
# Blocked egress attempts
openclaw logs query --event egress_blocked --since 7d
# Skill installations
openclaw logs query --event skill_install --since 7d
If you see failed auth attempts from IPs you don't recognize, someone is poking at your instance.
The Security Audit Command
OpenClaw has a built-in audit tool. Run it.
openclaw security audit
It checks 14 things:
| Check | What It Looks For |
|---|---|
| Network binding | Is the gateway bound to localhost or a private IP? |
| Auth token | Is auth enabled? Is the token 32+ characters? |
| Token age | Has the token been rotated in the last 90 days? |
| Container isolation | Is OpenClaw running inside Docker? |
| Non-root | Is the process running as a non-root user? |
| Skill allowlist | Is allowlist mode enabled? |
| Skill signatures | Do all installed skills pass Clawdex scan? |
| Egress policy | Is deny-all outbound enabled? |
| Tool restrictions | Are dangerous tools blocked by default? |
| Rate limiting | Is rate limiting active? |
| Input sanitization | Is input sanitization on? |
| Secret storage | Are secrets in env vars (not config files)? |
| TLS config | Is TLS enabled for any non-localhost connections? |
| Version | Is OpenClaw up to date? Any known CVEs? |
Run it after every config change. Add it to a weekly cron job:
# Weekly security audit (Mondays at 9am)
0 9 * * 1 openclaw security audit --output json >> /data/logs/security-audit.json
A clean audit looks like this:
$ openclaw security audit
OpenClaw Security Audit
=======================
✓ Network binding localhost only
✓ Authentication enabled, token 48 chars
✓ Token rotation last rotated 23 days ago
✓ Container isolation Docker, non-root
✓ Skill allowlist enabled, 3 skills allowed
✓ Egress policy deny-all, 5 domains allowed
✓ Tool restrictions 6 tools blocked, approval required
✓ Rate limiting 30 req/min, burst 10
✓ Input sanitization enabled
✓ Secret storage env vars (no plaintext in config)
✓ TLS not required (localhost only)
✓ Version 2026.2.25 (latest)
Score: 12/12 — All checks passed
If any check fails, the tool tells you exactly what to fix and links to the relevant docs.
Secrets Management
One more thing. Don't put secrets in config files.
Config files get committed to git. They get copied to backups. They end up in screenshots.
Use environment variables:
# ~/.bashrc or systemd unit file
export OPENCLAW_AUTH_TOKEN="your-token-here"
export OPENCLAW_LLM_API_KEY="sk-..."
For teams, use a secrets manager:
# HashiCorp Vault example
export OPENCLAW_AUTH_TOKEN=$(vault kv get -field=token secret/openclaw)
export OPENCLAW_LLM_API_KEY=$(vault kv get -field=api_key secret/openclaw)
For Docker deployments, use Docker secrets or a .env file with strict permissions:
# Create .env with restricted permissions
touch .env
chmod 600 .env
# Add secrets
echo "OPENCLAW_AUTH_TOKEN=your-token" >> .env
echo "OPENCLAW_LLM_API_KEY=sk-..." >> .env
Never commit .env files. Add them to .gitignore.
FAQ
Is OpenClaw secure out of the box?
No. The default install binds to 0.0.0.0 with no authentication. You need to manually enable auth tokens, network isolation, and container execution. This guide covers all of it.
How often should I rotate my OpenClaw auth token?
Every 90 days. Quarterly. If you suspect a leak, rotate immediately. Then check your audit logs for any unauthorized access during the exposure window.
Can I run OpenClaw without Docker?
You can. You shouldn't.
Docker container isolation is the single most impactful security improvement. Without it, a compromised skill has full access to your host system. Your files, keys, and credentials are all exposed.
What is CVE-2026-25253 and does it affect me?
CVE-2026-25253 is a remote code execution bug in OpenClaw versions before 2026.2.25. It exploits exposed gateway ports to run arbitrary code on the host.
If you're on an older version with the gateway reachable from the internet, you are vulnerable. Update and bind to localhost now.
What does openclaw security audit check?
It checks 14 security controls: network binding, auth token strength, container isolation, skill allowlists, egress rules, tool restrictions, rate limits, non-root execution, secret storage, TLS, log retention, version currency, CVE exposure, and permission boundaries. Run it weekly.
Or Skip All This
Every step in this guide matters. But it's a lot to manage.
Token rotation. Egress rules. Skill audits. Weekly log reviews. Version updates.
That's the tax you pay for self-hosting.
Clawctl is managed OpenClaw hosting with all of this built in.
Here's what you get out of the box:
- Docker isolation with per-tenant socket proxy — agents can't touch your host.
- Egress control via Squid proxy with deny-all default — only approved domains get through.
- 50+ high-risk actions blocked — shell exec, file writes outside workspace, raw network calls all require human approval.
- Audit logging — every action searchable and retained by plan tier.
- Human-in-the-loop approvals — dangerous operations wait for you to say "go."
- Prompt injection defenses — 9 attack pattern categories detected and blocked out of the box.
You focus on building. We handle the hardening.
Related reading: