From 69e5ad88462f9f58dacaee9ca926dea8a658378b Mon Sep 17 00:00:00 2001 From: Simone Date: Mon, 24 Aug 2026 00:53:37 +0200 Subject: [PATCH] fix(web): treat configured urls with uppercase schemes as secure (#8005) Co-authored-by: Simone <185146821+Lucenx9@users.noreply.github.com> --- .../src/environments/primary/bootstrap.test.ts | 18 ++++++++++++++++++ apps/web/src/environments/primary/target.ts | 8 ++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/apps/web/src/environments/primary/bootstrap.test.ts b/apps/web/src/environments/primary/bootstrap.test.ts index e200ecf2ff87e1e2d29ba9744b62d3a9610b9464..b08717d7c413abfb2c2944f26b5f0a3dcb260724 100644 --- a/apps/web/src/environments/primary/bootstrap.test.ts +++ b/apps/web/src/environments/primary/bootstrap.test.ts @@ -155,6 +155,24 @@ describe("environmentBootstrap", () => { }); }); + it("keeps an uppercase wss scheme secure when deriving the http url", () => { + vi.stubEnv("VITE_WS_URL", "WSS://remote.example.com"); + + expect(readPrimaryEnvironmentTarget().target).toEqual({ + httpBaseUrl: "https://remote.example.com/", + wsBaseUrl: "wss://remote.example.com/", + }); + }); + + it("keeps an uppercase https scheme secure when deriving the websocket url", () => { + vi.stubEnv("VITE_HTTP_URL", "HTTPS://remote.example.com"); + + expect(readPrimaryEnvironmentTarget().target).toEqual({ + httpBaseUrl: "https://remote.example.com/", + wsBaseUrl: "wss://remote.example.com/", + }); + }); + it("uses the current origin as the descriptor base for local dev environments", async () => { installTestBrowser("http://localhost:5735/"); await installDescriptorApi(); diff --git a/apps/web/src/environments/primary/target.ts b/apps/web/src/environments/primary/target.ts index cc002419fe785d8a403b29d0bc71cb2f8063433e..5aa957e8665d2490e1246ab53a907bb860ea0879 100644 --- a/apps/web/src/environments/primary/target.ts +++ b/apps/web/src/environments/primary/target.ts @@ -189,14 +189,18 @@ function resolveConfiguredPrimaryTarget(): PrimaryEnvironmentTarget | null { return null; } + // Scheme checks run on the raw configured string, while the URL parser + // folds schemes to lowercase ("WSS://host" parses fine). Without the + // case folding an uppercase scheme would be classified as plaintext and + // swapped to http/ws, silently downgrading TLS. const resolvedHttpBaseUrl = configuredHttpBaseUrl ?? - (configuredWsBaseUrl?.startsWith("wss:") + (configuredWsBaseUrl?.toLowerCase().startsWith("wss:") ? swapBaseUrlProtocol(configuredWsBaseUrl, "https:", "websocket-base-url") : swapBaseUrlProtocol(configuredWsBaseUrl!, "http:", "websocket-base-url")); const resolvedWsBaseUrl = configuredWsBaseUrl ?? - (configuredHttpBaseUrl?.startsWith("https:") + (configuredHttpBaseUrl?.toLowerCase().startsWith("https:") ? swapBaseUrlProtocol(configuredHttpBaseUrl, "wss:", "http-base-url") : swapBaseUrlProtocol(configuredHttpBaseUrl!, "ws:", "http-base-url")); -- 2.54.0