|
| 1 | +# OpenClaw Security Self-Audit Guide |
| 2 | +# Source: Attaché (https://docs.attache.dev/security) |
| 3 | +# Version: 2026-03-19 |
| 4 | +# License: Apache 2.0 |
| 5 | +# |
| 6 | +# This file is designed to be read by an OpenClaw agent to audit its own |
| 7 | +# deployment. Feed it to your agent and ask: "Read this file and audit |
| 8 | +# my configuration against these best practices." |
| 9 | +# |
| 10 | +# The agent should have access to its own openclaw.json config file |
| 11 | +# (typically at ~/.openclaw/openclaw.json) and be able to run |
| 12 | +# `openclaw --version` and `openclaw security audit`. |
| 13 | + |
| 14 | +--- |
| 15 | + |
| 16 | +## How to use this file |
| 17 | + |
| 18 | +You are an OpenClaw agent. This file describes security best practices for |
| 19 | +your deployment. Read your own configuration file at ~/.openclaw/openclaw.json |
| 20 | +and check each item below. Report findings as PASS, WARN, or FAIL with |
| 21 | +specific remediation steps. |
| 22 | + |
| 23 | +Run these commands to gather your configuration: |
| 24 | +- `openclaw --version` (check version) |
| 25 | +- `cat ~/.openclaw/openclaw.json` (read config — redact tokens in output) |
| 26 | +- `openclaw security audit --json` (built-in audit) |
| 27 | +- `lsof -i -nP | grep ESTABLISHED` (network connections) |
| 28 | +- `ls ~/.ssh/authorized_keys` (SSH keys) |
| 29 | +- `crontab -l` (cron jobs) |
| 30 | +- `ls ~/Library/LaunchAgents/` (macOS LaunchAgents) |
| 31 | + |
| 32 | +--- |
| 33 | + |
| 34 | +## 1. Version and Patching |
| 35 | + |
| 36 | +CRITICAL: Check `openclaw --version` |
| 37 | + |
| 38 | +- FAIL if version < 2026.3.12 (multiple unpatched CVEs) |
| 39 | +- WARN if version < latest stable (check https://github.com/openclaw/openclaw/releases) |
| 40 | +- Known vulnerable versions: |
| 41 | + - < 2026.1.29: CVE-2026-25253 (auth token exfiltration via crafted URL, CVSS 8.8) |
| 42 | + - < 2026.2.23: CVE-2026-22175 (exec allowlist bypass via busybox/toybox, CVSS 7.1) |
| 43 | + - < 2026.2.26: Advisory: DM-paired senders authorized in group contexts |
| 44 | + - < 2026.3.11: Advisory: WebSocket origin bypass in trusted-proxy auth mode (Critical) |
| 45 | + - < 2026.3.11: Advisory: Exec allowlist glob pattern `?` crosses directory boundaries |
| 46 | + - < 2026.3.12: Advisory: Setup/pairing codes embed long-lived gateway token |
| 47 | + |
| 48 | +Remediation: `npm update -g openclaw && openclaw gateway restart` |
| 49 | + |
| 50 | +--- |
| 51 | + |
| 52 | +## 2. Gateway Configuration |
| 53 | + |
| 54 | +### 2a. Binding |
| 55 | +Check: `gateway.bind` in openclaw.json |
| 56 | + |
| 57 | +- PASS if "loopback" or "127.0.0.1" |
| 58 | +- FAIL if "0.0.0.0" or missing (defaults to all interfaces on some versions) |
| 59 | +- FAIL if any public IP address |
| 60 | +- Context: 135,000-220,000+ OpenClaw instances found exposed to the internet |
| 61 | + |
| 62 | +### 2b. Auth mode |
| 63 | +Check: `gateway.auth.mode` in openclaw.json |
| 64 | + |
| 65 | +- PASS if "token" |
| 66 | +- FAIL if "trusted-proxy" (attack surface for origin bypass advisory) |
| 67 | +- WARN if auth section is missing entirely |
| 68 | + |
| 69 | +### 2c. Tailscale mode |
| 70 | +Check: `gateway.tailscale.mode` in openclaw.json (if Tailscale is configured) |
| 71 | + |
| 72 | +- PASS if "serve" |
| 73 | +- FAIL if "funnel" (exposes gateway to public internet via Tailscale ingress) |
| 74 | + |
| 75 | +--- |
| 76 | + |
| 77 | +## 3. Exec Security |
| 78 | + |
| 79 | +CRITICAL: Check `exec.security` in openclaw.json |
| 80 | + |
| 81 | +- PASS if "allowlist" or "ask" |
| 82 | +- FAIL if "full" (any prompt injection gives attacker arbitrary command execution) |
| 83 | +- WARN if allowlist contains broad patterns like `*`, `?`, or shell wrappers (busybox, toybox, sh, bash) |
| 84 | +- WARN if `sudo` is on the allowlist |
| 85 | +- WARN if `op` (1Password CLI) is directly on the allowlist without a proxy |
| 86 | + |
| 87 | +Context: With exec.security: "full", there is no technical barrier between a |
| 88 | +prompt injection and arbitrary command execution under the agent's OS user. |
| 89 | +This is the single most impactful security setting. |
| 90 | + |
| 91 | +Remediation: Switch to "allowlist" mode. Audit which commands your agent |
| 92 | +actually uses by reviewing session logs, then build an explicit allowlist. |
| 93 | + |
| 94 | +--- |
| 95 | + |
| 96 | +## 4. Channel Policies |
| 97 | + |
| 98 | +### 4a. Slack |
| 99 | +Check: `channels.slack.groupPolicy` and per-account settings |
| 100 | + |
| 101 | +- PASS if "allowlist" or "pairing" |
| 102 | +- WARN if "open" (anyone in any channel can trigger agent tools) |
| 103 | +- Check per-account overrides: `channels.slack.accounts.*.groupPolicy` |
| 104 | +- Check per-channel: `channels.slack.accounts.*.channels.*.requireMention` |
| 105 | +- WARN if any channel has requireMention: false in a shared workspace |
| 106 | + |
| 107 | +### 4b. Discord |
| 108 | +Check: `channels.discord.groupPolicy` and guild settings |
| 109 | + |
| 110 | +- PASS if "allowlist" |
| 111 | +- WARN if individual guilds have allowlist overrides but top-level is "open" |
| 112 | +- Check: `channels.discord.guilds.*.requireMention` |
| 113 | + |
| 114 | +### 4c. General principle |
| 115 | +All senders to one agent share the same delegated tool authority. |
| 116 | +If the agent has exec access, everyone in a shared channel can trigger exec. |
| 117 | +There is no per-sender permission scoping within a single agent. |
| 118 | + |
| 119 | +WARN if any channel with groupPolicy "open" has an agent with exec access. |
| 120 | + |
| 121 | +--- |
| 122 | + |
| 123 | +## 5. Credential Management |
| 124 | + |
| 125 | +### 5a. Plaintext secrets in config |
| 126 | +Check openclaw.json for any fields that look like API keys or tokens |
| 127 | + |
| 128 | +- FAIL if API keys appear as plaintext values in the config file |
| 129 | +- Specifically check: tools.web.search.apiKey, memorySearch.apiKey, |
| 130 | + and any custom tool configurations |
| 131 | +- WARN if bot tokens or app tokens are in plaintext (even though they must be) |
| 132 | +- Remediation: Move secrets to 1Password and reference via `op read` |
| 133 | + |
| 134 | +### 5b. 1Password vault scoping |
| 135 | +If using 1Password: |
| 136 | + |
| 137 | +- WARN if the service account token has access to personal vaults |
| 138 | +- Best practice: Dedicated "Agent Credentials" vault with only what the agent needs |
| 139 | +- WARN if the agent can run `op` directly (should use a secrets proxy) |
| 140 | + |
| 141 | +### 5c. GitHub tokens |
| 142 | +Check for GitHub authentication configuration |
| 143 | + |
| 144 | +- PASS if using GitHub App with installation tokens (short-lived, scoped) |
| 145 | +- WARN if using fine-grained PAT (acceptable but check expiration) |
| 146 | +- FAIL if using classic PAT (broad scope, no repository restrictions) |
| 147 | + |
| 148 | +### 5d. Gateway token rotation |
| 149 | +Check: `gateway.auth.token` age |
| 150 | + |
| 151 | +- WARN if the gateway token has not been rotated since upgrading past 2026.3.12 |
| 152 | + (setup codes in earlier versions contained the long-lived token) |
| 153 | +- Remediation: `openclaw config set gateway.auth.token "$(openssl rand -hex 32)"` |
| 154 | + |
| 155 | +--- |
| 156 | + |
| 157 | +## 6. Network Posture |
| 158 | + |
| 159 | +### 6a. Inbound access |
| 160 | +- PASS if gateway only accessible via localhost and Tailscale |
| 161 | +- FAIL if gateway responds to connections from LAN IP |
| 162 | +- Test: From another machine, `curl http://<mac-lan-ip>:18789/` should FAIL |
| 163 | + |
| 164 | +### 6b. Outbound access |
| 165 | +- WARN if no outbound network restrictions are configured |
| 166 | +- Best practice: DNS-level blocking of known exfiltration endpoints |
| 167 | + or macOS pf firewall rules limiting which domains the agent can reach |
| 168 | +- Check for unexpected outbound connections: |
| 169 | + `lsof -i -nP | grep ESTABLISHED | grep -v "localhost|127.0.0.1|::1|tailscale|100.64|100.100"` |
| 170 | + |
| 171 | +--- |
| 172 | + |
| 173 | +## 7. Agent Isolation (Multiplayer) |
| 174 | + |
| 175 | +If multiple agents or shared channels are in use: |
| 176 | + |
| 177 | +### 7a. Personal vs team agent separation |
| 178 | +- WARN if a single agent with full tool access operates in both DMs and shared channels |
| 179 | +- Best practice: Personal agent (DMs, full tools) + team agent (shared channels, restricted tools) |
| 180 | + |
| 181 | +### 7b. Memory isolation |
| 182 | +- FAIL if a team-facing agent has access to personal memory files |
| 183 | + (MEMORY.md, SOUL.md, USER.md, daily notes) |
| 184 | +- Best practice: Separate workspace directories for personal and team agents |
| 185 | + |
| 186 | +### 7c. Tool restrictions for shared agents |
| 187 | +Check agent-specific tool deny lists in openclaw.json |
| 188 | + |
| 189 | +- WARN if a shared-channel agent has exec access |
| 190 | +- WARN if a shared-channel agent has browser access |
| 191 | +- WARN if a shared-channel agent can spawn sub-agents |
| 192 | +- Best practice: Team agents should deny exec, browser, sessions_spawn, tts, nodes |
| 193 | + |
| 194 | +--- |
| 195 | + |
| 196 | +## 8. Persistence and IOC Checks |
| 197 | + |
| 198 | +### 8a. SSH keys |
| 199 | +Check: `cat ~/.ssh/authorized_keys` |
| 200 | + |
| 201 | +- WARN if any unrecognized keys are present |
| 202 | +- Each key should map to a known device |
| 203 | + |
| 204 | +### 8b. Scheduled tasks |
| 205 | +Check: `crontab -l` and `ls ~/Library/LaunchAgents/` |
| 206 | + |
| 207 | +- Expected LaunchAgents: ai.openclaw.gateway.plist (and optionally github-webhooks) |
| 208 | +- WARN if any unexpected LaunchAgents or cron entries exist |
| 209 | + |
| 210 | +### 8c. Suspicious exec patterns in logs |
| 211 | +Search recent gateway logs for indicators of compromise: |
| 212 | + |
| 213 | +- `grep -i "busybox\|toybox" ~/.openclaw/logs/gateway.err.log` (CVE-2026-22175) |
| 214 | +- `grep -iE "/dev/tcp|nc -e|mkfifo|ncat |netcat " ~/.openclaw/logs/gateway.err.log` (reverse shells) |
| 215 | +- `grep -iE "curl.*(pastebin|ngrok|webhook\.site|pipedream|requestbin)" ~/.openclaw/logs/gateway.err.log` (exfiltration) |
| 216 | +- `grep -iE "base64 -d" ~/.openclaw/logs/gateway.err.log` (encoded payloads) |
| 217 | + |
| 218 | +- FAIL if any of these patterns are found (investigate immediately) |
| 219 | + |
| 220 | +### 8d. Config audit trail |
| 221 | +Check: `tail -20 ~/.openclaw/logs/config-audit.jsonl` |
| 222 | + |
| 223 | +- All entries should trace to intentional `openclaw config set` commands |
| 224 | +- WARN if any entries have unexpected sources or suspicious patterns |
| 225 | + |
| 226 | +--- |
| 227 | + |
| 228 | +## 9. LLM Provider Configuration |
| 229 | + |
| 230 | +### 9a. Subscription tier |
| 231 | +- FAIL if using consumer-tier subscriptions (Claude Free, ChatGPT Free/Plus) |
| 232 | + for any work involving client or sensitive data |
| 233 | +- PASS if using API tier (Anthropic or OpenAI) — no training, short retention |
| 234 | +- Best practice for sensitive clients: Anthropic Zero Data Retention agreement |
| 235 | + or AWS Bedrock (model provider never sees prompts) |
| 236 | + |
| 237 | +### 9b. Provider data handling (verify periodically) |
| 238 | +- Anthropic API: No training. 7-day retention (reduced Sept 2025). ZDR available. |
| 239 | +- OpenAI API: No training (since March 2023). 30-day abuse monitoring. |
| 240 | +- AWS Bedrock: No storage, no logging, provider has no access. |
| 241 | +- Google Vertex AI: Per GCP data processing terms. |
| 242 | + |
| 243 | +--- |
| 244 | + |
| 245 | +## 10. Log Management |
| 246 | + |
| 247 | +### 10a. Log rotation |
| 248 | +- WARN if gateway.err.log exceeds 1GB without rotation configured |
| 249 | +- Best practice: Configure logrotate or launchd-based rotation |
| 250 | +- Retain at least 90 days of logs for forensic purposes |
| 251 | + |
| 252 | +### 10b. Log access |
| 253 | +- WARN if log files are world-readable |
| 254 | +- Best practice: Restrict log file permissions to the agent's OS user |
| 255 | + |
| 256 | +--- |
| 257 | + |
| 258 | +## Scoring |
| 259 | + |
| 260 | +After checking all items, calculate a score: |
| 261 | + |
| 262 | +- Each FAIL = 0 points |
| 263 | +- Each WARN = 1 point |
| 264 | +- Each PASS = 2 points |
| 265 | + |
| 266 | +Sections 1-4 are weighted 2x (most impactful security controls). |
| 267 | + |
| 268 | +Report the total score, the maximum possible score, and a percentage. |
| 269 | +List all FAIL items first with specific remediation commands. |
| 270 | +List WARN items second with recommendations. |
| 271 | + |
| 272 | +### Risk rating: |
| 273 | +- 90-100%: Strong security posture |
| 274 | +- 70-89%: Acceptable with noted improvements |
| 275 | +- 50-69%: Significant gaps — address FAIL items immediately |
| 276 | +- Below 50%: Critical — stop and harden before continued use |
| 277 | + |
| 278 | +--- |
| 279 | + |
| 280 | +## References |
| 281 | + |
| 282 | +- Attaché Security Docs: https://docs.attache.dev/security |
| 283 | +- OpenClaw Security: https://docs.openclaw.ai/gateway/security |
| 284 | +- OWASP Top 10 for Agentic Applications: https://genai.owasp.org/resource/owasp-top-10-for-agentic-applications-for-2026/ |
| 285 | +- NVIDIA NemoClaw: https://nvidianews.nvidia.com/news/nvidia-announces-nemoclaw |
| 286 | +- Auth0 OpenClaw Security Guide: https://auth0.com/blog/five-step-guide-securing-moltbot-ai-agent/ |
0 commit comments