Navigation: Main Guide | Security Audit Reference | CVEs/GHSAs | Issue #1796 | Medium Article | Post-merge Hardening | Open Issues | Ecosystem Threats | Model Comparison
Source:
src/cli/security-cli.ts:39-44,src/security/audit.ts:914-992,src/security/fix.ts:455-541The built-in security audit scans your local config, filesystem permissions, and channel policies for common misconfigurations. It does not scan source code for vulnerabilities.
| Command | Behavior |
|---|---|
openclaw security audit |
Read-only scan: 16 collector functions check config, filesystem, channels, models, plugins, hooks, gateway, browser. No network calls. |
openclaw security audit --deep |
Everything above + maybeProbeGateway() connects to gateway WebSocket (5 s timeout), verifies auth, adds gateway.probe_failed if unreachable. |
openclaw security audit --fix |
Runs fixSecurityFootguns() first, then full audit. Report reflects post-fix state. Also accepts --deep. |
openclaw security audit --json |
Any mode above with JSON output instead of formatted text. |
| # | Category | Check ID prefix | Severities | What it checks |
|---|---|---|---|---|
| 1 | Attack surface summary | summary.attack_surface |
info | Counts open groups, elevated tools, hooks, browser control |
| 2 | Synced folders | fs.synced_dir |
warn | State/config in iCloud, Dropbox, OneDrive, Google Drive |
| 3 | Filesystem permissions | fs.state_dir.*, fs.config.*, fs.credentials_dir.*, fs.auth_profiles.*, fs.sessions_store.*, fs.log_file.* |
critical/warn | World/group-writable dirs, world/group-readable config/credentials, symlink detection |
| 4 | Config include files | fs.config_include.* |
critical/warn | Permissions on included config files |
| 5 | Gateway configuration | gateway.bind_no_auth, gateway.loopback_no_auth, gateway.tailscale_funnel, gateway.tailscale_serve, gateway.control_ui.*, gateway.token_too_short, gateway.trusted_proxies_missing |
critical/warn/info | Non-loopback bind without auth, Tailscale Funnel public exposure, Control UI insecure auth/device auth, token length, missing trusted proxy |
| 6 | Browser control | browser.remote_cdp_http, browser.control_invalid_config |
warn | Remote CDP over plain HTTP, invalid CDP config |
| 7 | Logging | logging.redact_off |
warn | redactSensitive="off" leaks secrets in tool summaries |
| 8 | Elevated tools | tools.elevated.allowFrom.*.wildcard, tools.elevated.allowFrom.*.large |
critical/warn | Wildcard "*" in elevated allowlist, oversized allowlist (>25 entries) |
| 9 | Hooks hardening | hooks.path_root, hooks.token_too_short, hooks.token_reuse_gateway_token |
critical/warn | Hooks base path is "/", short token (<24 chars), token reuses gateway token |
| 10 | Model hygiene | models.legacy, models.weak_tier, models.small_params |
critical/warn | Legacy models (GPT-3.5, Claude 2), weak tier (Haiku, pre-GPT-5), small models (<=300B params) without sandboxing exposed to web tools |
| 11 | Config secrets | config.secrets.gateway_password_in_config, config.secrets.hooks_token_in_config |
warn/info | Secrets stored in config file instead of env vars |
| 12 | Plugins/extensions | plugins.extensions_no_allowlist |
critical | Extensions present but plugins.allow not configured (especially with skill commands exposed) |
| 13 | Channel security | channels.discord.*, channels.slack.*, channels.telegram.*, channels.*.dm.* |
critical/warn/info | DM policies (open/disabled/scoped), group policies, slash command restrictions, sender allowlists, multi-user DM session isolation |
| 14 | Exposure matrix | security.exposure.open_groups_with_elevated |
critical | Dangerous combination: open groupPolicy + elevated tools enabled |
| — | Deep probe | gateway.probe_failed |
warn | --deep only: gateway WebSocket unreachable or auth failed |
Config changes (applyConfigFixes, line 277):
logging.redactSensitive:"off"→"tools"(prevents secrets in tool summaries)groupPolicy:"open"→"allowlist"for all 7 supported channels (telegram, whatsapp, discord, signal, imessage, slack, msteams), including per-account overrides- WhatsApp
groupAllowFrom: populated from pairing store when policy flipped (so existing paired contacts still work)
Filesystem hardening (chmod/icacls):
| Target | Mode | Purpose |
|---|---|---|
~/.openclaw/ (state dir) |
700 |
User-only access to all state |
| Config file | 600 |
User-only read/write (contains tokens) |
| Config include files | 600 |
Same protection for split configs |
~/.openclaw/credentials/ |
700 |
OAuth credential directory |
credentials/*.json |
600 |
Individual credential files |
agents/<id>/agent/ |
700 |
Per-agent directory |
agents/<id>/agent/auth-profiles.json |
600 |
API keys and tokens |
agents/<id>/sessions/ |
700 |
Session transcript directory |
agents/<id>/sessions/sessions.json |
600 |
Session metadata |
On Windows: uses icacls ACL reset instead of chmod.
--fix skips symlinks, missing paths, and already-correct permissions (safe + idempotent).
The audit is a configuration and filesystem hardening tool. It detects misconfigurations but not code-level vulnerabilities.
| Issue | Severity | What the audit catches | Check ID |
|---|---|---|---|
| #9065 | LOW | ~/.openclaw group-writable after sudo install |
fs.state_dir.perms_group_writable (--fix applies chmod 700) |
| #7862 | MEDIUM | Session transcripts 644 instead of 600 | fs.sessions_store.perms_readable (--fix applies chmod 600) |
| #9627 | HIGH | Config secrets exposed in JSON | config.secrets.gateway_password_in_config (warns; recommends env var) |
| #6609 | HIGH | Browser bridge server optional auth | browser.control_invalid_config (partial detection) |
| General gateway exposure | — | Non-loopback bind, missing auth, Tailscale Funnel | gateway.bind_no_auth, gateway.loopback_no_auth, gateway.tailscale_funnel |
| Channel misconfiguration | — | Open DMs, open groups, missing allowlists | All channels.* checks + security.exposure.open_groups_with_elevated |
| Issue | Severity | Why the audit cannot detect it |
|---|---|---|
| #8512 | CRITICAL | Plugin HTTP routes bypass — code-level auth gap in src/gateway/server/plugins-http.ts |
| #3277 | HIGH | Path traversal via startsWith — code-level validation bug |
| #4950 | HIGH | Browser evaluate default on — hardcoded constant, not configurable |
| #5052 | HIGH | Config validation fail-open — code-level bug in src/config/io.ts |
| #5255 | HIGH | Browser file upload arbitrary read — code-level |
| #8516 | HIGH | Browser download/trace arbitrary file write — code-level |
| #8586 | HIGH | Configurable exec bypass — code-level allowlist gap |
| #8590 | HIGH | Status endpoint info leak — code-level |
| #8591 | HIGH | Env vars exposed via shell — code-level |
| #8776 | HIGH | soul-evil hook hijacking — code-level |
| #9435 | Gateway token in URL query params — fixed in PR #9436 | |
| #9512 | HIGH | Skill archive path traversal (Zip Slip) — code-level |
| #9517 | HIGH | Canvas host auth bypass — code-level |
| #8696 | HIGH | Playwright download path traversal — code-level |
| #4949 | HIGH | Browser DNS rebinding — code-level (no Host header validation) |
| #4995 | HIGH | iMessage DM auto-responds with pairing codes — code-level |
| #5995 | HIGH | Secrets in session transcripts — by design |
| #6606 | HIGH | Telegram webhook binds 0.0.0.0 — code-level |
| #8054 | HIGH | Type coercion "undefined" credentials — code-level |
The audit catches ~6 of 37 documented issues (config/filesystem misconfigurations). The remaining ~31 are code-level vulnerabilities that require upstream patches. For defense-in-depth: run
openclaw security audit --fixand monitor the open upstream security issues list.