I wrote previously about the five most common security mistakes in OpenClaw deployments. That article covered the surface. This one goes deeper.
OpenClaw is not a chatbot. It is an autonomous agent that can read and write files, execute commands, call APIs, send messages, and modify infrastructure. When you give it credentials to Stripe, Jira, GitLab, and your production database, you are handing a piece of software the keys to your business. It will use those keys 24 hours a day, unattended, processing instructions from multiple sources — including sources you don’t fully control.
That last part is what makes security non-negotiable. The agent doesn’t just respond to you. It responds to Discord messages, webhook events, cron schedules, and sub-agent chains. Every one of those input channels is a potential attack surface. Every one of those credentials is a potential exfiltration target.
Getting the deployment working is the easy part. Getting it safe requires making 11 specific architectural decisions correctly. Miss any of them, and you have a production system with a hole in it — one that an attacker, a malicious prompt, or even the agent itself can exploit.
Here they are, in the order I implement them for every client deployment.
Network & Access Layer
1. Zero Public Ports
DECISION 01 / 11Automated bots scan every public IP address on the internet, constantly. Port scanners hit EC2 instances within minutes of launch. Any open port — SSH, HTTP, your gateway UI — becomes a target for brute-force attacks, credential stuffing, and exploit attempts. A single exposed port turns your agent into a publicly addressable service.
Zero inbound rules in the EC2 security group. No SSH. No HTTPS. No port 22, 443, 8080, or anything else. The instance is invisible to the public internet. All access goes through Tailscale — a WireGuard-based mesh VPN that creates a private, encrypted network between your devices. The machine is only reachable by devices that are cryptographically authenticated on your Tailnet.
This is the single most important decision on the list. Everything else is defense-in-depth. This is the wall. Most self-deployed OpenClaw instances I’ve audited have at least port 22 open with password authentication enabled. That’s an invitation. The full guide covers the exact security group configuration and Tailscale setup, but the principle is simple: if the internet can’t see your machine, it can’t attack your machine.
2. Gateway Binds to “lan” Not “loopback”
DECISION 02 / 11This one is subtle and catches nearly everyone. By default, you might think binding the OpenClaw gateway to loopback (127.0.0.1) is the safest option — the classic “only accept local connections” pattern. But inside a Docker container, loopback means the container’s loopback interface. Docker’s port forwarding can’t reach it. You end up with a gateway that’s running but completely inaccessible, or worse — you bind to 0.0.0.0 to “fix” it and accidentally expose the gateway to every network interface.
Bind the gateway to “lan” — which binds to the container’s internal network interface — and then map that port to 127.0.0.1 on the host using Docker’s port mapping (127.0.0.1:8080:8080). This gives you reachability through Docker networking while ensuring the port is never exposed on the host’s public interface. Combined with Decision 1 (zero public ports), the gateway is only reachable through your Tailscale tunnel.
This is the kind of decision that looks like a minor networking detail. In practice, I’ve seen it cause either complete deployment failures or accidental public exposure. Both are bad. The correct pattern is one line in your Docker Compose file and one setting in your gateway config, but you have to know which line and which setting.
3. Token Auth + allowTailscale
DECISION 03 / 11Even on a private network, you need authentication. Without it, anyone on your Tailnet — including shared devices, guest users, or compromised endpoints — can access the gateway and issue commands to the agent. A single auth layer is also fragile: if a token leaks, you’re fully exposed.
Two independent auth layers. Token auth for programmatic access: API calls, scripts, cron triggers, and integrations all authenticate with a bearer token. allowTailscale for UI access: the gateway accepts connections from authenticated Tailscale devices, using WireGuard’s cryptographic device identity as the trust signal. An attacker needs both a valid Tailscale device identity and a valid token to get anywhere.
The layered approach matters because the two auth methods cover different threat models. Token auth protects against unauthorized API access. Tailscale identity protects against unauthorized UI access and ensures every connection comes from a known, hardware-bound device. I cover the exact gateway auth configuration — including scope management — in the full guide.
Agent Permission Boundaries
4. Passphrase on Workspace Scripts + Secret File Isolation
DECISION 04 / 11Prompt injection is the top threat to any AI agent. A malicious instruction embedded in a Jira ticket, a Discord message, a code comment, or a web page can instruct the agent to exfiltrate credentials, run destructive commands, or modify its own configuration. If your workspace scripts — the ones that access Stripe, GitLab, or Google Workspace — can be invoked by the agent without verification, a single injected prompt can trigger them.
Every sensitive workspace script requires a passphrase passed via the --auth flag. The passphrase is stored in a mounted secrets file at a known path — not in environment variables, not in the SOUL.md, not anywhere the agent can read through normal tool use. The critical constraint: the passphrase must come from the user’s message, not from external content. The agent is instructed to never auto-fill it from memory or context. This means a prompt injection can tell the agent to run a script, but it can’t supply the passphrase.
This is one of the more nuanced decisions because it requires thinking about the agent’s cognition as a security boundary. The passphrase isn’t just a string check — it’s a provenance check. The agent knows the passphrase exists. It knows where it’s stored. But it’s instructed to only accept it when a verified human provides it in a direct message. That instruction, embedded in the SOUL.md, is the actual defense. The file isolation is the fallback.
5. safeBins: No Code Executors
DECISION 05 / 11An agent with access to node, python3, npm, or docker can execute arbitrary code. This is by design — it’s how the agent runs builds, tests, and scripts. But it’s also how an injected prompt turns into a reverse shell, a cryptocurrency miner, or a data exfiltration pipeline. Any tool that can execute user-supplied code is a privilege escalation vector.
The safeBins configuration whitelists exactly which executables the agent can run without approval. Safe tools — ls, git, grep, cat, curl — are allowed. Code execution tools — node, npm, python3, docker, dig, nslookup, ngrok — are blocked and require explicit human approval before each use. The agent can still use them when you say so, but it can’t be tricked into using them by injected content.
The approval requirement is the key. It doesn’t remove capability — it adds a human checkpoint. When the agent legitimately needs to run npm install or execute a Python script, you approve it. When a poisoned Jira ticket tries to make the agent run node -e "require(’child_process’)...", the execution is blocked and you’re notified. The guide covers the exact safeBins list I use in production.
6. Deny Gateway Tool
DECISION 06 / 11OpenClaw agents have access to a gateway management tool that can modify auth settings, permissions, and other configuration. If the agent can modify its own permission boundaries, then any successful prompt injection can escalate itself — first disable safeBins, then execute arbitrary code, then exfiltrate credentials. A self-modifying agent is an uncontainable agent.
Deny the gateway tool entirely. The agent cannot read or modify its own auth config, its own permission settings, or its own gateway configuration. Period. Configuration changes require SSH access to the host machine — which, per Decision 1, requires Tailscale access, which requires a cryptographically authenticated device.
This is a simple decision with outsized impact. Without it, every other permission boundary is soft — the agent could, in theory, remove any restriction you’ve put in place. With it, the permission boundaries are enforced by the infrastructure, not by the agent’s willingness to follow instructions.
7. Elevated Disabled
DECISION 07 / 11An agent running as root can install packages, modify system files, change network configurations, and access any file on the filesystem. Even if you trust the agent’s judgment, root access means a single mistake — or a single injected instruction — can modify the container’s runtime environment, install backdoors, or tamper with security controls.
The container runs as uid 1000 (non-root). Elevated mode is disabled. No sudo, no su, no capability escalation. The agent can read and write files in its workspace and execute approved tools — nothing more. System-level operations require host access through Tailscale SSH.
This is standard container security practice, but it’s remarkable how many OpenClaw deployments skip it. The default Docker behavior runs containers as root. You have to explicitly configure non-root execution in your Dockerfile and Compose file. The guide covers the exact user configuration, including file permission patterns that avoid the common “permission denied” errors that make people give up and switch back to root.
Get the Full Security Hardening Checklist
All 11 decisions in a printable, step-by-step checklist you can follow during deployment. Includes the exact configuration values, file paths, and verification commands.
Behavioral Guardrails
8. Loop Detection
DECISION 08 / 11Autonomous agents can get stuck. A polling loop that checks a build status every two seconds. A ping-pong pattern where two sub-agents keep calling each other. A retry loop that hammers a failing API endpoint indefinitely. These patterns burn through your API budget, consume compute resources, and can trigger rate limits that affect your production systems. In the worst case, a looping agent with Stripe access could create hundreds of duplicate charges before anyone notices.
OpenClaw’s loop detection system monitors for repeated tool calls, polling patterns, and recursive sub-agent invocations. It escalates through three stages: warning (the agent is told it’s looping and asked to stop), stop (the current task is terminated), and kill (the agent process is forcefully ended). You configure the thresholds — how many repeated calls trigger a warning, how many trigger a stop — based on your tolerance for runaway behavior.
I’ve seen loop patterns cost hundreds of dollars in API credits in under an hour. The loop detection configuration is one of those settings that feels optional until the day it saves you. The production guide includes the threshold values I use and the reasoning behind them.
9. DM Policy: Pairing
DECISION 09 / 11If your agent responds to any Discord user who messages it, you have an open door. An attacker who finds your bot — or a random user who stumbles into your server — can issue commands, probe for information, attempt prompt injections, or simply waste your API budget. An agent that talks to strangers is an agent you don’t control.
Set the DM policy to pairing. New users must be explicitly approved before the agent will engage with them. Unknown contacts are ignored completely — not rejected, not given an error message, just silently ignored. You maintain an explicit allowlist of paired users. The agent only processes messages from known, verified identities.
This is especially important for Discord-based deployments where your bot might be in a server with people beyond your immediate team. The pairing model means you consciously decide who gets access. Everyone else gets nothing — not even an acknowledgment that the bot exists.
10. ClawHub Skills: Build Your Own
DECISION 10 / 11ClawHub is a community repository of skills — plugins that extend what your agent can do. Some are excellent. Some are poorly written. And some could contain malicious instructions that exfiltrate data, modify agent behavior, or introduce vulnerabilities. A skill is essentially a set of instructions and tools that run with the agent’s full permission set. Installing a random skill is like running curl | bash from an untrusted source.
Don’t install third-party skills you haven’t audited. Build your own. OpenClaw’s skill format is straightforward — a SKILL.md file with instructions and optional tool definitions. Custom skills tailored to your workflows are more useful and more secure than generic community skills. You control every instruction the agent follows.
I build custom skills for every client deployment. A PM scoping skill that follows your specific ticket format. A bug triage skill that knows your codebase structure. A deployment skill that follows your CI/CD pipeline. These are more valuable than anything on ClawHub because they’re built for your team, and they’re more secure because you wrote every line.
Credential Architecture
11. Credential Isolation + Safe-Fetch
DECISION 11 / 11This is the big one. Your agent has API keys for Stripe, GitLab, Jira, Google Workspace, Datadog, and whatever else you’ve integrated. If those credentials are stored in environment variables — the default pattern — any prompt injection that gets the agent to run env or printenv exfiltrates everything. One leaked Discord message containing a cleverly crafted instruction, and your Stripe key is in someone else’s hands.
Three layers of defense, working together. Layer 1: Per-file secrets. Credentials are stored in individual files mounted read-only into the container at /run/secrets/<name>, not as environment variables. The .env file contains only the handful of variables the gateway itself requires. Scripts use a readSecret() function that reads from the file at runtime. Layer 2: Safe-fetch. A wrapper around outbound HTTP requests that scans request bodies and headers for patterns that look like credentials — API key formats, token prefixes, base64-encoded secrets. If it detects a credential being sent to an unexpected destination, it blocks the request and logs it. Layer 3: SOUL.md rules. The agent’s base instructions explicitly prohibit running env, printenv, set, or any command that dumps the process environment. These are soft rules — a determined attacker could work around them — but combined with the first two layers, they add meaningful friction.
No single layer is sufficient on its own. Environment inspection commands can be aliased or obfuscated to bypass SOUL.md rules. File-based secrets can still be read if the agent is tricked into running cat /run/secrets/stripe-key. Safe-fetch can be bypassed by encoding the credential differently. But all three together create a defense-in-depth that catches the vast majority of exfiltration attempts — automated and manual alike. I also run a daily audit script that scans agent logs for patterns that suggest credential access attempts.
The full guide covers the exact directory structure, Docker mount configuration, readSecret() implementation, and safe-fetch patterns I use in production. This is the most complex of the 11 decisions, and the one where getting the details right matters most.
Getting All 11 Right
Here’s what I want you to take away from this: none of these decisions are optional.
You can skip any one of them and your deployment will still work. The agent will boot. It will respond to messages. It will run your cron jobs and create your Jira tickets. But it will be doing all of that with a hole in its security posture — a hole that exists because you didn’t know it needed to be closed, or because you decided to come back to it later.
“Come back to it later” is how breaches happen.
The 11 decisions break down into a clear architecture:
- Decisions 1-3 make the agent invisible and authenticated — you can’t attack what you can’t reach
- Decisions 4-7 constrain what the agent can do — even if an attacker gets in, the blast radius is limited
- Decisions 8-10 control behavior and access — the agent only talks to approved people, only runs approved skills, and can’t get stuck in destructive loops
- Decision 11 protects the most valuable thing — your credentials — with three independent layers
Getting all 11 right is what separates a toy from a production system. It’s what separates an AI assistant from an AI liability. And it’s what separates the teams that deploy with confidence from the ones that deploy with crossed fingers.
I’ve deployed these exact configurations for clients across different industries, codebases, and team structures. The architecture is battle-tested. The decisions don’t change. What changes is the implementation details — which integrations you connect, which skills you build, which team members get access.
If you want to implement all 11 yourself, the production guide covers every detail. If you want it done for you — correctly, the first time, in days instead of weeks — that’s the service.