Files
openclaw/docs/gateway/security/audit-checks.md
Peter Steinberger bdcc6836e0 refactor(gateway): retire the Control UI device-auth migration window (#124667)
* refactor(gateway): delete the retired Control UI device-auth migration window

The one-time remediation window for the retired
gateway.controlUi.dangerouslyDisableDeviceAuth break-glass threaded a pending
state machine through the connect pipeline, startup bootstrap, lifecycle,
request context, device management, security audit, the hello frame, and a
Control UI banner flow — steady-state runtime carrying a retired-shape shim
the architecture reserves for doctor. The window is closed: the retired key
is now fully inert, doctor still detects and removes it, and a browser that
never completed the migration pairs through the normal device flow (one
approval, no data loss).

Deleted with it: the config-machine-state import of the legacy flag, the
hello deviceAuthMigration field (optional; clients validate envelopes only,
so older gateways emitting it stay compatible), the migration-bound device
management authz states, the requireNoPairingCapableOperator approval mode,
the effective-operator pairing event emitter whose only subscriber was the
migration completion, and the Control UI banner, loader, overlay wiring,
i18n strings, and e2e scenario support. Swift and Kotlin protocol models
regenerated.

Live-verified on an isolated gateway with the retired key present in config:
clean boot with no migration warning, silent CLI pairing and silent local
scope widening unaffected, and doctor reporting the key as retired-and-inert.

Net -1111 production LOC.

* fix(ci): finish migration-window cleanup surfaced by the gates

The doctor migration for the retired key kept its "Preserved for remediation"
change text and describe; both now state plain removal, with the retired
tests updated. peekStoredDeviceIdentityId lost its only production consumer
with the deleted banner loader and is removed with its test mock. Also fixes
the unrelated no-unnecessary-boolean-literal-compare lint break that #124636
landed on main in scripts/check-changed.mts (truthiness is equivalent for the
boolean-or-undefined TTY probe).

* fix(ui): drop the retired-key device-auth reader from the security summary

Review findings on the migration-window removal: the Control UI security
summary still derived its "Device auth" row from the retired
dangerouslyDisableDeviceAuth key, rendering device auth as disabled on
configurations that merely retain the inert key. Device auth is now
unconditionally enforced, so the row and its derivation are removed rather
than pinned to a constant. The build-admission test also tracks and removes
its temporary device-identity databases after each run.
2026-08-16 09:39:15 -07:00

36 KiB

summary, read_when, title
summary read_when title
Reference catalog of checkIds emitted by openclaw security audit
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
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.

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.commands.allow no
gateway.nodes.deny_commands_ineffective warn Pattern-like deny entries do not match shell text or groups gateway.nodes.commands.deny 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.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
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
browser.extension_relay_legacy_auth warn Legacy extension relay bearer/Basic/token authentication remains enabled browser.extensionRelay.allowLegacyAuth 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.entries.*.tools.exec.host, agents.entries.*.sandbox.mode no
tools.exec.security_full_configured warn/critical Host exec is running with security="full" tools.exec.security, agents.entries.*.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.entries.*.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.entries.*.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.entries.*.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.entries.*.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.entries.*.tools.exec.safeBins no
tools.exec.safe_bin_trusted_dirs_risky warn safeBinTrustedDirs includes mutable or risky directories tools.exec.safeBinTrustedDirs, agents.entries.*.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
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
channels.discord.allowlisted_groups.broad_members warn Allowlisted Discord guild/channel targets have no member or role restriction channels.discord.guilds.*.users/roles, per-channel users/roles no
security.exposure.open_channels_with_exec warn/critical Shared/public rooms can reach exec-enabled agents channels.*.dmPolicy, channels.*.groupPolicy, tools.exec.*, agents.entries.*.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.entries.*.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.