#11794: fix(gateway): validate session key ownership against authenticated identity
gateway
stale
Cluster:
OpenClaw Plugin Enhancements
## Fix Summary
Validates that explicit session keys (via `x-openclaw-session-key` header or request body `sessionKey` field) belong to the authenticated user identity. In multi-user deployments (Tailscale Serve), any authenticated user could previously read/write another user's conversation history, memories, and tool execution context by supplying a predictable session key.
## Issue Linkage
Fixes #11793
## Security Snapshot
- CVSS v3.1: 8.1 (High)
- CVSS v4.0: 8.6 (High)
## Implementation Details
### Files Changed
- `src/gateway/hooks.ts` (+12/-4)
- `src/gateway/http-utils.ts` (+26/-1)
- `src/gateway/openai-http.ts` (+2/-1)
- `src/gateway/openresponses-http.ts` (+7/-1)
- `src/gateway/tools-invoke-http.ts` (+17/-1)
### Technical Analysis
**`src/gateway/http-utils.ts`**
- Add `sessionKeyBelongsToUser()` helper that checks whether a session key contains the authenticated user's identity
- Add `authUser` parameter to `resolveSessionKey()` — when set (Tailscale auth), ignores explicit session keys that don't match the authenticated identity and falls through to generate a user-bound key
**`src/gateway/openai-http.ts` / `src/gateway/openresponses-http.ts`**
- Thread `authResult.user` through to `resolveSessionKey()` via the wrapper functions
**`src/gateway/tools-invoke-http.ts`**
- Validate body-supplied session keys against `authResult.user` — return 403 if the key belongs to a different user
**`src/gateway/hooks.ts`**
- Restrict `normalizeAgentPayload()` to the `hook:` namespace — reject session keys starting with `agent:` to prevent hooks from accessing user conversation sessions
## Validation Evidence
- Command: `pnpm build`
- Status: failed
## Risk and Compatibility
- **Single-user deployments**: No change — token/password auth doesn't set `authUser`, so explicit session keys continue to work
- **Multi-user Tailscale deployments**: Users can still set explicit session keys that match their own identity. Cross-user access is blocked.
- **Hooks**: Hook callers that previously used `agent:` scoped session keys will receive an error. This is intentional — hooks should use the `hook:` namespace.
Fixes #11793
## AI-Assisted Disclosure
Generated with [Claude Code](https://claude.ai/code)
This fix was generated with AI assistance (Claude Opus 4.6).
<!-- greptile_comment -->
<h2>Greptile Overview</h2>
<h3>Greptile Summary</h3>
I’m going to review the PR diff for the 5 changed gateway files, trace how `authResult.user` and session keys flow through request handling (OpenAI/OpenResponses/tools/hooks), and look specifically for any logic gaps that would still allow cross-user session access or unintended breakage (e.g., incorrect session key parsing/ownership checks, inconsistent enforcement across endpoints, or namespace validation errors). I’ll leave only concrete, must-fix issues with exact file+line references.
<h3>Confidence Score: 2/5</h3>
- This PR improves security posture but still leaves a concrete cross-user session access bypass in the new ownership check logic.
- Core change relies on substring matching for session ownership, which is trivially satisfiable by crafting a session key containing the authenticated user marker anywhere in the string. Hook session key restriction also doesn’t fully enforce the intended namespace boundary. These issues affect the primary security objective of the PR.
- src/gateway/http-utils.ts (sessionKeyBelongsToUser), src/gateway/hooks.ts (session key namespace enforcement)
<!-- greptile_other_comments_section -->
**Context used:**
- Context from `dashboard` - CLAUDE.md ([source](https://app.greptile.com/review/custom-context?memory=fd949e91-5c3a-4ab5-90a1-cbe184fd6ce8))
- Context from `dashboard` - AGENTS.md ([source](https://app.greptile.com/review/custom-context?memory=0d0c8278-ef8e-4d6c-ab21-f5527e322f13))
<!-- /greptile_comment -->
Most Similar PRs
#21662: fix(gateway): validate session key ownership against agent scope
by AI-Reviewer-QS · 2026-02-20
84.2%
#20431: fix(sessions): add session contamination guards and self-leak lock ...
by marcomarandiz · 2026-02-18
78.7%
#19937: fix(gateway): validate token/password auth modes and isolate gatewa...
by NewdlDewdl · 2026-02-18
78.5%
#3182: fix(gateway): use canonical session key in chat.send
by chrisherold · 2026-01-28
78.2%
#10745: feat: Security improvements and Windows compatibility fixes
by lluviaoscuradeldoce-design · 2026-02-06
77.3%
#19885: test(gateway,browser): isolate tests from ambient OPENCLAW_GATEWAY_...
by NewdlDewdl · 2026-02-18
77.3%
#7301: fix(hooks): use resolveAgentIdFromSessionKey instead of split(":")[0]
by tsukhani · 2026-02-02
77.0%
#23410: Gateway: require prefixes for hook request session-key overrides
by bmendonca3 · 2026-02-22
76.6%
#8513: Gateway: require auth for plugin HTTP
by coygeek · 2026-02-04
76.4%
#15050: fix: transcript corruption resilience — strip aborted tool_use bloc...
by yashchitneni · 2026-02-12
76.4%