openclaw - ✅(Solved) Fix [Bug]: clearUnboundScopes strips operator scopes unconditionally for non-local token-auth clients [1 pull requests, 6 comments, 5 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#51396Fetched 2026-04-08 01:11:43
View on GitHub
Comments
6
Participants
5
Timeline
12
Reactions
0
Timeline (top)
commented ×6cross-referenced ×3labeled ×2referenced ×1

In 2026.3.13, clearUnboundScopes() unconditionally strips all operator scopes for non-local clients without device identity, even when token auth succeeds. This breaks chat.send (and any operator.write-scoped method) for backend clients connecting over a network with valid --token auth.

Root Cause

In 2026.3.13, clearUnboundScopes() unconditionally strips all operator scopes for non-local clients without device identity, even when token auth succeeds. This breaks chat.send (and any operator.write-scoped method) for backend clients connecting over a network with valid --token auth.

Fix Action

Fixed

PR fix notes

PR #51413: fix(gateway): retain operator scopes for non-local token-auth clients

Description (problem / solution / changelog)

Summary

Describe the problem and fix in 2-5 bullets:

  • Problem: clearUnboundScopes() unconditionally strips operator scopes for non-local clients without device identity, even when token auth succeeds. This breaks chat.send and other operator.write-scoped methods for backend clients connecting over network with valid --token auth.
  • Why it matters: Backend clients authenticating with a valid token over a remote connection get their requested scopes stripped, while localhost works fine. This prevents valid token-authenticated operators from using write methods.
  • What changed: In evaluateMissingDeviceIdentity, treat authOk + authMethod token/password as sufficient for operator device-skip (alongside sharedAuthOk), so non-local token-auth clients retain their self-declared scopes.
  • What did NOT change (scope boundary): No change to Control UI, device pairing, or trusted-proxy auth. Only fixes the operator + token/password path when sharedAuthOk might disagree with primary auth.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #51396
  • Related #

User-visible / Behavior Changes

Non-local backend clients connecting with valid token auth now retain their requested scopes (e.g. operator.admin), so chat.send and other operator.write methods work as they do for localhost.

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation: N/A

Repro + Verification

Environment

  • OS: Debian 12 (per issue); Windows 10 (local verification)
  • Runtime/container: Node / npm global
  • Model/provider: anthropic/opus-4.6
  • Integration/channel (if any): openclaw gateway with --bind tailnet --token
  • Relevant config (redacted): Gateway token auth

Steps

  1. Start gateway with openclaw gateway --bind tailnet --token <token>
  2. Connect from a remote host (non-loopback) via WebSocket with valid token in auth.token and scopes: ["operator.admin"]
  3. Call chat.send

Expected

  • Connection succeeds; chat.send succeeds (operator.admin implies operator.write).

Actual

  • Before fix: missing scope "operator.write". After fix: scopes retained, chat.send works.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

connect-policy.test.ts includes a regression test: operator + sharedAuthOk=false but authOk=true + authMethod=token + isLocalClient=false now returns allow. All tests pass.

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios: Ran pnpm exec vitest run src/gateway/server/ws-connection/connect-policy.test.ts 鈥?all tests pass.
  • Edge cases checked: Existing tests for operator+sharedAuthOk, Control UI, trusted-proxy, node role remain correct.
  • What you did not verify: End-to-end remote WebSocket connect with real gateway (no local repro of exact issue setup).

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

If a bot review conversation is addressed by this PR, resolve that conversation yourself. Do not leave bot review conversation cleanup for maintainers.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps: N/A

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Revert the commit; no feature flags.
  • Files/config to restore: src/gateway/server/ws-connection/connect-policy.ts, connect-policy.test.ts, message-handler.ts
  • Known bad symptoms reviewers should watch for: None anticipated.

Risks and Mitigations

List only real risks for this PR. Add/remove entries as needed. If none, write None.

None. The change narrows the condition under which scopes are stripped; token-authenticated operators already pass auth and are trusted. No new trust boundary is introduced.

Changed files

  • src/gateway/server/ws-connection/connect-policy.test.ts (modified, +17/-0)
  • src/gateway/server/ws-connection/connect-policy.ts (modified, +10/-1)
  • src/gateway/server/ws-connection/message-handler.ts (modified, +2/-1)
RAW_BUFFERClick to expand / collapse

Bug type

Regression (worked before, now fails)

Summary

In 2026.3.13, clearUnboundScopes() unconditionally strips all operator scopes for non-local clients without device identity, even when token auth succeeds. This breaks chat.send (and any operator.write-scoped method) for backend clients connecting over a network with valid --token auth.

Steps to reproduce

  1. Start gateway with openclaw gateway --bind tailnet --token <secret>
  2. Connect from a remote host (non-loopback) via WebSocket with valid token in auth.token and scopes: ["operator.admin"]
  3. Connection succeeds (hello-ok)
  4. Call chat.send → rejected with missing scope: operator.write

Connecting from localhost with the same token works fine.

Expected behavior

Non-local clients authenticating with a valid token should retain their requested scopes (same as localhost behavior).

Actual behavior

missing scope "operator.write" message received

OpenClaw version

2026.3.13

Operating system

Debian 12

Install method

npm global

Model

anthropic/opus-4.6

Provider / routing chain

openclaw -> anthropic

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

No response

extent analysis

Fix Plan

To resolve the issue, we need to modify the clearUnboundScopes function to conditionally strip operator scopes based on the client's authentication status and device identity.

Step-by-Step Solution

  1. Identify the clearUnboundScopes function: Locate the clearUnboundScopes function in the OpenClaw gateway codebase.
  2. Modify the function: Update the function to check if the client has a valid token authentication before stripping operator scopes.
function clearUnboundScopes(scopes, client) {
  if (client.tokenAuth && client.tokenAuth.success) {
    // Do not strip operator scopes for clients with valid token auth
    return scopes;
  } else {
    // Strip operator scopes for non-local clients without device identity
    return scopes.filter(scope => !scope.startsWith('operator.'));
  }
}
  1. Update the gateway configuration: Ensure that the gateway is configured to use the updated clearUnboundScopes function.

Verification

To verify the fix, repeat the steps to reproduce the issue:

  1. Start the gateway with the updated configuration.
  2. Connect from a remote host via WebSocket with a valid token in auth.token and scopes: ["operator.admin"].
  3. Call chat.send and verify that the operation succeeds without a "missing scope" error.

Extra Tips

  • Ensure that the tokenAuth property is properly set and updated for clients with valid token authentication.
  • Review the gateway's authentication and authorization logic to prevent similar issues in the future.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Non-local clients authenticating with a valid token should retain their requested scopes (same as localhost behavior).

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: clearUnboundScopes strips operator scopes unconditionally for non-local token-auth clients [1 pull requests, 6 comments, 5 participants]