diff --git a/artifacts/api-server/src/routes/events.ts b/artifacts/api-server/src/routes/events.ts index 1f92835..27651c6 100644 --- a/artifacts/api-server/src/routes/events.ts +++ b/artifacts/api-server/src/routes/events.ts @@ -297,9 +297,10 @@ export function attachWebSocketServer(server: Server): void { // Broadcast visitor message to all watchers broadcastToAll(wss, { type: "chat", agentId: "visitor", text }); - // Rate-limit Timmy's AI replies per visitor - const visId = String(msg.visitorId ?? ip); - if (!checkChatRateLimit(visId)) { + // Rate-limit Timmy's AI replies — key on server-trusted IP, not + // client-provided visitorId (which is trivially spoofable). + const ipStr = Array.isArray(ip) ? (ip[0] ?? "unknown") : String(ip).split(",")[0]!.trim(); + if (!checkChatRateLimit(ipStr)) { send(socket, { type: "chat", agentId: "timmy",