Skip to content

Commit 56133b1

Browse files
committed
fix(inworld): reject malformed base64 TTS audio
1 parent 3af3493 commit 56133b1

2 files changed

Lines changed: 15 additions & 2 deletions

File tree

extensions/inworld/tts.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,15 @@ describe("inworldTTS", () => {
237237
);
238238
});
239239

240+
it("rejects malformed base64 audio chunks", async () => {
241+
const body = JSON.stringify({ result: { audioContent: "not-base64!" } });
242+
queueGuardedResponse(new Response(body, { status: 200 }));
243+
244+
await expect(inworldTTS({ text: "test", apiKey: "fixture-api-key" })).rejects.toThrow(
245+
"Inworld TTS returned malformed base64 audio data",
246+
);
247+
});
248+
240249
it("throws on HTTP errors with response body", async () => {
241250
queueGuardedResponse(new Response("bad request body", { status: 400 }));
242251

extensions/inworld/tts.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Inworld plugin module implements tts behavior.
2-
import { MAX_AUDIO_BYTES } from "openclaw/plugin-sdk/media-runtime";
2+
import { canonicalizeBase64, MAX_AUDIO_BYTES } from "openclaw/plugin-sdk/media-runtime";
33
import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
44
import type { SpeechVoiceOption } from "openclaw/plugin-sdk/speech-core";
55
import { fetchWithSsrFGuard, type SsrFPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
@@ -186,7 +186,11 @@ export async function inworldTTS(params: {
186186
}
187187

188188
if (parsed.result?.audioContent) {
189-
const chunk = Buffer.from(parsed.result.audioContent, "base64");
189+
const canonicalAudio = canonicalizeBase64(parsed.result.audioContent);
190+
if (!canonicalAudio) {
191+
throw new Error("Inworld TTS returned malformed base64 audio data");
192+
}
193+
const chunk = Buffer.from(canonicalAudio, "base64");
190194
const nextDecodedAudioBytes = decodedAudioBytes + chunk.length;
191195
if (nextDecodedAudioBytes > MAX_AUDIO_BYTES) {
192196
throw new Error(

0 commit comments

Comments
 (0)