Merge pull request #247 from copenhagentruckwash/fix-information-disclosure-in-websocket-upgrades
Sanitize websocket upgrade error responses
This commit is contained in:
@@ -576,7 +576,7 @@ export function createBrokerServer(options = {}) {
|
||||
gatewayInfo = await validateAgent({ gatewayId, token, headers: req.headers });
|
||||
} catch (error) {
|
||||
const status = Number(error?.status) === 403 ? 403 : Number(error?.status) === 401 ? 401 : 503;
|
||||
rejectUpgrade(socket, status, error?.code || "agent_validation_failed", normalizeErrorMessage(error, "Gateway agent could not be validated."), {
|
||||
rejectUpgrade(socket, status, error?.code || "agent_validation_failed", "Gateway agent could not be validated.", {
|
||||
stage: "agent_validate",
|
||||
});
|
||||
return;
|
||||
@@ -643,7 +643,7 @@ export function createBrokerServer(options = {}) {
|
||||
try {
|
||||
session = await validateShellSession({ token, headers: req.headers });
|
||||
} catch (error) {
|
||||
rejectUpgrade(socket, Number(error?.status) === 403 ? 403 : 401, error?.code || "shell_session_invalid", normalizeErrorMessage(error, "Shell session could not be validated."), {
|
||||
rejectUpgrade(socket, Number(error?.status) === 403 ? 403 : 401, error?.code || "shell_session_invalid", "Shell session could not be validated.", {
|
||||
stage: "shell_session_validate",
|
||||
});
|
||||
return;
|
||||
@@ -744,7 +744,7 @@ export function createBrokerServer(options = {}) {
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
rejectUpgrade(socket, 500, "websocket_upgrade_failed", normalizeErrorMessage(error, "WebSocket upgrade failed."));
|
||||
rejectUpgrade(socket, 500, "websocket_upgrade_failed", "WebSocket upgrade failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -95,13 +95,15 @@ test("broker defaults to strict auth and fails closed when manager URL is missin
|
||||
assert.doesNotMatch(shellResponse, /101 Switching Protocols/);
|
||||
assert.match(shellResponse, /^HTTP\/1\.1 401 Unauthorized/m);
|
||||
assert.match(shellResponse, /"error_code":"shell_session_invalid"/);
|
||||
assert.match(shellResponse, /Edge manager URL is not configured/);
|
||||
assert.match(shellResponse, /"message":"Shell session could not be validated\."/);
|
||||
assert.doesNotMatch(shellResponse, /Edge manager URL is not configured/);
|
||||
|
||||
assert.doesNotMatch(agentResponse, /101 Switching Protocols/);
|
||||
assert.match(agentResponse, /^HTTP\/1\.1 503 Service Unavailable/m);
|
||||
assert.match(agentResponse, /"error_code":"agent_validation_failed"/);
|
||||
assert.match(agentResponse, /"stage":"agent_validate"/);
|
||||
assert.match(agentResponse, /Edge manager URL is not configured/);
|
||||
assert.match(agentResponse, /"message":"Gateway agent could not be validated\."/);
|
||||
assert.doesNotMatch(agentResponse, /Edge manager URL is not configured/);
|
||||
} finally {
|
||||
if (broker) {
|
||||
await broker.close();
|
||||
@@ -397,11 +399,34 @@ test("broker rejects invalid browser shell upgrades without leaking the token",
|
||||
|
||||
assert.match(response, /^HTTP\/1\.1 401 Unauthorized/m);
|
||||
assert.match(response, /"error_code":"shell_session_expired"/);
|
||||
assert.match(response, /"message":"Shell session could not be validated\."/);
|
||||
assert.doesNotMatch(response, /Shell session expired/);
|
||||
assert.doesNotMatch(response, new RegExp(rawToken));
|
||||
|
||||
await broker.close();
|
||||
});
|
||||
|
||||
test("broker rejects websocket upgrade errors without exposing exception text", async () => {
|
||||
const broker = createBrokerServer({
|
||||
authMode: "stub",
|
||||
validateBrowserStream: async () => {
|
||||
throw new Error("UPSTREAM-SENSITIVE: redis://cache.internal:6379 timeout");
|
||||
},
|
||||
});
|
||||
const address = await broker.listen(0);
|
||||
const port = address.port;
|
||||
|
||||
const response = await rawUpgradeRequest(port, "/ws/browser-gateway-stream?token=session-token");
|
||||
|
||||
assert.match(response, /^HTTP\/1\.1 500 Internal Server Error/m);
|
||||
assert.match(response, /"error_code":"websocket_upgrade_failed"/);
|
||||
assert.match(response, /"message":"WebSocket upgrade failed\."/);
|
||||
assert.doesNotMatch(response, /UPSTREAM-SENSITIVE/);
|
||||
assert.doesNotMatch(response, /redis:\/\/cache\.internal/);
|
||||
|
||||
await broker.close();
|
||||
});
|
||||
|
||||
test("broker closes browser shell sessions when the agent never reports shell opened", async () => {
|
||||
const closedSessions = [];
|
||||
const broker = createBrokerServer({
|
||||
|
||||
Reference in New Issue
Block a user