diff --git a/SECURITY.md b/SECURITY.md index 9276aef7283..31425d6ace9 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -39,6 +39,7 @@ For fastest triage, include all of the following: - Reproducible PoC against latest `main` or latest released version. - Demonstrated impact tied to OpenClaw's documented trust boundaries. - For exposed-secret reports: proof the credential is OpenClaw-owned (or grants access to OpenClaw-operated infrastructure/services). +- Explicit statement that the report does not rely on adversarial operators sharing one gateway host/config. - Scope check explaining why the report is **not** covered by the Out of Scope section below. Reports that miss these requirements may be closed as `invalid` or `no-action`. @@ -75,11 +76,20 @@ The best way to help the project right now is by sending PRs. When patching a GHSA via `gh api`, include `X-GitHub-Api-Version: 2022-11-28` (or newer). Without it, some fields (notably CVSS) may not persist even if the request returns 200. +## Operator Trust Model (Important) + +OpenClaw does **not** model one gateway as a multi-tenant, adversarial user boundary. + +- Authenticated Gateway callers are treated as trusted operators for that gateway instance. +- Session identifiers (`sessionKey`, session IDs, labels) are routing controls, not per-user authorization boundaries. +- If one operator can view data from another operator on the same gateway, that is expected in this trust model. +- If you need adversarial-user isolation, split by trust boundary (separate OS users/hosts/gateways). + ## Out of Scope - Public Internet Exposure - Using OpenClaw in ways that the docs recommend not to -- Deployments where mutually untrusted/adversarial operators share one gateway host and config +- Deployments where mutually untrusted/adversarial operators share one gateway host and config (for example, reports expecting per-operator isolation for `sessions.list`, `sessions.preview`, `chat.history`, or similar control-plane reads) - Prompt injection attacks - Reports that require write access to trusted local state (`~/.openclaw`, workspace files like `MEMORY.md` / `memory/*.md`) - Reports that depend on trusted operator-supplied configuration values to trigger availability impact (for example custom regex patterns). These may still be fixed as defense-in-depth hardening, but are not security-boundary bypasses. diff --git a/docs/gateway/security/index.md b/docs/gateway/security/index.md index 3cee5259a0a..1374f5d522a 100644 --- a/docs/gateway/security/index.md +++ b/docs/gateway/security/index.md @@ -38,6 +38,15 @@ OpenClaw assumes the host and config boundary are trusted: - Running one Gateway for multiple mutually untrusted/adversarial operators is **not a recommended setup**. - For mixed-trust teams, split trust boundaries with separate gateways (or at minimum separate OS users/hosts). +### Practical consequence (operator trust boundary) + +Inside one Gateway instance, authenticated operator access is a trusted control-plane role, not a per-user tenant role. + +- Operators with read/control-plane access can inspect gateway session metadata/history by design. +- Session identifiers (`sessionKey`, session IDs, labels) are routing selectors, not authorization tokens. +- Example: expecting per-operator isolation for methods like `sessions.list`, `sessions.preview`, or `chat.history` is outside this model. +- If you need adversarial-user isolation, run separate gateways per trust boundary. + ## Trust boundary matrix Use this as the quick model when triaging risk: @@ -57,6 +66,7 @@ These patterns are commonly reported and are usually closed as no-action unless - Prompt-injection-only chains without a policy/auth/sandbox bypass. - Claims that assume hostile multi-tenant operation on one shared host/config. +- Claims that classify normal operator read-path access (for example `sessions.list`/`sessions.preview`/`chat.history`) as IDOR in a shared-gateway setup. - Localhost-only deployment findings (for example HSTS on loopback-only gateway). - Discord inbound webhook signature findings for inbound paths that do not exist in this repo. - "Missing per-user authorization" findings that treat `sessionKey` as an auth token.