Deployment and host trust
- Full-disk encryption on the gateway host; prefer a dedicated OS user account for the Gateway if the host is shared.
- Published package dependencies:
pnpm-lock.yamlis the reviewed source dependency graph. Plugin packages bundle runtime dependencies by default; native-heavy plugins resolve them at install time from exact-pinned direct dependencies, and the rootopenclawpackage also resolves dependencies at install time. Root and plugin tarballs ship neithernpm-shrinkwrap.jsonnorpackage-lock.json. See Dependency locking. - Secure file operations: OpenClaw uses
@openclaw/fs-safefor root-bounded file access, atomic writes, archive extraction, temp workspaces, and secret-file helpers. Optional native acceleration defaults off; setOPENCLAW_FS_SAFE_NATIVE_MODE=autoto use an installed platform binding orrequireto fail closed when native support is unavailable. Details: Secure file operations. - Shared Slack workspace risk: if everyone in Slack can message the bot, the core risk is delegated tool authority - any allowed sender can induce tool calls (
exec, browser, network/file tools) within the agent’s policy, prompt/content injection from one sender can affect shared state/devices/outputs, and if the shared agent has sensitive credentials/files, any allowed sender can potentially drive exfiltration via tool usage. Use separate agents/gateways with minimal tools for team workflows; keep personal-data agents private. - Company-shared agent (acceptable pattern): fine when everyone using the agent is in the same trust boundary (for example one company team) and the agent is strictly business-scoped. Run it on a dedicated machine/VM/container, use a dedicated OS user + dedicated browser/profile/accounts, and do not sign that runtime into personal Apple/Google accounts or personal password-manager/browser profiles. Mixing personal and company identities on the same runtime collapses the separation and increases personal-data exposure risk.
Secrets on disk
Assume anything under~/.openclaw/ (or $OPENCLAW_STATE_DIR/) may contain secrets or private data:
Credential storage map
Also useful for backup decisions:- WhatsApp:
~/.openclaw/credentials/whatsapp/<accountId>/creds.json - Telegram bot token: config/env or
channels.telegram.tokenFile(regular file only; symlinks rejected) - Discord bot token: config/env or SecretRef (env/file/exec/store providers)
- Slack tokens: config/env (
channels.slack.*) - Pairing allowlists:
~/.openclaw/credentials/<channel>-allowFrom.json(default account) /<channel>-<accountId>-allowFrom.json(non-default accounts) - Model auth profiles:
~/.openclaw/agents/<agentId>/agent/openclaw-agent.sqlite(auth_profile_store) - MCP OAuth sessions:
~/.openclaw/state/openclaw.sqlite(mcp_oauth_stores) - Legacy OAuth import:
~/.openclaw/credentials/oauth.json
700 on dirs, 600 on files); use full-disk encryption on the gateway host; prefer a dedicated OS user account if the host is shared.
File permissions
~/.openclaw/openclaw.json:600(user read/write only)~/.openclaw:700(user only)
openclaw doctor can warn and offer to tighten these.
Workspace .env files
OpenClaw loads workspace-local .env files for agents and tools, but never lets them silently override gateway runtime controls:
- Provider credential environment variables are blocked from untrusted workspace
.envfiles - for exampleGEMINI_API_KEY,GOOGLE_API_KEY,XAI_API_KEY,MISTRAL_API_KEY,GROQ_API_KEY,DEEPSEEK_API_KEY,PERPLEXITY_API_KEY,BRAVE_API_KEY,TAVILY_API_KEY,EXA_API_KEY,FIRECRAWL_API_KEY, and provider auth keys declared by installed trusted plugins. Put provider credentials in the Gateway process environment,~/.openclaw/.env($OPENCLAW_STATE_DIR/.env), the configenvblock, or an optional login-shell import instead. - Any key starting with
OPENCLAW_is blocked from untrusted workspace.envfiles, reserving the whole runtime namespace so a futureOPENCLAW_*control is fail-closed by default rather than silently inheritable from checked-in or attacker-supplied.envcontent. - Channel and provider endpoint-routing settings are also blocked from workspace
.envoverrides (for exampleMATRIX_HOMESERVER,MATTERMOST_URL,IRC_HOST,SYNOLOGY_CHAT_INCOMING_URL,AZURE_SPEECH_ENDPOINT, and other keys ending in_ENDPOINT), so a cloned workspace cannot redirect bundled connector traffic through local endpoint config. These must come from the gateway process environment, global runtime dotenv, explicit config, orenv.shellEnv. - Trusted process/OS environment variables, global runtime dotenv, config
env, and enabled login-shell import still apply - this only constrains workspace.envfile loading.
.env files frequently live next to agent code, get committed by accident, or get written by tools; blocking provider credentials prevents a cloned workspace from substituting attacker-controlled provider accounts.
Logs and transcripts
OpenClaw stores session transcripts on disk under~/.openclaw/agents/<agentId>/sessions/*.jsonl for session continuity and optional memory indexing - any process/user with filesystem access can read them. Treat disk access as the trust boundary and lock down ~/.openclaw permissions; run agents under separate OS users or hosts for stronger isolation.
Gateway logs may include tool summaries, errors, and URLs; session transcripts can include pasted secrets, file contents, command output, and links.
- Log/transcript redaction is always on and cannot be disabled by config.
- Add custom patterns for your environment via
logging.redactPatterns(tokens, hostnames, internal URLs). - When sharing diagnostics, prefer
openclaw status --all(pasteable, secrets redacted) over raw logs. - Prune old session transcripts and log files if you do not need long retention.
Secret scanning
CI runs the in-reposcripts/detect-private-keys.mts scanner over every tracked regular file except colocated *.test.ts fixtures and the iOS Fastfile; pull requests run the base branch’s copy of the scanner and fail if the base branch lacks it. The local detect-private-key pre-commit hook runs the same scanner over the text files pre-commit hands it. If CI fails, remove or rotate the committed key material, then reproduce locally: