-
-
Notifications
You must be signed in to change notification settings - Fork 69.5k
Loopback token-auth CLI connects but RPC is scope-limited (missing operator.read/write) #46650
Description
Summary
openclaw CLI can connect successfully to a local loopback gateway over shared token auth, but the session lands in a scope-limited operator state and RPC calls fail with errors like:
missing scope: operator.readmissing scope: operator.write
This breaks control-plane operations such as:
openclaw gateway probeopenclaw cron addopenclaw cron runs
Environment
- OpenClaw package version:
2026.3.13 - Gateway mode:
local - Gateway bind:
loopback - Gateway auth mode:
token - Target URL:
ws://127.0.0.1:18789 - CLI invoked from Cedric via
exec, using the localopenclawCLI
Repro
From the same machine as the gateway:
openclaw gateway probe --token <gateway-token> --url ws://127.0.0.1:18789Observed result:
- transport/auth connect succeeds
- but probe reports degraded RPC auth, e.g.
Reachable: yes
Connect: ok
RPC: limited - missing scope: operator.read
And in gateway logs we see:
[ws] ⇄ res ✗ status 1ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ system-presence 1ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
[ws] ⇄ res ✗ config.get 1ms errorCode=INVALID_REQUEST errorMessage=missing scope: operator.read
Same class of failure affects cron add / cron runs through the same path.
What we checked already
1. Pairing/auth files looked correct
We verified both of these files contained operator scopes including read/write:
~/.openclaw/identity/device-auth.json~/.openclaw/devices/paired.json
Scopes present:
operator.adminoperator.approvalsoperator.pairingoperator.readoperator.write
We also restarted the gateway after correcting a mismatch there. The problem persisted.
2. Internal code path investigation
The installed code suggests this local-loopback path intentionally avoids attaching device identity for token/password-authenticated gateway calls.
In our local build we found:
Client side
dist/auth-profiles-*.js
function shouldAttachDeviceIdentityForGatewayCall(params) {
if (!(params.token || params.password)) return true;
try {
const parsed = new URL(params.url);
return ![
"127.0.0.1",
"::1",
"localhost"
].includes(parsed.hostname);
} catch {
return true;
}
}And the gateway client is built with:
deviceIdentity: shouldAttachDeviceIdentityForGatewayCall({
url,
token,
password
}) ? loadOrCreateDeviceIdentity() : void 0,Server side
dist/gateway-cli-*.js
We found:
function roleCanSkipDeviceIdentity(role, sharedAuthOk) {
return role === "operator" && sharedAuthOk;
}and missing-device handling that can clear scopes when no bound device is present:
const clearUnboundScopes = () => {
if (scopes.length > 0) {
scopes = [];
connectParams.scopes = scopes;
}
};This appears to produce an awkward state where:
- shared auth succeeds
- connection is allowed
- but effective operator scopes end up empty / limited
- so subsequent RPC authorization fails
3. Temporary local patch attempt
As a diagnostic only, we patched shouldAttachDeviceIdentityForGatewayCall(...) to always return true in the installed dist bundles.
That still did not fully fix the issue.
So the problem seems deeper than only the loopback identity gate.
Current diagnosis
Most likely the CLI is ending up in a partially authorized operator session on this loopback shared-auth path:
- connect succeeds
- operator role is accepted
- but the client does not arrive with a fully usable device-token-backed scope set for RPC
- and the client does not automatically upgrade/retry out of this degraded state
In other words:
local loopback + shared token auth can connect, but still leave the operator client scope-limited for gateway RPC.
Why this matters
This blocks a robust local operator workflow where the local openclaw CLI is expected to safely perform:
- cron registration
- cron inspection
- gateway probe/status
- other control-plane operations
Without this, local automation that depends on control-plane CLI operations becomes much harder to make reliable.
Questions / expected behavior
I think one of these should be true:
- Local loopback shared-auth operator CLI calls should attach device identity and establish a fully scoped operator session, or
- Local shared-auth operator CLI calls that are intentionally allowed without device identity should still preserve requested operator scopes for RPC, or
- The CLI should detect this degraded state and explicitly retry/upgrade into a device-token-backed operator session instead of silently succeeding at connect and failing later on read/write/admin RPCs.
Request
Could you confirm whether this is expected behavior or a bug?
If it is a bug, I’d appreciate guidance on the intended fix path for:
- local loopback token-authenticated operator CLI
- from the same machine as the gateway
- where downstream RPC methods need full operator scopes
If useful, I can also provide a smaller repro focused only on gateway probe.