# Security Hardening Guide Comprehensive security hardening guide for Mission Control and OpenClaw Gateway deployments. ## Quick Assessment Run the automated security audit: ```bash bash scripts/security-audit.sh # Check .env and configuration bash scripts/station-doctor.sh # Check runtime health ``` Or use the diagnostics API (admin only): ```bash curl -H "x-api-key: $API_KEY" http://localhost:3000/api/diagnostics curl -H "x-api-key: $API_KEY" http://localhost:3000/api/security-audit?timeframe=day ``` The `posture.score` field (0-100) gives a quick posture assessment. The **Security Audit Panel** (`/security` in the dashboard) provides a full real-time view with timeline charts, agent trust scores, and eval results. --- ## Mission Control Hardening ### 1. Credentials **Generate strong credentials** using the included script: ```bash bash scripts/generate-env.sh # Generates .env with random secrets chmod 600 .env # Lock down permissions ``` The installer (`install.sh`) does this automatically. If you set up manually, ensure: - `AUTH_PASS` is 12+ characters, not a dictionary word - `API_KEY` is 32+ hex characters - `AUTH_SECRET` is a unique random string - `.env` file permissions are `600` ### 2. Network Access Control Mission Control uses a host allowlist in production: ```env # Only allow connections from these hosts (comma-separated) MC_ALLOWED_HOSTS=localhost,127.0.0.1 # For Tailscale: MC_ALLOWED_HOSTS=localhost,127.0.0.1,100.* # For a domain: MC_ALLOWED_HOSTS=mc.example.com,localhost # NEVER set this in production: # MC_ALLOW_ANY_HOST=1 ``` Deploy behind a reverse proxy with TLS (Caddy, nginx, Tailscale Funnel) for any network-accessible deployment. ### 3. HTTPS & Cookies For HTTPS deployments: ```env MC_COOKIE_SECURE=1 # Cookies only sent over HTTPS MC_COOKIE_SAMESITE=strict # CSRF protection MC_ENABLE_HSTS=1 # HTTP Strict Transport Security ``` ### 4. Rate Limiting Rate limiting is enabled by default: | Endpoint Type | Limit | |--------------|-------| | Login | 5 attempts/min (always active) | | Mutations | 60 requests/min | | Reads | 120 requests/min | | Heavy operations | 10 requests/min | | Agent heartbeat | 30/min per agent | | Agent task polling | 20/min per agent | Never set `MC_DISABLE_RATE_LIMIT=1` in production. ### 5. Docker Hardening Use the production compose overlay: ```bash docker compose -f docker-compose.yml -f docker-compose.hardened.yml up -d ``` This enables: - **Read-only filesystem** with tmpfs for `/tmp` and `/app/.next/cache` - **Capability dropping** — all Linux capabilities dropped, only `NET_BIND_SERVICE` retained - **No new privileges** — prevents privilege escalation - **PID limit** — prevents fork bombs - **Memory/CPU limits** — prevents resource exhaustion - **Log rotation** — prevents disk filling from verbose logging - **HSTS, secure cookies** — forced via environment ### 6. Security Headers Mission Control sets these headers automatically: | Header | Value | |--------|-------| | `Content-Security-Policy` | `default-src 'self'; script-src 'self' 'nonce-' 'strict-dynamic'; style-src 'self' 'nonce-'` | | `X-Frame-Options` | `DENY` | | `X-Content-Type-Options` | `nosniff` | | `Referrer-Policy` | `strict-origin-when-cross-origin` | | `Permissions-Policy` | `camera=(), microphone=(), geolocation=()` | | `X-Request-Id` | Unique per-request UUID for log correlation | | `Strict-Transport-Security` | Set when `MC_ENABLE_HSTS=1` | ### 7. Audit Logging All security-relevant events are logged to the audit trail: - Login attempts (success and failure) - Task mutations - User management actions - Settings changes - Update operations Additionally, the **security event system** automatically logs: - Auth failures (invalid passwords, expired tokens, access denials) - Rate limit hits (429 responses with IP/agent correlation) - Injection attempts (prompt injection, command injection, exfiltration) - Secret exposures (AWS keys, GitHub tokens, Stripe keys, JWTs, private keys detected in agent messages) - MCP tool calls (agent, tool, duration, success/failure) These events feed into the **Security Audit Panel** (`/security`) which provides: - **Posture score** (0-100) with level badges (hardened/secure/needs-attention/at-risk) - **Agent trust scores** — weighted calculation based on auth failures, injection attempts, and task success rates - **MCP call audit** — tool-use frequency, success/failure rates per agent - **Timeline visualization** — event density over selected timeframe Configure retention: `MC_RETAIN_AUDIT_DAYS=365` (default: 1 year). ### 8. Hook Profiles Security strictness is tunable via hook profiles in Settings > Security Profiles: | Profile | Secret Scanning | MCP Auditing | Block on Secrets | Rate Limit Multiplier | |---------|----------------|--------------|------------------|----------------------| | **minimal** | Off | Off | No | 2x (relaxed) | | **standard** (default) | On | On | No | 1x | | **strict** | On | On | Yes (blocks messages) | 0.5x (tighter) | Set via the Settings panel or the `hook_profile` key in the settings API. ### 9. Agent Eval Framework The four-layer eval stack helps detect degrading agent quality: - **Output evals** — score task completion against golden datasets - **Trace evals** — convergence scoring (>3.0 indicates looping behavior) - **Component evals** — tool reliability from MCP call logs (p50/p95/p99 latency) - **Drift detection** — 10% threshold vs 4-week rolling baseline triggers alerts Access via `/api/agents/evals` or the Security Audit Panel's eval section. ### 10. Data Retention ```env MC_RETAIN_ACTIVITIES_DAYS=90 # Activity feed MC_RETAIN_AUDIT_DAYS=365 # Security audit trail MC_RETAIN_LOGS_DAYS=30 # Application logs MC_RETAIN_NOTIFICATIONS_DAYS=60 # Notifications MC_RETAIN_PIPELINE_RUNS_DAYS=90 # Pipeline logs MC_RETAIN_TOKEN_USAGE_DAYS=90 # Token/cost records MC_RETAIN_GATEWAY_SESSIONS_DAYS=90 # Gateway session history ``` --- ## OpenClaw Gateway Hardening Mission Control acts as the mothership for your OpenClaw fleet. The installer automatically checks and repairs common OpenClaw configuration issues. ### 1. Network Security - **Never expose the gateway publicly.** It runs on port 18789 by default. - **Bind to localhost:** Set `gateway.bind: "loopback"` in `openclaw.json`. - **Use SSH tunneling or Tailscale** for remote access. - **Docker users:** Be aware that Docker can bypass UFW rules. Use `DOCKER-USER` chain rules. ### 2. Authentication - **Always enable gateway auth** with a strong random token. - Generate: `openclaw doctor --generate-gateway-token` - Store in `OPENCLAW_GATEWAY_TOKEN` env var (never in `NEXT_PUBLIC_*` variables). - Rotate regularly. ### 3. Hardened Gateway Configuration ```json { "gateway": { "mode": "local", "bind": "loopback", "auth": { "mode": "token", "token": "replace-with-long-random-token" } }, "session": { "dmScope": "per-channel-peer" }, "tools": { "profile": "messaging", "deny": ["group:automation", "group:runtime", "group:fs", "sessions_spawn", "sessions_send"], "fs": { "workspaceOnly": true }, "exec": { "security": "deny", "ask": "always" } }, "elevated": { "enabled": false } } ``` ### 4. File Permissions ```bash chmod 700 ~/.openclaw chmod 600 ~/.openclaw/openclaw.json chmod 600 ~/.openclaw/credentials/* ``` ### 5. Tool Security - Apply the principle of least privilege — only grant tools the agent needs. - Audit third-party skills before installing (Mission Control's Skills Hub runs automatic security scans). - Run agents processing untrusted content in a sandbox with a minimal toolset. ### 6. Monitoring - Enable comprehensive logging: `logging.redactSensitive: "tools"` - Store logs separately where agents cannot modify them. - Use Mission Control's diagnostics API to monitor gateway health. - Have an incident response plan: stop gateway, revoke API keys, review audit logs. ### 7. Known CVEs Keep OpenClaw updated. Notable past vulnerabilities: | CVE | Severity | Description | Fixed In | |-----|----------|-------------|----------| | CVE-2026-25253 | Critical | RCE via Control UI token hijack | v2026.1.29 | | CVE-2026-26327 | High | Auth bypass via gateway spoofing | v2026.2.25 | | CVE-2026-26322 | High | SSRF | v2026.2.25 | | CVE-2026-26329 | High | Path traversal | v2026.2.25 | | CVE-2026-26319 | Medium | Missing webhook auth | v2026.2.25 | --- ## Deployment Architecture For production, the recommended architecture is: ``` Internet | [Reverse Proxy (Caddy/nginx) + TLS] | [Mission Control :3000] ---- [SQLite .data/] | [OpenClaw Gateway :18789 (localhost only)] | [Agent Workspaces] ``` - Reverse proxy handles TLS termination, rate limiting, and access control - Mission Control listens on localhost or a private network - OpenClaw Gateway is bound to loopback only - Agent workspaces are isolated per-agent directories --- ## Agent Auth: Least-Privilege Key Guidance ### The Problem The global API key (`API_KEY` env var) grants full `admin` access. When agents use it, they can: - Create/delete other agents - Modify any task or project - Rotate the API key itself - Access all workspaces This violates least-privilege. A compromised agent session leaks admin access. ### Recommended: Agent-Scoped Keys Create per-agent keys with limited scopes: ```bash # Create a scoped key for agent "Aegis" (via CLI) pnpm mc raw --method POST --path /api/agents/5/keys --body '{ "name": "aegis-worker", "scopes": ["viewer", "agent:self", "agent:diagnostics", "tasks:write"], "expires_in_days": 30 }' --json ``` Scoped keys: - Can only act as the agent they belong to (no cross-agent access) - Have explicit scope lists (viewer, agent:self, tasks:write, etc.) - Auto-expire after a set period - Can be revoked without affecting other agents - Are logged separately in the audit trail ### Auth Hierarchy | Method | Role | Use Case | |--------|------|----------| | Agent-scoped key (`mca_...`) | Per-scope | Autonomous agents (recommended) | | Global API key | admin | Admin scripts, CI/CD, initial setup | | Session cookie | Per-user role | Human operators via web UI | | Proxy header | Per-user role | SSO/gateway-authenticated users | ### Monitoring Global Key Usage Mission Control logs a security event (`global_api_key_used`) every time the global API key is used. Monitor these in the audit log: ```bash pnpm mc raw --method GET --path '/api/security-audit?event_type=global_api_key_used&timeframe=day' --json ``` Goal: drive global key usage to zero in production by replacing with scoped agent keys. ### Rate Limiting by Agent Identity Agent-facing endpoints use per-agent rate limiters (keyed by `x-agent-name` header): - Heartbeat: 30/min per agent - Task polling: 20/min per agent - Self-registration: 5/min per IP This prevents a runaway agent from consuming the entire rate limit budget. --- ## Rate Limit Backend Strategy Current: in-memory `Map` per process (suitable for single-instance deployments). For multi-instance deployments, the rate limiter supports a pluggable backend via the `createRateLimiter` factory. Future options: - **Redis**: shared state across instances (use Upstash or self-hosted) - **SQLite WAL**: leverage the existing DB for cross-process coordination - **Edge KV**: for edge-deployed instances The current implementation includes: - Periodic cleanup (60s interval) - Capacity-bounded maps (default 10K entries, LRU eviction) - Trusted proxy IP parsing (`MC_TRUSTED_PROXIES`) No action needed for single-instance deployments. For multi-instance, implement a custom `RateLimitStore` interface when scaling beyond 1 node.