Skip to content

CLI gateway calls can poison local device scopes after read probes #95997

Description

@vincentkoc

Summary

Local CLI Gateway calls can leave the CLI paired device/token at a read-only scope after a read probe, then reject the next write-scoped CLI agent call with scope upgrade pending approval.

This is a stable-release blocker unless we decide the affected local state is intentionally expected, because the embedded fallback can hide the failure while the primary Gateway agent path is blocked.

Affected Surface

  • Local Gateway auth with shared token/password.
  • CLI clients using Gateway RPCs before an agent run, especially gateway health or other read-scoped probes followed by agent or another write-scoped call.
  • Observed during 2026.6.10 beta release smoke, but the failing path is present on current main.

Steps to Reproduce

  1. Start a local Gateway with token auth enabled.
  2. Run a CLI read-scoped RPC such as gateway health with the shared token.
  3. Run a CLI write-scoped agent command with the same local Gateway/session.
  4. Watch the Gateway close the primary agent connection with pairing scope-upgrade state.

Expected

Local CLI shared-token/password calls should not persist or reuse a durable read-scoped paired-device baseline that blocks later local CLI write/admin calls.

The security rule still needs to hold: an already-paired device reconnecting with a device identity must not silently widen scopes. Remote CLI/device-token paths should keep requiring explicit scope-upgrade approval.

Actual

The read probe can persist or reuse the CLI paired device at operator.read. A later agent run needs operator.write, so the server treats it as a paired-device scope upgrade and rejects the primary Gateway path.

Redacted audit shape:

security audit: device access upgrade requested reason=scope-upgrade auth=token roleFrom=operator roleTo=operator scopesFrom=operator.read scopesTo=operator.write client=cli

Observed client close:

1008 pairing required: device is asking for more scopes than currently approved

Root Cause

  • CLI calls derive least-privilege scopes per method. health maps to operator.read; agent maps to operator.write.
  • The client path carried a durable CLI device identity even when the caller already used loopback shared-token/password auth.
  • The server clears self-declared scopes for generic device-less shared-token clients, but had only a backend gateway-client exception for local shared-auth scope preservation.
  • Result: read-only CLI device state could become the baseline for later write-scoped local CLI calls.

Provenance

The broken behavior is the interaction between those pieces, not the scope-upgrade guard itself.

Fix Shape

  1. Keep paired-device scope-upgrade enforcement unchanged.
  2. Omit durable device identity for loopback CLI shared-token/password calls.
  3. Preserve declared scopes server-side only for local, non-browser CLI shared-token/password auth.
  4. Keep generic device-less shared-token/password clients scope-cleared.
  5. Add regression coverage for client identity omission, server scope preservation, and the stale read-scoped CLI baseline.

Metadata

Metadata

Assignees

Labels

P1High-priority user-facing bug, regression, or broken workflow.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.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.maintainerMaintainer-authored PR

Type

No type

Fields

Priority

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions