Skip to content

RFE: gateway.auth.tokenScopes config field for headless/single-tenant deployments #80836

Description

@jchoi-atn

Problem

In headless / single-tenant deployments (ours runs OpenClaw inside an ECS Fargate container, with the agent and the CLI on the same host), operator-scope upgrades require an interactive approval flow that doesn't apply to the deployment model. Each time OpenClaw tightens default scopes — most recently 2026.5.7's hardening that requires operator.write for cron mutations — every paired device in our fleet generates a scope-upgrade approval request and gets blocked until a human approves it via the operator UI.

In our case, the requests come from devices we already trust (our own ECS containers running our own agents), but there's no way to express that trust statically in openclaw.json. Token-auth bypasses the device-identity gate for read commands via roleCanSkipDeviceIdentity("operator", true) = true, but mutating commands re-enter the device-identity check at a stricter scope, which the token-auth bypass doesn't cover.

Today's workaround on our end was an operator UI approval after each hardening bump. That doesn't scale — every new scope OpenClaw adds in the future will recreate the same wall.

Proposed config

Add a tokenScopes field to GatewayAuthConfig (src/config/types.gateway.ts):

auth: {
  mode: "token",
  token: "...",
  // NEW: when a request is authenticated via the shared token (token mode), resolve
  // the session's effective scopes to this set instead of the default operator.read.
  tokenScopes?: OperatorScope[];
}

Example usage in openclaw.json:

{
  "gateway": {
    "mode": "local",
    "bind": "loopback",
    "auth": {
      "mode": "token",
      "token": "<per-boot random secret>",
      "tokenScopes": ["operator.admin", "operator.pairing", "operator.read", "operator.write"]
    }
  }
}

Semantics

  • When auth.mode === "token" and tokenScopes is present, a successful token-auth handshake resolves to a session with exactly those scopes (not operator's default scope set).
  • When tokenScopes is absent or empty, behavior is unchanged from today (defaults apply).
  • The scopes a config can grant should be bounded — e.g., operator.admin should be permissible only for bind: "loopback" (or behind an explicit allowAdminTokenScopes: true flag) so a public-facing deployment can't accidentally grant admin to anyone with the shared token.

Why this matters

Two real use cases:

  1. Headless deployments like ours (ECS Fargate, agent + CLI in the same container, no human operator in the loop). Every scope hardening bump silently breaks cron skills until a human approves.
  2. Bootstrap / fresh install. New devices today land on operator.read only and need scope upgrades for any non-trivial work. A config-level declaration of "this deployment is trusted to grant itself these scopes" short-circuits the bootstrap dance.

Why not workarounds

  • Pre-write identity/device-auth.json at boot. Requires the gateway to have already booted to generate device.json with a deviceId — multi-stage bootstrap with race conditions, hard to make reliable.
  • Run openclaw devices approve from inside the container. Requires admin-scoped device pairing, which is circular (that's what we're trying to avoid needing in the first place).
  • Trust the existing roleCanSkipDeviceIdentity bypass. It only applies to operator role with sharedAuthOk, which is sufficient for read commands but not for cron mutations or admin-scope operations. Adding more bypass cases there fragments the logic; a clean config field is more maintainable.

Environment

  • OpenClaw version: 2026.5.7 (the hardening that surfaced this for us)
  • Our fleet: 14 agents on ECS Fargate, each a separate container with its own gateway + agent process. All loopback CLI.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:auth-providerAuth, provider routing, model choice, or SecretRef resolution may break.impact:securitySecurity boundary, credential, authz, sandbox, or sensitive-data risk.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.maturity:stableIssue affects a taxonomy feature currently scored M4/M5.staleMarked as stale due to inactivity

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions