diff --git a/src/server/GameServer.ts b/src/server/GameServer.ts index 003542bd8..5754ad218 100644 --- a/src/server/GameServer.ts +++ b/src/server/GameServer.ts @@ -1,9 +1,9 @@ import ipAnonymize from "ip-anonymize"; import { Logger } from "winston"; import WebSocket from "ws"; +import { z } from "zod/v4"; import { ClientID, - ClientMessage, ClientMessageSchema, ClientSendWinnerMessage, GameConfig, @@ -178,12 +178,16 @@ export class GameServer { "message", gatekeeper.wsHandler(client.ip, async (message: string) => { try { - let clientMsg: ClientMessage | null = null; - try { - clientMsg = ClientMessageSchema.parse(JSON.parse(message)); - } catch (error) { - throw Error(`error parsing schema for ${ipAnonymize(client.ip)}`); + const parsed = ClientMessageSchema.safeParse(JSON.parse(message)); + if (!parsed.success) { + const error = z.prettifyError(parsed.error); + this.log.error("Failed to parse client message", error, { + clientID: client.clientID, + }); + client.ws.close(); + return; } + const clientMsg = parsed.data; if (clientMsg.type === "intent") { if (clientMsg.intent.clientID !== client.clientID) { this.log.warn( diff --git a/src/server/Worker.ts b/src/server/Worker.ts index 068799fed..3f072ebdf 100644 --- a/src/server/Worker.ts +++ b/src/server/Worker.ts @@ -10,7 +10,8 @@ import { GameEnv } from "../core/configuration/Config"; import { getServerConfigFromServer } from "../core/configuration/ConfigLoader"; import { GameType } from "../core/game/Game"; import { - ClientMessageSchema, + ClientJoinMessageSchema, + GameConfig, GameRecord, GameRecordSchema, } from "../core/Schemas"; @@ -293,11 +294,17 @@ export function startWorker() { : forwarded || req.socket.remoteAddress || "unknown"; try { - // Process WebSocket messages as in your original code // Parse and handle client messages - const clientMsg = ClientMessageSchema.parse( + const parsed = ClientJoinMessageSchema.safeParse( JSON.parse(message.toString()), ); + if (!parsed.success) { + const error = z.prettifyError(parsed.error); + log.warn("Error parsing join message client", error); + ws.close(); + return; + } + const clientMsg = parsed.data; if (clientMsg.type === "join") { // Verify this worker should handle this game