-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
NOTE: Most of this report is generated by gpt-5.4, but I reviewed it manually and it does refer to a genuine bug I experienced. Also see below why I did not submit a PR.
Problem
T3 Code 0.0.3 could render successfully over HTTPS and still fail to become usable because the frontend attempted to open its control WebSocket over insecure ws:// instead of secure wss://.
This is a product bug in T3's browser client bootstrap logic. The app was assuming a non-TLS websocket origin even when the page itself was loaded from an HTTPS origin behind a reverse proxy.
Symptom
The browser console shows a startup failure similar to:
SecurityError: An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.
In practical terms, the page shell can load, but real-time state hydration and interactive behavior do not come up correctly because the main websocket transport never connects.
Reproduce Conditions
This bug is most likely to appear under all of the following conditions:
- T3 is deployed behind a TLS terminator or reverse proxy.
- The browser reaches T3 through
https://.... - T3 itself still listens on plain HTTP internally.
- The frontend computes its websocket endpoint from assumptions that ignore the current page protocol.
This is especially easy to trigger in the common production topology:
- browser ->
https://<some-host>(in my case, on Tailscale) - reverse proxy terminates TLS
- proxy forwards to T3 on
http://127.0.0.1:<port>
In that topology, ws:// is invalid from the browser's point of view even if the reverse proxy could technically reach the backend over plain HTTP.
Why This Is Broken
The browser's security model requires websocket security to match the page security context:
http://pages may openws://https://pages must openwss://
If the frontend derives its websocket URL from a static default, a plain-host assumption, or duplicated URL-building logic that forgets to switch protocols under HTTPS, the app fails only in secured deployments. That makes the defect easy to miss in local development and easy to hit in real deployment.
Internal Fix We Wrote
We patched T3's frontend websocket URL derivation so the default websocket origin is computed from the active browser location:
- use
wss://whenwindow.location.protocol === "https:" - use
ws://otherwise
We also characterized and fixed a second consistency problem at the same time: HTTP-origin derivation for related frontend features was spread across multiple call sites. The internal patch centralized that origin-resolution logic so websocket and HTTP URL derivation use the same source of truth.
Affected source files in the internal fix:
/home/<USER>/t3code/apps/web/src/wsUrl.ts/home/<USER>/t3code/apps/web/src/wsTransport.ts/home/<USER>/t3code/apps/web/src/store.ts/home/<USER>/t3code/apps/web/src/components/Sidebar.tsx
Me the user, here (manual edit to this report): However, since T3 Code is not accepting merge requests from external at this time, I am simply reporting that I managed to fix this in my own local copy of the app, and will not be contributing my exact fix unless it is asked of me by someone on the T3 team.
Expected Behavior After Fix
When the app is opened through HTTPS:
- the websocket target resolves to
wss://<current-host> - the client connects successfully through the reverse proxy
- the page no longer fails during startup with a browser security error
When the app is opened through plain HTTP in development:
- the websocket target still resolves to
ws://... - local non-TLS development behavior remains intact
Scope of the Issue
This is not a deployment-only mistake. The deployment topology exposed it, but the actual defect was in T3's frontend runtime behavior:
- protocol-sensitive URL derivation was incorrect or incomplete
- production-safe websocket bootstrapping was not robust
Any T3 deployment that serves the app through HTTPS without explicitly overriding the websocket URL could encounter the same failure.