Skip to content

How to Secure Your OpenClaw AI Agent Installation

I exposed my OpenClaw instance to the internet on port 8080. Within hours, I found suspicious requests in my logs. Someone was probing my AI agent, trying to access files and run commands.

That’s when I realized: an AI agent with file system access and command execution capabilities is basically a remote code execution vulnerability waiting to happen.

Here’s how I locked it down.

The Problem with Default Installations

OpenClaw runs as a daemon with access to your file system, terminal, and various APIs. By default:

  • It listens on a predictable port (8080)
  • It may bind to all network interfaces (0.0.0.0)
  • It runs with your user permissions
  • It accepts connections from any IP
  • Skills can execute arbitrary commands

This is convenient for development but dangerous for production. One misconfigured skill or leaked endpoint could give attackers full access to your system.

Step 1: Change the Default Port

The default port 8080 is a common target for automated scanners. I changed it to a non-standard port:

config.yaml
server:
port: 38472 # Use a random high port
host: 127.0.0.1 # Bind to localhost only

At first, I used port 3000. Bad idea—that’s another common port that scanners check. Then I tried 8081, still too predictable.

I ended up using a random port in the 30000-50000 range. The key is unpredictability. Automated scanners focus on common ports; a random high port reduces your attack surface.

After changing the port, restart OpenClaw:

restart.sh
sudo systemctl restart openclaw

Test it works:

test.sh
curl http://localhost:38472/health

Step 2: Use a VPN (Tailscale)

Even with localhost binding, I wanted remote access. I initially tried SSH tunneling, but it was clunky. Then I discovered Tailscale.

Tailscale creates a private network between your devices. No port forwarding, no exposed services, no public IPs.

Here’s how I set it up:

install-tailscale.sh
# Install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh
# Authenticate
sudo tailscale up

Now my server has a private IP like 100.x.y.z. I can access OpenClaw from anywhere:

access-vpn.sh
curl http://100.x.y.z:38472/health

The beauty is that port 38472 is never exposed to the internet. It’s only accessible within my Tailscale network.

Network topology
┌─────────────┐ ┌──────────────┐
│ Laptop │ │ Server │
│ │ │ │
│ Tailscale │◄───────►│ Tailscale │
│ 100.x.y.z │ VPN │ 100.x.y.z │
└─────────────┘ │ │
│ OpenClaw │
│ :38472 │
└──────────────┘
Internet (blocked)

Step 3: Configure Firewall Rules

Defense in depth means multiple layers. Even though Tailscale hides my service, I still configured a firewall.

On Ubuntu, I used ufw:

firewall-setup.sh
# Default deny incoming
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow SSH (don't lock yourself out!)
sudo ufw allow ssh
# Allow Tailscale traffic
sudo ufw allow in on tailscale0
# Enable firewall
sudo ufw enable

I made the mistake of not allowing SSH first. Don’t do that. Always allow SSH before enabling the firewall, or you’ll lock yourself out.

Check your rules:

check-firewall.sh
sudo ufw status verbose

Output should show:

UFW status output
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), disabled (routed)
New profiles: skip
To Action From
-- ------ ----
22/tcp ALLOW IN Anywhere
Anywhere on tailscale0 ALLOW IN Anywhere

Now even if someone discovers my IP, they can’t reach OpenClaw.

Step 4: Use Isolated User Accounts

I initially ran OpenClaw with my regular user account. Big mistake. If compromised, an attacker would have access to all my files.

I created a dedicated user:

create-user.sh
# Create openclaw user with no shell
sudo useradd -r -s /usr/sbin/nologin openclaw
# Create directories
sudo mkdir -p /opt/openclaw/{config,logs,skills}
sudo chown -R openclaw:openclaw /opt/openclaw

Then I configured OpenClaw to run as this user:

systemd-service.sh
# /etc/systemd/system/openclaw.service
[Unit]
Description=OpenClaw AI Agent
After=network.target
[Service]
Type=simple
User=openclaw
Group=openclaw
WorkingDirectory=/opt/openclaw
ExecStart=/usr/local/bin/openclaw --config /opt/openclaw/config/config.yaml
Restart=on-failure
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/openclaw
[Install]
WantedBy=multi-user.target

The systemd hardening options restrict what the process can do:

  • NoNewPrivileges=true: Prevents privilege escalation
  • PrivateTmp=true: Isolates temporary files
  • ProtectSystem=strict: Makes system directories read-only
  • ProtectHome=true: Blocks access to home directories
  • ReadWritePaths: Only allows writing to specified directories

Reload and restart:

reload-service.sh
sudo systemctl daemon-reload
sudo systemctl restart openclaw
sudo systemctl status openclaw

Now OpenClaw runs in a sandbox with minimal privileges.

Step 5: Scan and Audit Skills

Skills are OpenClaw’s power and danger. A malicious skill could exfiltrate data or run destructive commands.

I created an audit script to check skills before installation:

audit-skills.sh
#!/bin/bash
# Check for suspicious patterns in skill files
SKILL_DIR="$1"
if [ -z "$SKILL_DIR" ]; then
echo "Usage: $0 <skill-directory>"
exit 1
fi
echo "Scanning $SKILL_DIR for security issues..."
# Check for suspicious patterns
PATTERNS=(
"curl.*|.*bash"
"wget.*|.*sh"
"eval\s"
"exec\s*("
"__import__"
"subprocess\.call"
"os\.system"
"rm\s+-rf"
)
for pattern in "${PATTERNS[@]}"; do
MATCHES=$(grep -rE "$pattern" "$SKILL_DIR" 2>/dev/null)
if [ -n "$MATCHES" ]; then
echo "⚠️ WARNING: Found pattern '$pattern':"
echo "$MATCHES"
echo ""
fi
done
# Check for external network calls
echo "Checking for external network calls..."
grep -r "http://" "$SKILL_DIR" 2>/dev/null | head -20
grep -r "https://" "$SKILL_DIR" 2>/dev/null | head -20
# Check file permissions
echo ""
echo "File permissions:"
find "$SKILL_DIR" -type f -exec ls -la {} \;

Run this before installing any skill:

run-audit.sh
chmod +x audit-skills.sh
./audit-skills.sh ~/.openclaw/skills/new-skill

I also maintain a whitelist of approved skills in my configuration:

skill-whitelist.yaml
skills:
allowed:
- "openclaw/[email protected]"
- "openclaw/[email protected]"
- "custom/[email protected]"
auto_update: false # Manual review required

This prevents automatic installation of unverified skills.

Verification: Testing Your Setup

After implementing all five steps, I verified each layer:

Port check:

verify-port.sh
# From another machine on the same network
nmap -p 38472 your-server-ip
# Should show "filtered" or "closed"

VPN access:

verify-vpn.sh
# From your Tailscale-connected laptop
curl http://100.x.y.z:38472/health
# Should return 200 OK

Firewall:

verify-firewall.sh
sudo ufw status
# Should show only SSH and Tailscale allowed

User isolation:

verify-user.sh
ps aux | grep openclaw
# Should show process running as 'openclaw' user

Skill audit:

verify-skills.sh
./audit-skills.sh /opt/openclaw/skills
# Should show no warnings

Common Mistakes I Made

Mistake 1: Using default port 8080 I thought “no one will find my server.” Wrong. Automated scanners found it within hours.

Mistake 2: Running as root Convenient? Yes. Secure? Absolutely not. One vulnerability and attackers have root access.

Mistake 3: Skipping skill audits I installed a skill that made external API calls without checking. It wasn’t malicious, but it could have been.

Mistake 4: Not testing firewall rules I blocked myself out twice before adding an exception for SSH. Always test from another terminal before closing your session.

Summary

Securing OpenClaw requires defense in depth:

  1. Obscurity: Random port reduces automated scanning
  2. Network isolation: VPN hides your service from the internet
  3. Firewall: Explicit deny-by-default policy
  4. Least privilege: Dedicated user with minimal permissions
  5. Code audit: Scan skills before installation

No single step is sufficient. Together, they create multiple barriers that make exploitation significantly harder.

The most important insight: treat your AI agent like a remote code execution endpoint. Because that’s essentially what it is. Every security measure you add is another layer of protection between your data and the internet.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments