Summary
The WebSocket proxy in server/gateway-proxy.js forwards all messages between browser and upstream gateway without size constraints or connection timeouts. This enables denial of service against both the Studio server and the upstream gateway.
Location
server/gateway-proxy.js (entire browserWs.on("message") handler)
Technical Detail
Three gaps:
1. No message size limit
The ws library's default maxPayload is 100MB (v8.x). Every incoming message is parsed with JSON.parse(String(raw)). A malicious browser client can send payloads up to 100MB that get fully buffered and parsed, causing memory pressure and CPU spikes.
browserWs.on("message", async (raw) => {
const parsed = safeJsonParse(String(raw ?? "")); // No size check before parsing
// ...
});
2. No connect timeout
If a browser opens a WebSocket but never sends a connect frame, the connection stays open indefinitely. The upstream WebSocket is also opened and held open.
3. No rate limiting
A browser client can send thousands of messages per second, all forwarded to the upstream gateway.
Impact
- Memory exhaustion on the Studio server from large payloads
- Connection exhaustion from idle/zombie connections
- Upstream gateway flooding from rapid message forwarding
- A single malicious browser tab can degrade service for all users
Suggested Fix
// In createGatewayProxy, set maxPayload on the WebSocketServer:
const wss = new WebSocketServer({
noServer: true,
verifyClient,
maxPayload: 1_048_576, // 1MB - generous for JSON control frames
});
// Add connect timeout in the connection handler:
let connectTimeout = setTimeout(() => {
closeBoth(1008, "connect timeout");
}, 10_000); // 10 seconds to send connect frame
// Clear timeout when connect frame arrives:
if (connectRequestId && connectTimeout) {
clearTimeout(connectTimeout);
connectTimeout = null;
}
The maxPayload option on the ws WebSocketServer will reject oversized frames at the protocol level before they reach the message handler.
Summary
The WebSocket proxy in
server/gateway-proxy.jsforwards all messages between browser and upstream gateway without size constraints or connection timeouts. This enables denial of service against both the Studio server and the upstream gateway.Location
server/gateway-proxy.js(entirebrowserWs.on("message")handler)Technical Detail
Three gaps:
1. No message size limit
The
wslibrary's defaultmaxPayloadis 100MB (v8.x). Every incoming message is parsed withJSON.parse(String(raw)). A malicious browser client can send payloads up to 100MB that get fully buffered and parsed, causing memory pressure and CPU spikes.2. No connect timeout
If a browser opens a WebSocket but never sends a
connectframe, the connection stays open indefinitely. The upstream WebSocket is also opened and held open.3. No rate limiting
A browser client can send thousands of messages per second, all forwarded to the upstream gateway.
Impact
Suggested Fix
The
maxPayloadoption on thewsWebSocketServer will reject oversized frames at the protocol level before they reach the message handler.