Context
Follow-up to #27494 (fixed in 9c14299, closed as completed). The fix regressed in v2026.4.1.
What happened
The original fix (9c14299) correctly added && !sharedAuthOk to clearUnboundScopes(). However, commit 8b88b92 (gateway: clear unbound scopes for trusted-proxy auth, #57692) refactored the scope-clearing logic into a new shouldClearUnboundScopesForMissingDeviceIdentity() function in connect-policy.ts, and the refactor re-introduced the original bug.
Why it regressed
The new function explicitly clears scopes for authMethod === "token" || authMethod === "password":
export function shouldClearUnboundScopesForMissingDeviceIdentity(params) {
return (
params.decision.kind !== "allow" ||
(!params.controlUiAuthPolicy.allowBypass &&
!params.preserveInsecureLocalControlUiScopes &&
(params.authMethod === "token" || // ← catches API clients
params.authMethod === "password" || // ← catches API clients
params.authMethod === "trusted-proxy" ||
params.trustedProxyAuthOk === true))
);
}
When decision.kind === "allow" (operator + sharedAuthOk), scopes should be preserved. But the second branch of the || still returns true for token/password auth methods, causing scopes to be wiped.
Same use case
Agent orchestration hub connecting as operator with ["operator.read", "operator.write"] scopes via shared gateway token (gateway.auth.token), no device identity. The connection is accepted but chat.send / chat.history fail with missing scope: operator.read / operator.write.
Suggested fix
The function should check sharedAuthOk (or equivalent) to preserve scopes for authenticated operator API clients without device identity, matching the intent of the original fix in 9c14299.
Environment
- OpenClaw: v2026.4.1
- Connection: local WebSocket, operator role, shared token auth
- Scopes requested:
["operator.read", "operator.write"]
Context
Follow-up to #27494 (fixed in 9c14299, closed as completed). The fix regressed in v2026.4.1.
What happened
The original fix (9c14299) correctly added
&& !sharedAuthOktoclearUnboundScopes(). However, commit 8b88b92 (gateway: clear unbound scopes for trusted-proxy auth, #57692) refactored the scope-clearing logic into a newshouldClearUnboundScopesForMissingDeviceIdentity()function inconnect-policy.ts, and the refactor re-introduced the original bug.Why it regressed
The new function explicitly clears scopes for
authMethod === "token" || authMethod === "password":When
decision.kind === "allow"(operator + sharedAuthOk), scopes should be preserved. But the second branch of the||still returnstruefor token/password auth methods, causing scopes to be wiped.Same use case
Agent orchestration hub connecting as
operatorwith["operator.read", "operator.write"]scopes via shared gateway token (gateway.auth.token), no device identity. The connection is accepted butchat.send/chat.historyfail withmissing scope: operator.read/operator.write.Suggested fix
The function should check
sharedAuthOk(or equivalent) to preserve scopes for authenticated operator API clients without device identity, matching the intent of the original fix in 9c14299.Environment
["operator.read", "operator.write"]