From 7facf157e67d7902dd645f33026a253e006ed0e0 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 2 Aug 2026 02:59:32 +0800 Subject: [PATCH] test(openai): parse realtime websocket frames safely --- .../openai/realtime-audio-buffer-ownership.test.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/extensions/openai/realtime-audio-buffer-ownership.test.ts b/extensions/openai/realtime-audio-buffer-ownership.test.ts index 0f496a264222..dd26c050f524 100644 --- a/extensions/openai/realtime-audio-buffer-ownership.test.ts +++ b/extensions/openai/realtime-audio-buffer-ownership.test.ts @@ -1,12 +1,21 @@ import { once } from "node:events"; import type { RealtimeVoiceBridge } from "openclaw/plugin-sdk/realtime-voice"; import { describe, expect, it, vi } from "vitest"; -import WebSocket, { WebSocketServer } from "ws"; +import WebSocket, { type RawData, WebSocketServer } from "ws"; import { OpenAIQuicksilverVoiceBridge } from "./realtime-quicksilver-bridge.js"; import { buildOpenAIRealtimeVoiceProvider } from "./realtime-voice-provider.js"; type RealtimeProviderKind = "native" | "gpt-live"; +function parseWebSocketMessage(data: RawData): Record { + const bytes = Buffer.isBuffer(data) + ? data + : Array.isArray(data) + ? Buffer.concat(data) + : Buffer.from(data); + return JSON.parse(bytes.toString("utf8")) as Record; +} + async function withRealtimeProvider( kind: RealtimeProviderKind, prepareAudio: (bridge: RealtimeVoiceBridge) => void, @@ -21,7 +30,7 @@ async function withRealtimeProvider( const received: Array> = []; server.once("connection", (socket) => { socket.on("message", (payload) => { - const event = JSON.parse(payload.toString()) as Record; + const event = parseWebSocketMessage(payload); received.push(event); if (event.type === "session.update") { socket.send(