fix: harden plugin sockets, public routes, prebuilt binaries and login fallback

This commit is contained in:
LukeGus committed 2026-10-05 19:50:19 -05:00
1 parent efb4259438
commit 5e54d95e71
16 files changed
+318 -23

No files matched your search

+69
View File
@@ -91,6 +91,20 @@ function connect(
});
}
function connectWithHeaders(
url: string,
headers: Record<string, string>,
): Promise<{ outcome: "open"; socket: WebSocket } | { outcome: number }> {
return new Promise((resolve) => {
const socket = new WebSocket(url, { headers });
socket.once("open", () => resolve({ outcome: "open", socket }));
socket.once("unexpected-response", (_req, res) =>
resolve({ outcome: res.statusCode ?? 0 }),
);
socket.once("error", () => resolve({ outcome: 0 }));
});
}
function authProtocols(token: string): string[] {
return [`termix.jwt.${token}`];
}
@@ -159,6 +173,61 @@ describe("ctx.ws routing", () => {
});
describe("ctx.ws authentication", () => {
it("ignores the jwt cookie on an upgrade from another site", async () => {
ws.registerPluginWsRoute("sample-plugin", "/socket", () => {}, DECLARED);
const base = await startServer();
const result = await connectWithHeaders(
`${base}/plugin-ws/sample-plugin/socket`,
{ Cookie: `jwt=${state.validToken}`, Origin: "https://evil.example" },
);
expect(result.outcome).toBe(401);
});
it("accepts the jwt cookie from this server's own page", async () => {
ws.registerPluginWsRoute("sample-plugin", "/socket", () => {}, DECLARED);
const base = await startServer();
const result = await connectWithHeaders(
`${base}/plugin-ws/sample-plugin/socket`,
{
Cookie: `jwt=${state.validToken}`,
Origin: base.replace(/^ws:/, "http:"),
},
);
expect(result.outcome).toBe("open");
if (result.outcome === "open") result.socket.close();
});
it("hides cross-site cookies from a public socket's handler", async () => {
const cookies: Array<string | undefined> = [];
const users: string[] = [];
ws.registerPluginWsRoute(
"sample-plugin",
"/public",
({ request, userId, socket }) => {
cookies.push(request.headers.cookie);
users.push(userId);
(socket as WebSocket).close();
},
DECLARED,
{ public: true, optionalAuth: true },
);
const base = await startServer();
const result = await connectWithHeaders(
`${base}/plugin-ws/sample-plugin/public`,
{ Cookie: `jwt=${state.validToken}`, Origin: "https://evil.example" },
);
expect(result.outcome).toBe("open");
await vi.waitFor(() => expect(users).toHaveLength(1));
expect(users).toEqual([""]);
expect(cookies).toEqual([undefined]);
});
it("rejects an upgrade with no token", async () => {
ws.registerPluginWsRoute("sample-plugin", "/socket", () => {}, DECLARED);