Hardening OpenClaw: Credentials, Tool Allowlists, and Who Gets to Talk to Your Agent
Why This Post Exists
A tweet made the rounds this week:
> *"There's a tension between privacy and capability with AI products. The more info you give, the more effective the tools are, but the larger the security blast radius grows. Nothing highlights this more than how people use and (don't) configure OpenClaw properly today."*
Ten impressions, but it nails the problem. Most people set up OpenClaw, hand the agent all their API keys, enable every tool — and don't think twice about it.
That's a problem. Not because OpenClaw is insecure by design, but because a poorly configured agent does the same thing as a poorly configured server: it becomes an attack surface.
This post covers the three layers we used to harden our 6-agent setup. No theory — concrete settings.
---
Layer 1: Storing Credentials Properly
This is the most common mistake, and the one with the worst consequences.
What most people do (wrong):
```yaml
# Directly in the openclaw config:
ANTHROPIC_API_KEY: sk-ant-api03-xxxxx
TELEGRAM_TOKEN: 8234567890:AAHxxxxx
```
The problem: this file usually lives at `~/.openclaw/config.yaml` or in the workspace directory. Infostealer malware targeting AI developer setups already knows these paths. They actively search for them.
What we do instead:
Option 1: .env file with strict permissions
```bash
# Create .env
touch /home/sam/.openclaw/workspace/.env
chmod 600 /home/sam/.openclaw/workspace/.env # Only owner can read
# Contents:
ANTHROPIC_API_KEY=sk-ant-...
TELEGRAM_TOKEN=123456:ABC...
```
In the OpenClaw configuration, reference the variable name — never paste the value directly.
Option 2: Spending limits as a safety net
Regardless of how you store keys: set spending limits with your LLM provider. In Anthropic, that's under *Usage Limits* in account settings. In OpenAI, it's under *Billing → Usage limits*.
If a key gets compromised, this caps the damage at €50 instead of €5,000.
Option 3: Regular key rotation
Rotate all API keys once a month. Painful? Yes. But significantly less painful than an unexpected four-figure bill.
---
Layer 2: Tool Allowlists — Agents Don't Need Everything
OpenClaw agents can use many tools by default: shell execution, browser control, web fetching, file access. That's convenient. But not every agent needs everything.
The principle of least privilege
Our coding agent Peter needs:
Our marketing agent Maya needs:
How we implement this
In each agent's SOUL.md, we explicitly define which tools are allowed and what's off-limits:
```markdown
Boundaries
```
This isn't a technical lock — it's an instruction. But combined with Docker volumes (which physically restrict access), it's effective. The agent doesn't even know /etc/ exists if it's not mounted into the volume.
Docker volumes as hard boundaries
```yaml
# docker-compose.yml
services:
maya:
image: openclaw/openclaw:latest
volumes:
- ./maya-workspace:/home/sam/.openclaw/workspace:rw
- ./content:/content:rw
# No access to host system outside these paths
```
The agent can write whatever it wants in its workspace directory — but it can't reach out of the container to touch /etc/passwd or other critical files.
---
Layer 3: Who's Allowed to Talk to Your Agent?
This is the most-forgotten layer. When you make an agent reachable via Telegram, Discord, or WhatsApp — who can actually send it commands?
The default problem
Many people set up a Telegram bot and assume "nobody knows the bot ID anyway." That's security through obscurity. Bot IDs aren't secret. If your bot token shows up anywhere (a commit, a screenshot, an error log), anyone can command your agent.
And your agent — with access to your API keys, your server, your files — will execute those commands.
Allowlist-based access control
OpenClaw supports channel configurations with sender filtering. Our configuration:
```yaml
channels:
telegram:
token: ${TELEGRAM_TOKEN}
allowedUsers:
- "123456789" # Dimitrios's user ID
- "987654321" # Sam's user ID
# Everything else is silently ignored
```
Any message from an unknown user ID: silently dropped. No "who are you?", no indication the bot exists.
Discord: roles instead of IDs
For Discord, we use role-based control:
```yaml
channels:
discord:
allowedRoles:
- "Team"
- "Admin"
# Without this role: no response
```
This means: even if someone finds the Discord server, they can't command the agent without the right role.
---
The Combined Result
Before this setup:
After this setup:
The effort: half a day. The result: our entire agent setup is now significantly more resilient against the most common attack vectors.
---
Going Further
The full playbook documents in chapters 7 and 8 exactly how we implemented isolation, access control, and credential management in our 6-agent setup — including the Docker Compose files and exact channel configurations.
Fully available in German too. 🇩🇪
Want to learn more?
Our playbook contains 18 detailed chapters — available in English and German.
Get the Playbook