I've been running OpenClaw as my personal AI assistant for months now, and I'll admit: when I first set it up, I was so excited about having an AI in my WhatsApp that I didn't think twice about security. "It's just for me," I told myself. Then I added my Telegram bot to a group chat. Then I let a friend test it. Suddenly my "personal" assistant was talking to strangers.
That's when I realized: OpenClaw isn't just a chatbot. It's a gateway to your machine. It can run commands, read files, and send messages as you. So the question isn't "do I need to secure this?" but "how do I secure this without losing the magic?"
I've spent the last few weeks digging through the docs, reading the GitHub issues, and hardening my own setup. Here's what I've learned—the stuff that actually works, not just theory.
Let me walk you through securing your OpenClaw gateway from the ground up, based on the official docs, real-world deployments, and what I've learned the hard way.
The Threat Model: What Are We Protecting Against?
Before we dive into configs, let's get clear on the risks. OpenClaw sits between your messaging apps and an AI that can:
- Execute shell commands on your machine
- Read and write files
- Access network services
- Send messages to anyone you're connected to
The people who message you can:
- Try to trick the AI into doing bad things (prompt injection)
- Social engineer access to your data
- Probe for infrastructure details
The key insight from the OpenClaw security model: access control before intelligence. Don't rely on the AI to "do the right thing"—assume it can be manipulated. Your job is to limit who can trigger it and what it can reach.
Baseline Hardening: 60 Seconds to Safety
If you do nothing else, apply this baseline to your openclaw.json:
{
"gateway": {
"mode": "local",
"bind": "loopback",
"auth": { "mode": "token", "token": "replace-with-long-random-token" }
},
"session": {
"dmScope": "per-channel-peer"
},
"tools": {
"profile": "messaging",
"deny": ["group:automation", "group:runtime", "group:fs", "sessions_spawn", "sessions_send"],
"fs": { "workspaceOnly": true },
"exec": { "security": "deny", "ask": "always" },
"elevated": { "enabled": false }
},
"channels": {
"whatsapp": { "dmPolicy": "pairing", "groups": { "*": { "requireMention": true } } }
}
}
Let's break down what this does:
-
Gateway only listens on loopback (
bind: "loopback") – no network exposure - All WebSocket connections require a token – even local clients must authenticate
-
DM sessions are isolated per channel+peer (
dmScope: "per-channel-peer") – prevents context leakage if multiple people can DM you - Tool profile set to "messaging" – restricts available tools to safe ones
-
Filesystem workspace only – agent can only touch files inside
~/.openclaw/workspace - Exec is denied by default – but requires explicit approval if enabled
- Elevated tools disabled – no privileged execution without explicit opt-in
- WhatsApp DMs require pairing – unknown senders get a code, must be approved
- Groups require a mention – bot won't respond unless explicitly mentioned
This is your security floor. Everything else builds on it.
DM Policies: Who Can Even Talk to Your Bot?
OpenClaw's first line of defense is the DM policy (dmPolicy). It controls inbound DMs before the message hits your agent.
The Four DM Policies
| Policy | Behavior | When to Use |
|---|---|---|
pairing (default) |
Unknown senders get a short code; bot ignores them until you approve | Personal assistant – you want control over who reaches you |
allowlist |
Unknown senders blocked; only pre-approved numbers/users can DM | You have a small, fixed set of contacts |
open |
Anyone can DM (public) | Only if you really want public access (rare) |
disabled |
DMs disabled entirely | You only use groups or don't need DMs |
My recommendation: stick with pairing for personal use. It's the right balance of accessible but secure.
Approving Pairing Requests
When someone new DMs you, list pending requests:
openclaw pairing list whatsapp
Approve with the code they received:
openclaw pairing approve whatsapp ABC123
Approvals are saved to ~/.openclaw/credentials/whatsapp-allowFrom.json (or the channel equivalent). Don't share your pairing code with anyone—treat it like a one-time password.
Important: Pending requests are capped at 3 per channel by default. If someone spams your bot, they won't flood the queue.
Group Access: Mention Gating and Allowlists
Groups are a different beast. Even if your DMs are locked down, an open group could let hundreds of people trigger your bot.
The simplest group hardening is requireMention: true (as shown in the baseline). This means the bot only responds when someone explicitly @mentions it.
But you can also restrict which groups the bot even joins:
{
"channels": {
"telegram": {
"groups": {
"allowlist": ["-1001234567890", "-1009876543210"]
}
}
}
}
For Discord and Slack, you set guild/channel allowlists instead. The principle is the same: whitelist the specific group IDs you trust.
The dmScope Setting: Isolating Multi-User DMs
If you're the only person who DMs the bot, leave dmScope at its default ("main"). All your DMs share one session, which is convenient.
But if you run a shared inbox (say, a support email-to-chat bridge, or multiple team members can DM the bot), set:
{
"session": {
"dmScope": "per-channel-peer"
}
}
Now each sender gets their own isolated session. User A can't see User B's conversation history, and prompt injection from one user can't poison the session for others.
This is not hostile multi-tenant isolation. If users share the same Gateway host and config, they still share filesystem access. For true adversarial isolation, you need separate gateways per trust boundary. But dmScope prevents the most common cross-user leakage.
Tool Policy: Limiting What the Bot Can Do
Even with perfect DM controls, a trusted sender could still try to make the bot do something destructive. Tool policy is your second line of defense.
The Built-in Tool Profiles
OpenClaw ships with three profiles:
-
minimal– extremely restricted; mostly just messaging -
messaging– safe for chatbots; includesweb_fetch,web_search,browser(read-only) -
standard– enablesexec,fs.write, and other powerful tools
For a public-facing or multi-user bot, never use standard. Stick with messaging at most.
The baseline config I gave you explicitly denies:
-
group:automation– prevents cron/webhook abuse in groups -
group:runtime– blocks agent spawning in groups -
group:fs– no filesystem access from groups -
sessions_spawn/sessions_send– no agent-to-agent coordination (unless you need it)
Exec: The Most Dangerous Tool
system.run is remote code execution. Treat it with extreme caution.
The baseline sets:
"exec": { "security": "deny", "ask": "always" }
-
security: "deny"– exec is disabled by default at the tool policy level -
ask: "always"– even if you enable it for a specific agent, every exec call requires your explicit approval
Only enable exec for agents you fully control—personal assistants, not shared bots. And even then, keep ask: "always" enabled for interactive confirmation.
Filesystem Workspace Isolation
The setting fs.workspaceOnly: true (included in the baseline) restricts file operations to the agent's workspace directory (~/.openclaw/workspace by default). The bot can't wander into ~/Documents or /etc unless you explicitly disable this.
Pro tip: If you do need broader filesystem access, consider a dedicated agent with a custom workspace that's a symlink to a specific data directory, rather than turning off workspace-only globally.
Network Exposure: Don't Expose the Gateway Unnecessarily
The Gateway listens on a single port (default 18789) for both WebSocket and HTTP (Control UI). By default, it binds to loopback only—only processes on your machine can connect.
This is the safest setup. You access the Control UI at http://127.0.0.1:18789 and your local CLI tools connect automatically.
When You Need Remote Access
If you want to connect from your phone or another machine, don't just change bind to 0.0.0.0. That exposes the gateway to your LAN (or worse, the internet) with potentially weak auth.
Instead, use Tailscale Serve or SSH tunnels.
Tailscale Serve (Recommended)
Tailscale creates a secure mesh network. With Serve, the Gateway stays bound to loopback, but Tailscale exposes it over HTTPS on your tailnet with automatic identity-based auth.
{
"gateway": {
"tailscale": {
"mode": "serve"
}
}
}
Now you can reach the Control UI at https://GATEWAY-HOSTNAME.TS.NET from any device on your tailnet, and Tailscale handles authentication. No passwords, no token sharing.
Important: When mode: "serve" is set, OpenClaw enforces bind: "loopback" automatically. Don't try to override it.
SSH Tunnels (Alternative)
If you don't use Tailscale, set up an SSH reverse tunnel:
ssh -R 18789:localhost:18789 user@your-laptop
Then connect your remote client to localhost:18789 on the SSH server. The gateway never sees the public internet.
Never Expose Without Auth
If you must bind to a non-loopback interface (LAN access), always set a strong gateway.auth.token or gateway.auth.password. The default onboarding generates a random token, but double-check it's set and not the empty string.
Also, firewall the port. On Linux with UFW:
sudo ufw allow from 192.168.1.0/24 to any port 18789
Only your local network can reach it.
Browser Control: A Separate Attack Surface
OpenClaw's browser automation is powerful—but it's also a full Chrome instance that can navigate arbitrary sites, take screenshots, and interact with pages.
The browser tool uses a dedicated Chrome/Chromium installation managed by OpenClaw. The browser can be controlled remotely via the Control UI or the browser tool.
Security considerations:
- Browser control is operator-only by default. If your gateway auth is solid, only approved sessions can invoke
browser. - The browser runs with its own profile. Don't sign into Chrome with your personal Google account if you're using the browser from shared agents. Use a dedicated, throwaway profile for automation.
- The browser can access your local network. Treat it like any other remote execution surface.
- If you enable remote nodes (iOS/Android), browser control could theoretically be triggered from those devices if they're paired and in the same session. That's operator-level access, so keep node pairing under control.
My practice: I only enable browser for my personal agent, never for any agent that might receive messages from untrusted senders. And I keep the Chrome profile isolated—no logged-in accounts, no saved passwords.
The openclaw security audit Command: Your Best Friend
OpenClaw ships with a built-in security auditor. Run it regularly, especially after config changes:
openclaw security audit # normal check
openclaw security audit --deep # live probe (may be noisy)
openclaw security audit --fix # auto-fix file perms, etc.
openclaw security audit --json # machine-readable output
The auditor checks:
- Inbound access – DM policies, group policies, allowlists
- Tool blast radius – elevated tools, open groups with tool access
- Network exposure – bind mode, auth, Tailscale Funnel
- Browser control – remote exposure, relay ports
-
Filesystem hygiene – permissions on
~/.openclaw - Plugins – untrusted extension loading
- Model hygiene – warns if you're using a weak model for tool-enabled agents
Treat audit findings as a prioritized todo list. Critical issues (public exposure, world-readable config) get fixed immediately. Warnings (mDNS full mode, missing token) get evaluated and either fixed or documented as acceptable risk.
Common Audit Findings and How to Fix Them
| Finding | Severity | Fix |
|---|---|---|
fs.config.perms_world_readable |
critical | chmod 600 ~/.openclaw/openclaw.json |
gateway.bind_no_auth |
critical | Set gateway.auth.token or switch to bind: "loopback"
|
gateway.tailscale_funnel |
critical | Set gateway.tailscale.mode: "serve" or "off" (Funnel is public exposure) |
gateway.control_ui.allowed_origins_required |
critical | If UI is on non-loopback, set gateway.controlUi.allowedOrigins or use localhost
|
security.exposure.open_groups_with_elevated |
critical | Enable requireMention or restrict group allowlist |
discovery.mdns_full_mode |
warn | Set discovery.mdns.mode: "minimal"
|
tools.exec.host_sandbox_no_sandbox_defaults |
warn | Explicitly set agents.defaults.sandbox.mode: "enabled" if using exec |
Shared Inboxes: When More Than One Person Can DM the Bot
Maybe you have a team Slack where anyone can DM the OpenClaw bot. Or you've set up a support mailbox that forwards to chat. That's a shared inbox scenario.
Hardening checklist for shared inboxes:
-
Set
session.dmScope: "per-channel-peer"– isolates each sender's context -
Keep
dmPolicy: "pairing"or strict allowlists – don't useopen - Never combine shared DMs with broad tool access – the bot should have minimal tools
- Run a separate gateway if the users are adversarial or have different trust levels
Remember: in a shared inbox, any user can try to prompt-inject the bot. If that bot has exec access to your filesystem, they might exfiltrate data. Keep shared bots on a dedicated machine/VM with no access to personal accounts or sensitive files.
The Control UI: Secure Access to the Dashboard
The Control UI (http://127.0.0.1:18789/) is how you manage sessions, view logs, and tweak config. It needs to be protected.
- If you access it only on
localhost, you're fine. - If you need remote access, use Tailscale Serve (preferred) or a reverse proxy with authentication.
- Never expose the Control UI to the public internet without a strong password or token.
- Set
gateway.controlUi.allowedOriginsif you're accessing from a different origin via reverse proxy. - Avoid
gateway.controlUi.dangerouslyDisableDeviceAuth– that disables a critical check.
Recap: The Security Mindset
OpenClaw is powerful because it connects AI reasoning to real-world actions. That power demands care.
Core principles:
- Start closed, open selectively – default-deny everything, then add access as needed
- Identity first – lock down DMs and groups with pairing/allowlists
- Scope next – tool profiles, sandboxing, filesystem limits
- Assume the model can be manipulated – design so injection has minimal blast radius
-
Run
openclaw security auditregularly – catch drift early - Separate trust boundaries with separate gateways – one gateway per user/team/role
This isn't about making OpenClaw "unhackable." It's about making deliberate choices so that the everyday operation—chatting with your assistant, letting it read a webpage, running a safe tool—happens inside a well-understood boundary. And when you need to cross that boundary (exec a command, open a port, allow a new sender), you do it consciously, with an audit trail and a plan to roll back.
What's Your Setup?
I'm curious: how have you secured your OpenClaw gateway? What trade-offs did you make for convenience vs. safety? Drop a comment below—I'm always learning from other deployments.
P.S. The openclaw security audit command is your best friend. Seriously. Run it tonight.
Top comments (0)