---
summary: "Reference catalog of checkIds emitted by openclaw security audit"
read_when:
  - You saw a specific `checkId` in `openclaw security audit` output and want to know what it means
  - You need the fix key/path for a given finding
  - You are triaging severity across a security audit run
title: "Security audit checks"
---

`openclaw security audit` emits structured findings keyed by `checkId`. This
page is the reference catalog for those IDs. For the high-level threat model
and hardening guidance, see [Security](/gateway/security).

Some checks only run with `openclaw security audit --deep`: plugin/skill code
scans (`plugins.code_safety*`, `skills.code_safety*`) and live Gateway probe
checks (`gateway.probe_*`). Everything else in this table runs on a plain
`openclaw security audit`.

A severity like `warn/critical` means the same `checkId` can be emitted at
either level depending on config (for example, whether the Gateway is remotely
exposed). High-signal values you will most likely see in real deployments (not
exhaustive):

| `checkId`                                                       | Severity           | Why it matters                                                                          | Primary fix key/path                                                                                 | Auto-fix |
| --------------------------------------------------------------- | ------------------ | --------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | -------- |
| `fs.state_dir.perms_world_writable`                             | critical           | Other users/processes can modify full OpenClaw state                                    | filesystem perms on `~/.openclaw`                                                                    | yes      |
| `fs.state_dir.perms_group_writable`                             | warn               | Group users can modify full OpenClaw state                                              | filesystem perms on `~/.openclaw`                                                                    | yes      |
| `fs.state_dir.perms_readable`                                   | warn               | State dir is readable by others                                                         | filesystem perms on `~/.openclaw`                                                                    | yes      |
| `fs.state_dir.symlink`                                          | warn               | State dir target becomes another trust boundary                                         | state dir filesystem layout                                                                          | no       |
| `fs.config.perms_writable`                                      | critical           | Others can change auth/tool policy/config                                               | filesystem perms on `~/.openclaw/openclaw.json`                                                      | yes      |
| `fs.config.symlink`                                             | warn               | Symlinked config files are unsupported for writes and add another trust boundary        | replace with a regular config file or point `OPENCLAW_CONFIG_PATH` at the real file                  | no       |
| `fs.config.perms_group_readable`                                | warn               | Group users can read config tokens/settings                                             | filesystem perms on config file                                                                      | yes      |
| `fs.config.perms_world_readable`                                | critical           | Config can expose tokens/settings                                                       | filesystem perms on config file                                                                      | yes      |
| `fs.config_include.perms_writable`                              | critical           | Config include file can be modified by others                                           | include-file perms referenced from `openclaw.json`                                                   | yes      |
| `fs.config_include.perms_group_readable`                        | warn               | Group users can read included secrets/settings                                          | include-file perms referenced from `openclaw.json`                                                   | yes      |
| `fs.config_include.perms_world_readable`                        | critical           | Included secrets/settings are world-readable                                            | include-file perms referenced from `openclaw.json`                                                   | yes      |
| `fs.auth_profiles.perms_writable`                               | critical           | Others can inject or replace stored model credentials                                   | `agents/<agentId>/agent/auth-profiles.json` perms                                                    | yes      |
| `fs.auth_profiles.perms_readable`                               | warn               | Others can read API keys and OAuth tokens                                               | `agents/<agentId>/agent/auth-profiles.json` perms                                                    | yes      |
| `fs.credentials_dir.perms_writable`                             | critical           | Others can modify channel pairing/credential state                                      | filesystem perms on `~/.openclaw/credentials`                                                        | yes      |
| `fs.credentials_dir.perms_readable`                             | warn               | Others can read channel credential state                                                | filesystem perms on `~/.openclaw/credentials`                                                        | yes      |
| `fs.sessions_store.perms_readable`                              | warn               | Others can read session transcripts/metadata                                            | session store perms                                                                                  | yes      |
| `fs.log_file.perms_readable`                                    | warn               | Others can read redacted-but-still-sensitive logs                                       | gateway log file perms                                                                               | yes      |
| `fs.synced_dir`                                                 | warn               | State/config in iCloud/Dropbox/Drive broadens token/transcript exposure                 | move config/state off synced folders                                                                 | no       |
| `gateway.bind_no_auth`                                          | critical           | Remote bind without shared secret                                                       | `gateway.bind`, `gateway.auth.*`                                                                     | no       |
| `gateway.loopback_no_auth`                                      | critical           | Reverse-proxied loopback may become unauthenticated                                     | `gateway.auth.*`, proxy setup                                                                        | no       |
| `gateway.trusted_proxies_missing`                               | warn               | Reverse-proxy headers are present but not trusted                                       | `gateway.trustedProxies`                                                                             | no       |
| `gateway.http.no_auth`                                          | warn/critical      | Gateway HTTP APIs reachable with `auth.mode="none"`                                     | `gateway.auth.mode`, `gateway.http.endpoints.*`, `plugins.entries.admin-http-rpc`                    | no       |
| `gateway.http.session_key_override_enabled`                     | info               | HTTP API callers can override `sessionKey`                                              | `gateway.http.allowSessionKeyOverride`                                                               | no       |
| `gateway.tools_invoke_http.dangerous_allow`                     | warn/critical      | Re-enables dangerous tools over HTTP API for owner/admin callers                        | `gateway.tools.allow`                                                                                | no       |
| `gateway.nodes.allow_commands_dangerous`                        | warn/critical      | Enables high-impact node commands (desktop input/camera/screen/contacts/calendar/SMS)   | `gateway.nodes.allowCommands`                                                                        | no       |
| `gateway.nodes.deny_commands_ineffective`                       | warn               | Pattern-like deny entries do not match shell text or groups                             | `gateway.nodes.denyCommands`                                                                         | no       |
| `gateway.tailscale_funnel`                                      | critical           | Public internet exposure                                                                | `gateway.tailscale.mode`                                                                             | no       |
| `gateway.tailscale_serve`                                       | info               | Tailnet exposure is enabled via Serve                                                   | `gateway.tailscale.mode`                                                                             | no       |
| `gateway.control_ui.allowed_origins_required`                   | critical           | Non-loopback Control UI without explicit browser-origin allowlist                       | `gateway.controlUi.allowedOrigins`                                                                   | no       |
| `gateway.control_ui.allowed_origins_wildcard`                   | warn/critical      | `allowedOrigins=["*"]` disables browser-origin allowlisting                             | `gateway.controlUi.allowedOrigins`                                                                   | no       |
| `gateway.control_ui.host_header_origin_fallback`                | warn/critical      | Enables Host-header origin fallback (DNS rebinding hardening downgrade)                 | `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback`                                         | no       |
| `gateway.control_ui.insecure_auth`                              | warn               | Insecure-auth compatibility toggle enabled                                              | `gateway.controlUi.allowInsecureAuth`                                                                | no       |
| `gateway.control_ui.device_auth_disabled`                       | critical           | Disables device identity check                                                          | `gateway.controlUi.dangerouslyDisableDeviceAuth`                                                     | no       |
| `gateway.real_ip_fallback_enabled`                              | warn/critical      | Trusting `X-Real-IP` fallback can enable source-IP spoofing via proxy misconfig         | `gateway.allowRealIpFallback`, `gateway.trustedProxies`                                              | no       |
| `gateway.token_too_short`                                       | warn               | Short shared token is easier to brute force                                             | `gateway.auth.token`                                                                                 | no       |
| `gateway.auth_no_rate_limit`                                    | warn               | Exposed auth without rate limiting increases brute-force risk                           | `gateway.auth.rateLimit`                                                                             | no       |
| `gateway.trusted_proxy_auth`                                    | critical           | Proxy identity now becomes the auth boundary                                            | `gateway.auth.mode="trusted-proxy"`                                                                  | no       |
| `gateway.trusted_proxy_no_proxies`                              | critical           | Trusted-proxy auth without trusted proxy IPs is unsafe                                  | `gateway.trustedProxies`                                                                             | no       |
| `gateway.trusted_proxy_no_user_header`                          | critical           | Trusted-proxy auth cannot resolve user identity safely                                  | `gateway.auth.trustedProxy.userHeader`                                                               | no       |
| `gateway.trusted_proxy_no_allowlist`                            | warn               | Trusted-proxy auth accepts any authenticated upstream user                              | `gateway.auth.trustedProxy.allowUsers`                                                               | no       |
| `gateway.trusted_proxy_allow_loopback`                          | warn               | Trusted-proxy auth accepts explicitly allowed loopback proxy sources                    | `gateway.auth.trustedProxy.allowLoopback`                                                            | no       |
| `gateway.probe_auth_secretref_unavailable`                      | warn               | Deep probe could not resolve auth SecretRefs in this command path                       | deep-probe auth source / SecretRef availability                                                      | no       |
| `gateway.probe_failed`                                          | warn               | Live Gateway probe failed (`--deep` only)                                               | gateway reachability/auth                                                                            | no       |
| `discovery.mdns_full_mode`                                      | warn/critical      | mDNS full mode advertises `cliPath`/`sshPort` metadata on local network                 | `discovery.mdns.mode`, `gateway.bind`                                                                | no       |
| `config.insecure_or_dangerous_flags`                            | warn               | One insecure/dangerous debug flag is enabled                                            | key named in finding detail                                                                          | no       |
| `security.audit.suppressions.active`                            | info               | Audit output has configured suppressions and may be filtered                            | `security.audit.suppressions`                                                                        | no       |
| `config.secrets.gateway_password_in_config`                     | warn               | Gateway password is stored directly in config                                           | `gateway.auth.password`                                                                              | no       |
| `config.secrets.hooks_token_in_config`                          | warn               | Hook bearer token is stored directly in config                                          | `hooks.token`                                                                                        | no       |
| `hooks.token_reuse_gateway_token`                               | critical           | Hook ingress token also unlocks Gateway auth                                            | `hooks.token`, `gateway.auth.token`, `gateway.auth.password`                                         | no       |
| `hooks.token_too_short`                                         | warn               | Easier brute force on hook ingress                                                      | `hooks.token`                                                                                        | no       |
| `hooks.default_session_key_unset`                               | warn               | Hook agent runs fan out into generated per-request sessions                             | `hooks.defaultSessionKey`                                                                            | no       |
| `hooks.allowed_agent_ids_unrestricted`                          | warn/critical      | Authenticated hook callers may route to any configured agent                            | `hooks.allowedAgentIds`                                                                              | no       |
| `hooks.request_session_key_enabled`                             | warn/critical      | External caller can choose sessionKey                                                   | `hooks.allowRequestSessionKey`                                                                       | no       |
| `hooks.request_session_key_prefixes_missing`                    | warn/critical      | No bound on external session key shapes                                                 | `hooks.allowedSessionKeyPrefixes`                                                                    | no       |
| `hooks.path_root`                                               | critical           | Hook path is `/`, making ingress easier to collide or misroute                          | `hooks.path`                                                                                         | no       |
| `hooks.installs_unpinned_npm_specs`                             | warn               | Hook install records are not pinned to immutable npm specs                              | hook install metadata                                                                                | no       |
| `hooks.installs_missing_integrity`                              | warn               | Hook install records lack integrity metadata                                            | hook install metadata                                                                                | no       |
| `hooks.installs_version_drift`                                  | warn               | Hook install records drift from installed packages                                      | hook install metadata                                                                                | no       |
| `logging.redact_off`                                            | warn               | Sensitive values leak to logs/status                                                    | `logging.redactSensitive`                                                                            | yes      |
| `browser.control_invalid_config`                                | warn               | Browser control config is invalid before runtime                                        | `browser.*`                                                                                          | no       |
| `browser.control_no_auth`                                       | critical           | Browser control exposed without token/password auth                                     | `gateway.auth.*`                                                                                     | no       |
| `browser.remote_cdp_http`                                       | warn               | Remote CDP over plain HTTP lacks transport encryption                                   | browser profile `cdpUrl`                                                                             | no       |
| `browser.remote_cdp_private_host`                               | warn               | Remote CDP targets a private/internal host                                              | browser profile `cdpUrl`, `browser.ssrfPolicy.*`                                                     | no       |
| `sandbox.docker_config_mode_off`                                | warn               | Sandbox Docker config present but inactive                                              | `agents.*.sandbox.mode`                                                                              | no       |
| `sandbox.bind_mount_non_absolute`                               | warn               | Relative bind mounts can resolve unpredictably                                          | `agents.*.sandbox.docker.binds[]`                                                                    | no       |
| `sandbox.dangerous_bind_mount`                                  | critical           | Sandbox bind mount targets blocked system, credential, or Docker socket paths           | `agents.*.sandbox.docker.binds[]`                                                                    | no       |
| `sandbox.dangerous_network_mode`                                | critical           | Sandbox Docker network uses `host` or `container:*` namespace-join mode                 | `agents.*.sandbox.docker.network`                                                                    | no       |
| `sandbox.dangerous_seccomp_profile`                             | critical           | Sandbox seccomp profile weakens container isolation                                     | `agents.*.sandbox.docker.securityOpt`                                                                | no       |
| `sandbox.dangerous_apparmor_profile`                            | critical           | Sandbox AppArmor profile weakens container isolation                                    | `agents.*.sandbox.docker.securityOpt`                                                                | no       |
| `sandbox.browser_cdp_bridge_unrestricted`                       | warn               | Sandbox browser bridge is exposed without source-range restriction                      | `sandbox.browser.cdpSourceRange`                                                                     | no       |
| `sandbox.browser_container.non_loopback_publish`                | critical           | Existing browser container publishes CDP on non-loopback interfaces                     | browser sandbox container publish config                                                             | no       |
| `sandbox.browser_container.hash_label_missing`                  | warn               | Existing browser container predates current config-hash labels                          | `openclaw sandbox recreate --browser --all`                                                          | no       |
| `sandbox.browser_container.hash_epoch_stale`                    | warn               | Existing browser container predates current browser config epoch                        | `openclaw sandbox recreate --browser --all`                                                          | no       |
| `sandbox.browser_container.docker_probe_timeout`                | warn               | Docker label probe for the browser container timed out                                  | Docker daemon reachability                                                                           | no       |
| `tools.exec.host_sandbox_no_sandbox_defaults`                   | warn               | `exec host=sandbox` fails closed when sandbox is off                                    | `tools.exec.host`, `agents.defaults.sandbox.mode`                                                    | no       |
| `tools.exec.host_sandbox_no_sandbox_agents`                     | warn               | Per-agent `exec host=sandbox` fails closed when sandbox is off                          | `agents.list[].tools.exec.host`, `agents.list[].sandbox.mode`                                        | no       |
| `tools.exec.security_full_configured`                           | warn/critical      | Host exec is running with `security="full"`                                             | `tools.exec.security`, `agents.list[].tools.exec.security`                                           | no       |
| `tools.exec.agent_skill_mcp_boundary_drift`                     | warn               | Agent skill allowlists are present while host exec can reach MCP clients/registries     | `agents.list[].tools.exec.*`, sandbox/OS isolation, MCP server credentials                           | no       |
| `tools.exec.fs_tools_disabled_but_exec_enabled`                 | warn               | Filesystem tool policy does not make shell execution read-only                          | `tools.deny`, `agents.list[].tools.deny`, `agents.*.sandbox.workspaceAccess`                         | no       |
| `tools.exec.auto_allow_skills_enabled`                          | warn               | Exec approvals trust skill bins implicitly                                              | host approvals file                                                                                  | no       |
| `tools.exec.allowlist_interpreter_without_strict_inline_eval`   | warn               | Interpreter allowlists permit inline eval without forced reapproval                     | `tools.exec.strictInlineEval`, `agents.list[].tools.exec.strictInlineEval`, exec approvals allowlist | no       |
| `tools.exec.safe_bins_interpreter_unprofiled`                   | warn               | Interpreter/runtime bins in `safeBins` without explicit profiles broaden exec risk      | `tools.exec.safeBins`, `tools.exec.safeBinProfiles`, `agents.list[].tools.exec.*`                    | no       |
| `tools.exec.safe_bins_broad_behavior`                           | warn               | Broad-behavior tools in `safeBins` weaken the low-risk stdin-filter trust model         | `tools.exec.safeBins`, `agents.list[].tools.exec.safeBins`                                           | no       |
| `tools.exec.safe_bin_trusted_dirs_risky`                        | warn               | `safeBinTrustedDirs` includes mutable or risky directories                              | `tools.exec.safeBinTrustedDirs`, `agents.list[].tools.exec.safeBinTrustedDirs`                       | no       |
| `tools.elevated.allowFrom.<provider>.wildcard`                  | critical           | `tools.elevated.allowFrom.<provider>` includes `"*"`, approving every sender            | `tools.elevated.allowFrom.<provider>`                                                                | no       |
| `tools.elevated.allowFrom.<provider>.large`                     | warn               | Elevated allowlist for `<provider>` has more than 25 entries                            | `tools.elevated.allowFrom.<provider>`                                                                | no       |
| `agents.claude_cli.permission_mode_overridden_by_yolo`          | warn               | Claude CLI `--permission-mode` is ignored because OpenClaw exec is fully unattended     | `tools.exec.security`, `tools.exec.ask`, `cliBackends.claude-cli` args                               | no       |
| `skills.workspace.symlink_escape`                               | warn               | Workspace `skills/**/SKILL.md` resolves outside workspace root (symlink-chain drift)    | workspace `skills/**` filesystem state                                                               | no       |
| `skills.workspace.scan_truncated`                               | warn               | Workspace skill scan hit its directory-visit cap before finishing                       | flatten/simplify the workspace `skills/` directory tree                                              | no       |
| `plugins.extensions_no_allowlist`                               | warn               | Plugins are installed without an explicit plugin allowlist                              | `plugins.allowlist`                                                                                  | no       |
| `plugins.allow_phantom_entries`                                 | warn               | `plugins.allow` lists an ID with no matching installed plugin                           | `plugins.allow`                                                                                      | no       |
| `plugins.installs_unpinned_npm_specs`                           | warn               | Plugin index records are not pinned to immutable npm specs                              | plugin install metadata                                                                              | no       |
| `plugins.installs_missing_integrity`                            | warn               | Plugin index records lack integrity metadata                                            | plugin install metadata                                                                              | no       |
| `plugins.installs_version_drift`                                | warn               | Plugin index records drift from installed packages                                      | plugin install metadata                                                                              | no       |
| `plugins.code_safety`                                           | warn/critical      | Plugin code scan found suspicious or dangerous patterns (`--deep` only)                 | plugin code / install source                                                                         | no       |
| `plugins.code_safety.entry_path`                                | warn               | Plugin entry path points into hidden or `node_modules` locations                        | plugin manifest `entry`                                                                              | no       |
| `plugins.code_safety.entry_escape`                              | critical           | Plugin entry escapes the plugin directory                                               | plugin manifest `entry`                                                                              | no       |
| `plugins.code_safety.manifest_parse_error`                      | warn               | Plugin manifest could not be parsed during the code-safety scan                         | plugin manifest file                                                                                 | no       |
| `plugins.code_safety.scan_failed`                               | warn               | Plugin code scan could not complete (`--deep` only)                                     | plugin path / scan environment                                                                       | no       |
| `plugins.<pluginId>.security_audit_failed`                      | warn               | A plugin-owned security audit collector threw an error                                  | that plugin's security-audit collector                                                               | no       |
| `skills.code_safety`                                            | warn/critical      | Skill installer metadata/code contains suspicious or dangerous patterns (`--deep` only) | skill install source                                                                                 | no       |
| `skills.code_safety.scan_failed`                                | warn               | Skill code scan could not complete (`--deep` only)                                      | skill scan environment                                                                               | no       |
| `security.exposure.open_channels_with_exec`                     | warn/critical      | Shared/public rooms can reach exec-enabled agents                                       | `channels.*.dmPolicy`, `channels.*.groupPolicy`, `tools.exec.*`, `agents.list[].tools.exec.*`        | no       |
| `security.exposure.open_groups_with_elevated`                   | critical           | Open DMs/groups + elevated tools create high-impact prompt-injection paths              | top-level or nested DM policy paths, account overrides, `channels.*.groupPolicy`                     | no       |
| `security.exposure.open_groups_with_runtime_or_fs`              | critical/warn      | Open DMs/groups can reach command/file tools without sandbox/workspace guards           | DM/group policy paths, `tools.profile/deny`, `tools.fs.workspaceOnly`, `agents.*.sandbox.mode`       | no       |
| `security.exposure.open_groups_with_control_plane_tools`        | critical           | Open DMs/groups can reach gateway/cron control-plane tools                              | DM/group policy paths, `tools.allow`, `tools.alsoAllow`, `tools.profile`, `gateway`, `cron`          | no       |
| `security.trust_model.multi_user_heuristic`                     | warn               | Config looks multi-user while gateway trust model is personal-assistant                 | split trust boundaries, or shared-user hardening (`sandbox.mode`, tool deny/workspace scoping)       | no       |
| `tools.profile_minimal_overridden`                              | warn               | Agent overrides bypass global minimal profile                                           | `agents.list[].tools.profile`                                                                        | no       |
| `plugins.tools_reachable_permissive_policy`                     | warn               | Extension tools reachable in permissive contexts                                        | `tools.profile` + tool allow/deny                                                                    | no       |
| `models.legacy`                                                 | warn               | Legacy model families are still configured                                              | model selection                                                                                      | no       |
| `models.weak_tier`                                              | warn               | Configured models are below current recommended tiers                                   | model selection                                                                                      | no       |
| `models.small_params`                                           | critical/info      | Small models + unsafe tool surfaces raise injection risk                                | model choice + sandbox/tool policy                                                                   | no       |
| `channels.<provider>.dm.open`                                   | critical           | `<provider>` DM policy is `"open"`; anyone can DM the bot                               | `channels.<provider>.dmPolicy`, `.allowFrom`                                                         | no       |
| `channels.<provider>.dm.open_invalid`                           | warn               | `dmPolicy="open"` without `"*"` in `allowFrom` is inconsistent                          | `channels.<provider>.allowFrom`                                                                      | no       |
| `channels.<provider>.dm.scope_main_multiuser`                   | warn               | Multiple DM senders currently share the main session                                    | `session.dmScope`                                                                                    | no       |
| `channels.<provider>.allowFrom.dangerous_name_matching_enabled` | info               | `dangerouslyAllowNameMatching` re-enables mutable name/email/tag sender matching        | disable `dangerouslyAllowNameMatching`, use stable sender IDs                                        | no       |
| `channels.<provider>.account.read_only_resolution`              | warn               | A channel account could not be fully resolved for audit (missing secret/gateway)        | ensure referenced secrets are resolvable, or run against a live gateway snapshot                     | no       |
| `channels.<provider>.warning.<n>`                               | info/warn/critical | Provider-specific security warning, classified from free-form plugin text               | see finding detail                                                                                   | no       |
| `summary.attack_surface`                                        | info               | Roll-up summary of auth, channel, tool, and exposure posture                            | multiple keys (see finding detail)                                                                   | no       |

`channels.<provider>.*` and `tools.elevated.allowFrom.<provider>.*` checkIds are
generated per configured channel/provider, so `<provider>` is a real channel id
(for example `telegram`, `discord`) in actual output, not a literal string.

## Related

- [Security](/gateway/security)
- [Configuration](/gateway/configuration)
- [Trusted proxy auth](/gateway/trusted-proxy-auth)
