[BUG] DevTools inspector redirect uses ?ws= with a wss:// endpoint when USE_SSL=true
Describe the bug
When Steel is self-hosted with USE_SSL=true, the DevTools inspector redirect is generated with the ws query parameter while its value is still a full wss:// URL:
https://browser.example.com/devtools/devtools_app.html?ws=wss://browser.example.com/devtools/page/<page-id>Chromium DevTools expects the secure WebSocket endpoint in this form instead:
https://browser.example.com/devtools/devtools_app.html?wss=browser.example.com/devtools/page/<page-id>As a result, the DevTools inspector opened through /v1/devtools/inspector.html fails to connect correctly in an HTTPS/WSS self-hosted deployment.
Configuration
A minimal relevant configuration is:
DOMAIN=browser.example.com
CDP_DOMAIN=browser.example.com
USE_SSL=trueThe deployment is behind an HTTPS reverse proxy that forwards /devtools/ to Steel's debugger port with WebSocket upgrade support.
Steps to reproduce
Run a self-hosted Steel instance with the configuration above.
Create a browser session.
Open:
https://browser.example.com/v1/devtools/inspector.html?pageId=<page-id>Inspect the redirect URL.
Actual behavior
The endpoint redirects to:
https://browser.example.com/devtools/devtools_app.html?ws=wss://browser.example.com/devtools/page/<page-id>The DevTools frontend does not connect correctly.
Expected behavior
For a secure WebSocket endpoint, it should redirect to:
https://browser.example.com/devtools/devtools_app.html?wss=browser.example.com/devtools/page/<page-id>Manually changing the generated URL to this form allows the DevTools frontend to connect successfully.
Root cause
The current route always uses ?ws= and only strips the literal ws: prefix:
https://github.com/steel-dev/steel-browser/blob/main/api/src/modules/cdp/cdp.routes.ts
`${server.cdpService.getDebuggerUrl()}?ws=${server.cdpService
.getDebuggerWsUrl(request.query.pageId)
.replace("ws:", "")}`When USE_SSL=false, getDebuggerWsUrl() starts with ws:, so the replacement works.
When USE_SSL=true, it starts with wss:. The replacement does not match, leaving wss://... inside the ws parameter.
Suggested fix
Select the query parameter from the WebSocket protocol and remove the scheme explicitly, for example:
const debuggerWsUrl = new URL(
server.cdpService.getDebuggerWsUrl(request.query.pageId),
);
const queryParam = debuggerWsUrl.protocol === "wss:" ? "wss" : "ws";
const endpoint =
`${debuggerWsUrl.host}${debuggerWsUrl.pathname}${debuggerWsUrl.search}`;
return reply.redirect(
`${server.cdpService.getDebuggerUrl()}?${queryParam}=${endpoint}`,
);This appears distinct from the general debugger/CDP connection reports in #143 and #222 because it is a deterministic redirect-construction issue specifically triggered by USE_SSL=true.
Source: steel-dev/steel-browser