Skip to content

Security: Companion WebSocket always uses plaintext ws:// — upgrade to wss:// when page is served over HTTPS #662

Description

@LucasMaupin

Summary

The companion WebSocket URL is always constructed with the plaintext `ws://` scheme, even when the intercom frontend itself is served over HTTPS. This means:

  1. Mixed-content blocking — modern browsers block `ws://` WebSocket connections initiated from an `https://` page, so the companion connection silently fails in production
  2. Security — even where the browser does not block it, the companion WebSocket traffic (call state, control messages) is transmitted unencrypted and is vulnerable to passive eavesdropping and MITM

Location

`src/utils/call-url.ts` lines 45–47:

```ts
// companion parameter always gets ws:// regardless of page origin
return ws://\${param};
```

Also affects:

  • `src/components/calls-page/connect-to-ws-modal.tsx` line 56
  • `src/components/calls-page/save-preset-modal.tsx` line 166

(Both strip the existing protocol and re-prepend `ws://`, preventing a user from ever specifying a `wss://` URL via the UI or URL parameter.)

Recommendation

In `parseCompanionParam` (and any other place that constructs the WebSocket URL):

  1. If the companion param already includes a scheme (`ws://` or `wss://`), preserve it as-is
  2. If no scheme is present and `window.location.protocol === 'https:'`, default to `wss://`
  3. If no scheme is present and on HTTP, default to `ws://` (current behaviour)

Example:

```ts
function parseCompanionParam(param: string): string {
if (param.startsWith('ws://') || param.startsWith('wss://')) return param;
const scheme = window.location.protocol === 'https:' ? 'wss' : 'ws';
return `${scheme}://${param}`;
}
```

Additionally, update the companion URL input in the modal to accept and preserve `wss://` prefixes rather than stripping and replacing the scheme.

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    UrgentPriority: urgent — act nowsecuritySecurity vulnerability or hardening

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions