mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:40:44 +00:00
docs: restructure gateway security page and extract audit checks reference
This commit is contained in:
@@ -1380,6 +1380,7 @@
|
||||
"group": "Security and sandboxing",
|
||||
"pages": [
|
||||
"gateway/security/index",
|
||||
"gateway/security/audit-checks",
|
||||
"gateway/sandboxing",
|
||||
"gateway/openshell",
|
||||
"gateway/sandbox-vs-tool-policy-vs-elevated"
|
||||
|
||||
126
docs/gateway/security/audit-checks.md
Normal file
126
docs/gateway/security/audit-checks.md
Normal file
@@ -0,0 +1,126 @@
|
||||
---
|
||||
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"
|
||||
---
|
||||
|
||||
# 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).
|
||||
|
||||
High-signal `checkId` 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.*` | 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 | `gateway.tools.allow` | no |
|
||||
| `gateway.nodes.allow_commands_dangerous` | warn/critical | Enables high-impact node commands (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.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/critical | Live Gateway probe failed | 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 | Any insecure/dangerous debug flags enabled | multiple keys (see finding detail) | 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` | 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 |
|
||||
| `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.auto_allow_skills_enabled` | warn | Exec approvals trust skill bins implicitly | `~/.openclaw/exec-approvals.json` | 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 |
|
||||
| `skills.workspace.symlink_escape` | warn | Workspace `skills/**/SKILL.md` resolves outside workspace root (symlink-chain drift) | workspace `skills/**` filesystem state | no |
|
||||
| `plugins.extensions_no_allowlist` | warn | Plugins are installed without an explicit plugin allowlist | `plugins.allowlist` | no |
|
||||
| `plugins.installs_unpinned_npm_specs` | warn | Plugin install records are not pinned to immutable npm specs | plugin install metadata | no |
|
||||
| `plugins.installs_missing_integrity` | warn | Plugin install records lack integrity metadata | plugin install metadata | no |
|
||||
| `plugins.installs_version_drift` | warn | Plugin install records drift from installed packages | plugin install metadata | no |
|
||||
| `plugins.code_safety` | warn/critical | Plugin code scan found suspicious or dangerous patterns | 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.scan_failed` | warn | Plugin code scan could not complete | plugin path / scan environment | no |
|
||||
| `skills.code_safety` | warn/critical | Skill installer metadata/code contains suspicious or dangerous patterns | skill install source | no |
|
||||
| `skills.code_safety.scan_failed` | warn | Skill code scan could not complete | 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 groups + elevated tools create high-impact prompt-injection paths | `channels.*.groupPolicy`, `tools.elevated.*` | no |
|
||||
| `security.exposure.open_groups_with_runtime_or_fs` | critical/warn | Open groups can reach command/file tools without sandbox/workspace guards | `channels.*.groupPolicy`, `tools.profile/deny`, `tools.fs.workspaceOnly`, `agents.*.sandbox.mode` | 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 |
|
||||
| `summary.attack_surface` | info | Roll-up summary of auth, channel, tool, and exposure posture | multiple keys (see finding detail) | no |
|
||||
|
||||
## Related
|
||||
|
||||
- [Security](/gateway/security)
|
||||
- [Configuration](/gateway/configuration)
|
||||
- [Trusted proxy auth](/gateway/trusted-proxy-auth)
|
||||
@@ -125,17 +125,6 @@ These patterns are commonly reported and are usually closed as no-action unless
|
||||
- Reports that treat node pairing metadata as a hidden second per-command approval layer for `system.run`, when the real execution boundary is still the gateway's global node command policy plus the node's own exec approvals.
|
||||
- "Missing per-user authorization" findings that treat `sessionKey` as an auth token.
|
||||
|
||||
## Researcher preflight checklist
|
||||
|
||||
Before opening a GHSA, verify all of these:
|
||||
|
||||
1. Repro still works on latest `main` or latest release.
|
||||
2. Report includes exact code path (`file`, function, line range) and tested version/commit.
|
||||
3. Impact crosses a documented trust boundary (not just prompt injection).
|
||||
4. Claim is not listed in [Out of Scope](https://github.com/openclaw/openclaw/blob/main/SECURITY.md#out-of-scope).
|
||||
5. Existing advisories were checked for duplicates (reuse canonical GHSA when applicable).
|
||||
6. Deployment assumptions are explicit (loopback/local vs exposed, trusted vs untrusted operators).
|
||||
|
||||
## Hardened baseline in 60 seconds
|
||||
|
||||
Use this baseline first, then selectively re-enable tools per trusted agent:
|
||||
@@ -238,110 +227,18 @@ When the audit prints findings, treat this as a priority order:
|
||||
|
||||
## Security audit glossary
|
||||
|
||||
High-signal `checkId` values you will most likely see in real deployments (not exhaustive):
|
||||
Each audit finding is keyed by a structured `checkId` (for example
|
||||
`gateway.bind_no_auth` or `tools.exec.security_full_configured`). Common
|
||||
critical severity classes:
|
||||
|
||||
| `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.*` | 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 | `gateway.tools.allow` | no |
|
||||
| `gateway.nodes.allow_commands_dangerous` | warn/critical | Enables high-impact node commands (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.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/critical | Live Gateway probe failed | 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 | Any insecure/dangerous debug flags enabled | multiple keys (see finding detail) | 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` | 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 |
|
||||
| `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.auto_allow_skills_enabled` | warn | Exec approvals trust skill bins implicitly | `~/.openclaw/exec-approvals.json` | 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 |
|
||||
| `skills.workspace.symlink_escape` | warn | Workspace `skills/**/SKILL.md` resolves outside workspace root (symlink-chain drift) | workspace `skills/**` filesystem state | no |
|
||||
| `plugins.extensions_no_allowlist` | warn | Plugins are installed without an explicit plugin allowlist | `plugins.allowlist` | no |
|
||||
| `plugins.installs_unpinned_npm_specs` | warn | Plugin install records are not pinned to immutable npm specs | plugin install metadata | no |
|
||||
| `plugins.installs_missing_integrity` | warn | Plugin install records lack integrity metadata | plugin install metadata | no |
|
||||
| `plugins.installs_version_drift` | warn | Plugin install records drift from installed packages | plugin install metadata | no |
|
||||
| `plugins.code_safety` | warn/critical | Plugin code scan found suspicious or dangerous patterns | 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.scan_failed` | warn | Plugin code scan could not complete | plugin path / scan environment | no |
|
||||
| `skills.code_safety` | warn/critical | Skill installer metadata/code contains suspicious or dangerous patterns | skill install source | no |
|
||||
| `skills.code_safety.scan_failed` | warn | Skill code scan could not complete | 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 groups + elevated tools create high-impact prompt-injection paths | `channels.*.groupPolicy`, `tools.elevated.*` | no |
|
||||
| `security.exposure.open_groups_with_runtime_or_fs` | critical/warn | Open groups can reach command/file tools without sandbox/workspace guards | `channels.*.groupPolicy`, `tools.profile/deny`, `tools.fs.workspaceOnly`, `agents.*.sandbox.mode` | 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 |
|
||||
| `summary.attack_surface` | info | Roll-up summary of auth, channel, tool, and exposure posture | multiple keys (see finding detail) | no |
|
||||
- `fs.*` — filesystem permissions on state, config, credentials, auth profiles.
|
||||
- `gateway.*` — bind mode, auth, Tailscale, Control UI, trusted-proxy setup.
|
||||
- `hooks.*`, `browser.*`, `sandbox.*`, `tools.exec.*` — per-surface hardening.
|
||||
- `plugins.*`, `skills.*` — plugin/skill supply chain and scan findings.
|
||||
- `security.exposure.*` — cross-cutting checks where access policy meets tool blast radius.
|
||||
|
||||
See the full catalog with severity levels, fix keys, and auto-fix support at
|
||||
[Security audit checks](/gateway/security/audit-checks).
|
||||
|
||||
## Control UI over HTTP
|
||||
|
||||
@@ -368,48 +265,53 @@ does not extend to node-role Control UI sessions.
|
||||
|
||||
## Insecure or dangerous flags summary
|
||||
|
||||
`openclaw security audit` includes `config.insecure_or_dangerous_flags` when
|
||||
known insecure/dangerous debug switches are enabled. That check currently
|
||||
aggregates:
|
||||
`openclaw security audit` raises `config.insecure_or_dangerous_flags` when
|
||||
known insecure/dangerous debug switches are enabled. Keep these unset in
|
||||
production.
|
||||
|
||||
- `gateway.controlUi.allowInsecureAuth=true`
|
||||
- `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true`
|
||||
- `gateway.controlUi.dangerouslyDisableDeviceAuth=true`
|
||||
- `hooks.gmail.allowUnsafeExternalContent=true`
|
||||
- `hooks.mappings[<index>].allowUnsafeExternalContent=true`
|
||||
- `tools.exec.applyPatch.workspaceOnly=false`
|
||||
- `plugins.entries.acpx.config.permissionMode=approve-all`
|
||||
<AccordionGroup>
|
||||
<Accordion title="Flags tracked by the audit today">
|
||||
- `gateway.controlUi.allowInsecureAuth=true`
|
||||
- `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback=true`
|
||||
- `gateway.controlUi.dangerouslyDisableDeviceAuth=true`
|
||||
- `hooks.gmail.allowUnsafeExternalContent=true`
|
||||
- `hooks.mappings[<index>].allowUnsafeExternalContent=true`
|
||||
- `tools.exec.applyPatch.workspaceOnly=false`
|
||||
- `plugins.entries.acpx.config.permissionMode=approve-all`
|
||||
</Accordion>
|
||||
|
||||
Complete `dangerous*` / `dangerously*` config keys defined in OpenClaw config
|
||||
schema:
|
||||
<Accordion title="All `dangerous*` / `dangerously*` keys in the config schema">
|
||||
Control UI and browser:
|
||||
|
||||
- `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback`
|
||||
- `gateway.controlUi.dangerouslyDisableDeviceAuth`
|
||||
- `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork`
|
||||
- `channels.discord.dangerouslyAllowNameMatching`
|
||||
- `channels.discord.accounts.<accountId>.dangerouslyAllowNameMatching`
|
||||
- `channels.slack.dangerouslyAllowNameMatching`
|
||||
- `channels.slack.accounts.<accountId>.dangerouslyAllowNameMatching`
|
||||
- `channels.googlechat.dangerouslyAllowNameMatching`
|
||||
- `channels.googlechat.accounts.<accountId>.dangerouslyAllowNameMatching`
|
||||
- `channels.msteams.dangerouslyAllowNameMatching`
|
||||
- `channels.synology-chat.dangerouslyAllowNameMatching` (plugin channel)
|
||||
- `channels.synology-chat.accounts.<accountId>.dangerouslyAllowNameMatching` (plugin channel)
|
||||
- `channels.synology-chat.dangerouslyAllowInheritedWebhookPath` (plugin channel)
|
||||
- `channels.zalouser.dangerouslyAllowNameMatching` (plugin channel)
|
||||
- `channels.zalouser.accounts.<accountId>.dangerouslyAllowNameMatching` (plugin channel)
|
||||
- `channels.irc.dangerouslyAllowNameMatching` (plugin channel)
|
||||
- `channels.irc.accounts.<accountId>.dangerouslyAllowNameMatching` (plugin channel)
|
||||
- `channels.mattermost.dangerouslyAllowNameMatching` (plugin channel)
|
||||
- `channels.mattermost.accounts.<accountId>.dangerouslyAllowNameMatching` (plugin channel)
|
||||
- `channels.telegram.network.dangerouslyAllowPrivateNetwork`
|
||||
- `channels.telegram.accounts.<accountId>.network.dangerouslyAllowPrivateNetwork`
|
||||
- `agents.defaults.sandbox.docker.dangerouslyAllowReservedContainerTargets`
|
||||
- `agents.defaults.sandbox.docker.dangerouslyAllowExternalBindSources`
|
||||
- `agents.defaults.sandbox.docker.dangerouslyAllowContainerNamespaceJoin`
|
||||
- `agents.list[<index>].sandbox.docker.dangerouslyAllowReservedContainerTargets`
|
||||
- `agents.list[<index>].sandbox.docker.dangerouslyAllowExternalBindSources`
|
||||
- `agents.list[<index>].sandbox.docker.dangerouslyAllowContainerNamespaceJoin`
|
||||
- `gateway.controlUi.dangerouslyAllowHostHeaderOriginFallback`
|
||||
- `gateway.controlUi.dangerouslyDisableDeviceAuth`
|
||||
- `browser.ssrfPolicy.dangerouslyAllowPrivateNetwork`
|
||||
|
||||
Channel name-matching (bundled and plugin channels; also available per
|
||||
`accounts.<accountId>` where applicable):
|
||||
|
||||
- `channels.discord.dangerouslyAllowNameMatching`
|
||||
- `channels.slack.dangerouslyAllowNameMatching`
|
||||
- `channels.googlechat.dangerouslyAllowNameMatching`
|
||||
- `channels.msteams.dangerouslyAllowNameMatching`
|
||||
- `channels.synology-chat.dangerouslyAllowNameMatching` (plugin channel)
|
||||
- `channels.synology-chat.dangerouslyAllowInheritedWebhookPath` (plugin channel)
|
||||
- `channels.zalouser.dangerouslyAllowNameMatching` (plugin channel)
|
||||
- `channels.irc.dangerouslyAllowNameMatching` (plugin channel)
|
||||
- `channels.mattermost.dangerouslyAllowNameMatching` (plugin channel)
|
||||
|
||||
Network exposure:
|
||||
|
||||
- `channels.telegram.network.dangerouslyAllowPrivateNetwork` (also per account)
|
||||
|
||||
Sandbox Docker (defaults + per-agent):
|
||||
|
||||
- `agents.defaults.sandbox.docker.dangerouslyAllowReservedContainerTargets`
|
||||
- `agents.defaults.sandbox.docker.dangerouslyAllowExternalBindSources`
|
||||
- `agents.defaults.sandbox.docker.dangerouslyAllowContainerNamespaceJoin`
|
||||
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Reverse Proxy Configuration
|
||||
|
||||
@@ -771,7 +673,7 @@ Guidance:
|
||||
|
||||
## Configuration Hardening (examples)
|
||||
|
||||
### 0) File permissions
|
||||
### File permissions
|
||||
|
||||
Keep config + state private on the gateway host:
|
||||
|
||||
@@ -780,7 +682,7 @@ Keep config + state private on the gateway host:
|
||||
|
||||
`openclaw doctor` can warn and offer to tighten these permissions.
|
||||
|
||||
### 0.4) Network exposure (bind + port + firewall)
|
||||
### Network exposure (bind, port, firewall)
|
||||
|
||||
The Gateway multiplexes **WebSocket + HTTP** on a single port:
|
||||
|
||||
@@ -808,7 +710,7 @@ Rules of thumb:
|
||||
- If you must bind to LAN, firewall the port to a tight allowlist of source IPs; do not port-forward it broadly.
|
||||
- Never expose the Gateway unauthenticated on `0.0.0.0`.
|
||||
|
||||
### 0.4.1) Docker port publishing + UFW (`DOCKER-USER`)
|
||||
### Docker port publishing with UFW
|
||||
|
||||
If you run OpenClaw with Docker on a VPS, remember that published container ports
|
||||
(`-p HOST:CONTAINER` or Compose `ports:`) are routed through Docker's forwarding
|
||||
@@ -857,7 +759,7 @@ nmap -sT -p 1-65535 <public-ip> --open
|
||||
Expected external ports should be only what you intentionally expose (for most
|
||||
setups: SSH + your reverse proxy ports).
|
||||
|
||||
### 0.4.2) mDNS/Bonjour discovery (information disclosure)
|
||||
### mDNS/Bonjour discovery
|
||||
|
||||
The Gateway broadcasts its presence via mDNS (`_openclaw-gw._tcp` on port 5353) for local device discovery. In full mode, this includes TXT records that may expose operational details:
|
||||
|
||||
@@ -903,7 +805,7 @@ The Gateway broadcasts its presence via mDNS (`_openclaw-gw._tcp` on port 5353)
|
||||
|
||||
In minimal mode, the Gateway still broadcasts enough for device discovery (`role`, `gatewayPort`, `transport`) but omits `cliPath` and `sshPort`. Apps that need CLI path information can fetch it via the authenticated WebSocket connection instead.
|
||||
|
||||
### 0.5) Lock down the Gateway WebSocket (local auth)
|
||||
### Lock down the Gateway WebSocket (local auth)
|
||||
|
||||
Gateway auth is **required by default**. If no valid gateway auth path is configured,
|
||||
the Gateway refuses WebSocket connections (fail‑closed).
|
||||
@@ -958,7 +860,7 @@ Rotation checklist (token/password):
|
||||
3. Update any remote clients (`gateway.remote.token` / `.password` on machines that call into the Gateway).
|
||||
4. Verify you can no longer connect with the old credentials.
|
||||
|
||||
### 0.6) Tailscale Serve identity headers
|
||||
### Tailscale Serve identity headers
|
||||
|
||||
When `gateway.auth.allowTailscale` is `true` (default for Serve), OpenClaw
|
||||
accepts Tailscale Serve identity headers (`tailscale-user-login`) for Control
|
||||
@@ -1005,7 +907,7 @@ Trusted proxies:
|
||||
|
||||
See [Tailscale](/gateway/tailscale) and [Web overview](/web).
|
||||
|
||||
### 0.6.1) Browser control via node host (recommended)
|
||||
### Browser control via node host (recommended)
|
||||
|
||||
If your Gateway is remote but the browser runs on another machine, run a **node host**
|
||||
on the browser machine and let the Gateway proxy browser actions (see [Browser tool](/tools/browser)).
|
||||
@@ -1021,7 +923,7 @@ Avoid:
|
||||
- Exposing relay/control ports over LAN or public Internet.
|
||||
- Tailscale Funnel for browser control endpoints (public exposure).
|
||||
|
||||
### 0.7) Secrets on disk (sensitive data)
|
||||
### Secrets on disk
|
||||
|
||||
Assume anything under `~/.openclaw/` (or `$OPENCLAW_STATE_DIR/`) may contain secrets or private data:
|
||||
|
||||
@@ -1040,7 +942,7 @@ Hardening tips:
|
||||
- Use full-disk encryption on the gateway host.
|
||||
- Prefer a dedicated OS user account for the Gateway if the host is shared.
|
||||
|
||||
### 0.8) Workspace `.env` files
|
||||
### Workspace `.env` files
|
||||
|
||||
OpenClaw loads workspace-local `.env` files for agents and tools, but never lets those files silently override gateway runtime controls.
|
||||
|
||||
@@ -1051,7 +953,7 @@ OpenClaw loads workspace-local `.env` files for agents and tools, but never lets
|
||||
|
||||
Why: workspace `.env` files frequently live next to agent code, get committed by accident, or get written by tools. Blocking the whole `OPENCLAW_*` prefix means adding a new `OPENCLAW_*` flag later can never regress into silent inheritance from workspace state.
|
||||
|
||||
### 0.9) Logs + transcripts (redaction + retention)
|
||||
### Logs and transcripts (redaction and retention)
|
||||
|
||||
Logs and transcripts can leak sensitive info even when access controls are correct:
|
||||
|
||||
@@ -1067,7 +969,7 @@ Recommendations:
|
||||
|
||||
Details: [Logging](/gateway/logging)
|
||||
|
||||
### 1) DMs: pairing by default
|
||||
### DMs: pairing by default
|
||||
|
||||
```json5
|
||||
{
|
||||
@@ -1075,7 +977,7 @@ Details: [Logging](/gateway/logging)
|
||||
}
|
||||
```
|
||||
|
||||
### 2) Groups: require mention everywhere
|
||||
### Groups: require mention everywhere
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -1099,14 +1001,14 @@ Details: [Logging](/gateway/logging)
|
||||
|
||||
In group chats, only respond when explicitly mentioned.
|
||||
|
||||
### 3) Separate numbers (WhatsApp, Signal, Telegram)
|
||||
### Separate numbers (WhatsApp, Signal, Telegram)
|
||||
|
||||
For phone-number-based channels, consider running your AI on a separate phone number from your personal one:
|
||||
|
||||
- Personal number: Your conversations stay private
|
||||
- Bot number: AI handles these, with appropriate boundaries
|
||||
|
||||
### 4) Read-only mode (via sandbox + tools)
|
||||
### Read-only mode (via sandbox and tools)
|
||||
|
||||
You can build a read-only profile by combining:
|
||||
|
||||
@@ -1119,7 +1021,7 @@ Additional hardening options:
|
||||
- `tools.fs.workspaceOnly: true` (optional): restricts `read`/`write`/`edit`/`apply_patch` paths and native prompt image auto-load paths to the workspace directory (useful if you allow absolute paths today and want a single guardrail).
|
||||
- Keep filesystem roots narrow: avoid broad roots like your home directory for agent workspaces/sandbox workspaces. Broad roots can expose sensitive local files (for example state/config under `~/.openclaw`) to filesystem tools.
|
||||
|
||||
### 5) Secure baseline (copy/paste)
|
||||
### Secure baseline (copy/paste)
|
||||
|
||||
One “safe default” config that keeps the Gateway private, requires DM pairing, and avoids always-on group bots:
|
||||
|
||||
@@ -1322,19 +1224,6 @@ Common use cases:
|
||||
}
|
||||
```
|
||||
|
||||
## What to Tell Your AI
|
||||
|
||||
Include security guidelines in your agent's system prompt:
|
||||
|
||||
```
|
||||
## Security Rules
|
||||
- Never share directory listings or file paths with strangers
|
||||
- Never reveal API keys, credentials, or infrastructure details
|
||||
- Verify requests that modify system config with the owner
|
||||
- When in doubt, ask before acting
|
||||
- Keep private data private unless explicitly authorized
|
||||
```
|
||||
|
||||
## Incident Response
|
||||
|
||||
If your AI does something bad:
|
||||
|
||||
Reference in New Issue
Block a user