Skip to content

RI-8321: Enforce x-window-id auth on WebSocket connections#6225

Merged
pawelangelow merged 2 commits into
mainfrom
be/bugfix/RI-8321/socket-io-window-auth
Jul 20, 2026
Merged

RI-8321: Enforce x-window-id auth on WebSocket connections#6225
pawelangelow merged 2 commits into
mainfrom
be/bugfix/RI-8321/socket-io-window-auth

Conversation

@pawelangelow

@pawelangelow pawelangelow commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

What

The local WebSocket layer did not enforce the x-window-id authorization
that the HTTP API requires. SessionMetadataAdapter was registered as the
WebSocket adapter unconditionally after WindowsAuthAdapter, and NestJS keeps
only the last adapter set — so the auth gate never ran and every socket was
granted the default session. Unauthenticated cross-origin clients could reach
the monitor, pub-sub, and bulk-actions namespaces, observe live commands,
and trigger destructive bulk actions against saved databases.

WindowsAuthAdapter now extends SessionMetadataAdapter, so an authorized
socket gets both the window-id check and its session metadata, and it is the
only adapter wired for the desktop build. Web/dev builds keep the
metadata-only adapter, matching the Electron-only scope of the HTTP
WindowAuthMiddleware.


Note

High Risk
Changes WebSocket authentication and connection teardown for the desktop build, closing a path where unauthenticated clients could use monitor/pub-sub/bulk-actions namespaces.

Overview
Fixes a WebSocket auth bypass where registering SessionMetadataAdapter after WindowsAuthAdapter in bootstrap meant only the metadata adapter ran, so every socket got default session without an x-window-id check.

For Electron builds, bootstrap now registers only WindowsAuthAdapter (with an inline comment). Web/dev builds use SessionMetadataAdapter alone, matching HTTP window-auth scope.

WindowsAuthAdapter extends SessionMetadataAdapter and calls super.bindMessageHandlers after a successful window-id check, so authorized sockets still get session metadata and user-room join. Unauthorized sockets are disconnect(true) so they cannot keep receiving namespace broadcasts.

Adds unit tests for authorized vs unauthorized bindMessageHandlers behavior.

Reviewed by Cursor Bugbot for commit b87342f. Bugbot is set up for automated code reviews on this repo. Configure here.

The SessionMetadataAdapter was set as the web socket adapter
unconditionally after WindowsAuthAdapter, and NestJS keeps only the last
adapter — so the x-window-id handshake check never ran and every socket
was granted the default session. Unauthenticated cross-origin clients
could reach the monitor, pub-sub and bulk-actions namespaces.

WindowsAuthAdapter now extends SessionMetadataAdapter so an authorized
socket gets both the window-id gate and the session metadata, and it is
the only adapter wired for the desktop build. Web/dev builds keep the
metadata-only adapter.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@pawelangelow pawelangelow self-assigned this Jul 17, 2026
@pawelangelow
pawelangelow requested a review from a team as a code owner July 17, 2026 09:22

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

if (!isAuthorized) {
this.logger.error(ERROR_MESSAGES.UNDEFINED_WINDOW_ID);
return;

P1 Badge Disconnect unauthorized sockets

When an Electron production client supplies a missing or invalid x-window-id, this returns without closing the already-established Socket.IO connection; it merely skips registration of @SubscribeMessage handlers. The unauthenticated socket can still join the root namespace and receive broadcasts such as FeatureGateway and NotificationGateway, both of which use wss.of('/').emit(...). Explicitly disconnect or reject the socket here so the authorization check actually gates the WebSocket connection and its server-pushed data.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Code Coverage - Backend unit tests

St.
Category Percentage Covered / Total
🟢 Statements 93.14% 16520/17736
🟡 Branches 75.34% 5279/7007
🟢 Functions 87.47% 2535/2898
🟢 Lines 93% 15797/16986

Test suite run success

3688 tests passing in 322 suites.

Report generated by 🧪jest coverage report action from b87342f

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Code Coverage - Integration Tests

Status Category Percentage Covered / Total
🟡 Statements 79.26% 18210/22975
🟡 Branches 61.88% 8485/13711
🟡 Functions 66.9% 2462/3680
🟡 Lines 78.86% 17144/21739

Returning early only skipped message-handler registration; the socket
stayed connected to the root namespace and still received broadcasts
such as FeatureGateway and NotificationGateway (wss.of('/').emit(...)).
Disconnect the socket when the window id is not authorized so the auth
check gates the connection, not just message sending.
@pawelangelow

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: b87342f388

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@pawelangelow
pawelangelow merged commit 8b8a091 into main Jul 20, 2026
29 checks passed
@pawelangelow
pawelangelow deleted the be/bugfix/RI-8321/socket-io-window-auth branch July 20, 2026 06:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants