Skip to content

fix:Implement WebSocket origin checking in production#3273

Open
salignatmoandal wants to merge 1 commit intosuperplanehq:mainfrom
salignatmoandal:fix/websocket-origin-checking
Open

fix:Implement WebSocket origin checking in production#3273
salignatmoandal wants to merge 1 commit intosuperplanehq:mainfrom
salignatmoandal:fix/websocket-origin-checking

Conversation

@salignatmoandal
Copy link

What

In production, WebSocket connections are now restricted to allowed origins only. In development, all origins are still accepted (no change for local dev).

Why

Previously, the server accepted WebSocket connections from any origin. That could allow a third-party site to open a WebSocket to your SuperPlane instance using the user's cookies. Restricting origins in production reduces that risk and aligns with common security practice for WebSockets.

How

  • allowedWebSocketOrigins() builds the list of allowed origins:
    • In development (APP_ENV=development): returns no list → all origins accepted (unchanged behavior).
    • In production: uses WEBSOCKET_ALLOWED_ORIGINS if set (comma-separated), otherwise derives a single origin from BASE_URL (scheme + host).
  • The WebSocket CheckOrigin callback now allows a connection only when:
    • there is no restriction list (dev / fallback), or
    • the request’s Origin header is in the allowed list.

Configuration

  • BASE_URL: In production, the origin derived from this URL is allowed (e.g. https://app.example.comhttps://app.example.com).
  • WEBSOCKET_ALLOWED_ORIGINS (optional): Comma-separated list of origins when you need multiple (e.g. https://app.example.com,https://dashboard.example.com).
  • No change needed for local development; all origins remain accepted when APP_ENV=development.

Signed-off-by: Mawen Salignat-Moandal <mwnslgt@gmail.com>
@salignatmoandal salignatmoandal force-pushed the fix/websocket-origin-checking branch from 90cfb6b to cf89f62 Compare February 25, 2026 22:38
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

This is the final PR Bugbot will review for you during this billing cycle

Your free Bugbot reviews will reset on March 12

Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

origin := strings.TrimSpace(r.Header.Get("Origin"))
if origin == "" {
return false
}
Copy link

Choose a reason for hiding this comment

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

Missing Origin header blocks non-browser WebSocket clients

Medium Severity

When allowedOrigins is configured (production), connections without an Origin header are rejected. The gorilla/websocket default behavior is to accept connections when the Origin header is absent, because non-browser clients (CLI tools, server-to-server) typically don't send it. The Origin header is a browser-only CSRF mechanism, so rejecting its absence blocks legitimate programmatic clients without any security benefit — non-browser clients can trivially forge the header anyway.

Fix in Cursor Fix in Web

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.

1 participant