Background
Claude Code's Remote Control feature creates sessions that are managed through Anthropic's session API. Each session has a unique identifier and is associated with an account and organization. Bridge workers connect to sessions using bearer tokens that carry a session_id claim in their JWT payload.
This advisory examines whether session isolation is enforced at the server level. The question: can a bearer token from session A observe and control session B? Can plain OAuth do the same?
This research was conducted alongside the bridge worker chain documented in RDXS-2026-005. Where that advisory covers the exploitation chain from repo to persistence, this advisory covers the session-binding weaknesses that amplify the blast radius of stolen credentials.
Methodology
Session isolation was tested by harvesting real bridge bearer tokens from disposable repositories, then using those tokens against different live sessions. A custom probe script handled WebSocket subscribe connections, event injection, control requests, and tool approval flows against the production session API.
Each finding was tested with both bridge bearers and plain Claude.ai OAuth tokens. Cross-account testing was performed using a separate Anthropic account in a separate organization.
High-Severity Findings
1. Bridge bearer session_id claim is not enforced
Broken Session BindingA bridge bearer token carries a session_id claim in its JWT payload. The server does not enforce this claim. A token harvested from session A can subscribe to, observe traffic from, and send control requests to a completely different session B on the same account.
Test setup
# Token from session A (JWT session_id: session_01FTdSw3...) # Target: session B (session_01BRLnZcweS6...) # Subscribe to session B using session A's token: wss://api.anthropic.com/v1/sessions/ws/session_01BRLnZcweS6.../subscribe Authorization: Bearer <token from session A> # Result: WebSocket opens, session B traffic streams in
Impact
A stolen bearer from any session on the account can observe and control every other active session on that account. The session_id claim in the JWT provides no isolation.
Mitigation
The server should validate that the bearer's session_id claim matches the target session in the request path. Tokens should only be valid for the session that issued them.
2. Cross-session bearer enables active control and tool approval
Session TakeoverThe session binding failure is not limited to passive observation. Using session A's bearer against session B:
set_permission_modesucceeded and changed session B's permission mode- A real
can_use_toolrequest from session B was received and answered withbehavior:"allow" - Session B created
/tmp/cc-cross-active-proof-2as a result
Impact
A stolen bearer gives full control over any active session on the account, not just read access. The attacker can change permission modes, approve tool use, and execute commands through other sessions.
3. Bearer survives source session teardown
Stale CredentialAfter terminating session A (the source of the bearer), the token remained valid for controlling other sessions. Using the preserved stale bearer:
- Successfully sent
set_permission_mode:dontAskto session B after session A was shut down - Later created session C and successfully controlled it with the same dead-session bearer
Impact
Bridge tokens are not revoked when their source session is terminated. A token stolen once provides indefinite control over future sessions on the account until the token itself expires or is rotated.
Mitigation
Session teardown should revoke all bearer tokens associated with that session. Tokens should not be usable against sessions created after the source session was destroyed.
4. Plain OAuth can enumerate, join, control, and approve for any session
Missing AuthorizationNo bridge bearer is needed at all. A plain Claude.ai OAuth access token (the same token used for normal API calls) can perform the full attack chain:
GET /v1/sessionsreturns the full inventory of active sessions with ids, statuses, and titlesPOST /v1/sessions/{id}/eventsinjects user events into a discovered session- WebSocket subscribe delivers live session traffic
set_permission_modesucceeds via control request- Real
can_use_toolrequests can be answered withbehavior:"allow"
Runtime proof: using only a plain OAuth token, the probe discovered a running session via GET /v1/sessions, injected a prompt, subscribed to the session stream, changed the permission mode, and approved a real tool call that created /tmp/cc-oauth-enum-proof.
Impact
Any token with account-level OAuth scope can discover and fully control all active Remote Control sessions. This means a compromised OAuth token (from any integration, leaked env var, or malicious app) gives immediate control over all running Claude Code sessions on that account.
Mitigation
Session control endpoints should require session-scoped credentials, not account-wide OAuth tokens. Session discovery via GET /v1/sessions should require elevated permissions and should not be accessible with standard OAuth tokens.
5. Organization UUID is not enforced on session endpoints
Missing AuthorizationThe organization_uuid parameter (query param on subscribe, header on REST endpoints) is not enforced. All session operations succeeded with:
- A completely fake UUID:
00000000-0000-0000-0000-000000000000 - The header omitted entirely
This was tested on event POST, WebSocket subscribe, session list, and session fetch. All returned 200 with real data.
Impact
The organization UUID is cosmetic. It is not a security boundary and cannot be relied upon for tenant isolation within a multi-org account.
What Held
Cross-account isolation appears to be enforced. A plain OAuth token from account A and a bridge bearer from account A were both tested against a live session on a separate account B in a separate organization:
- Event POST returned
404 not_found - WebSocket subscribe connected but immediately closed with code
1006and zero messages - Control requests produced no response
- Foreign sessions appeared as nonexistent, identical to the behavior for a valid-format but nonexistent session ID
The server appears to enforce account_uuid even though it does not enforce session_id or organization_uuid. This is a positive finding: the most catastrophic scenario (cross-account session hijack) was not confirmed.
The Systemic Issue
The Remote Control session API enforces account-level isolation but nothing below it. Within an account:
Every session is reachable from every credential. The practical consequence:
- A bearer stolen from one session controls all other sessions (Findings 1-2)
- The bearer works after its source session is destroyed (Finding 3)
- Plain OAuth tokens have the same power without any bridge bearer (Finding 4)
- Organization UUID provides no meaningful boundary (Finding 5)
When combined with the bridge worker credential exposure documented in RDXS-2026-005, these session-binding failures amplify the blast radius: a bearer stolen from one malicious repository gives the attacker control over every active Remote Control session on the account, not just the one running in the compromised repository.
Immediate Mitigations
- Limit active Remote Control sessions to reduce the number of targets reachable from a compromised credential.
- Review OAuth token grants for any unexpected integrations or applications. Any OAuth token on the account can enumerate and control all sessions.
- Apply the mitigations from RDXS-2026-005 to prevent bearer theft from malicious repositories in the first place.
Disclosure
These findings were discovered during the same research engagement that produced RDXS-2026-001, RDXS-2026-002, and RDXS-2026-005. We work with Anthropic and all vendors we research, and inform them before publishing. These session-binding findings are published as independent security research.
The findings affect Claude Code version 2.1.72 on macOS (arm64). Cross-account isolation was tested and appears to hold. All session-binding failures documented here are same-account only.