fix(inworld): reject malformed base64 TTS audio (#111197)

This commit is contained in:
Wynne668
2026-07-19 20:48:46 -04:00
committed by GitHub
parent 0074270056
commit 27f05c8993
2 changed files with 15 additions and 2 deletions
+9
View File
@@ -237,6 +237,15 @@ describe("inworldTTS", () => {
);
});
it("rejects malformed base64 audio chunks", async () => {
const body = JSON.stringify({ result: { audioContent: "not-base64!" } });
queueGuardedResponse(new Response(body, { status: 200 }));
await expect(inworldTTS({ text: "test", apiKey: "fixture-api-key" })).rejects.toThrow(
"Inworld TTS returned malformed base64 audio data",
);
});
it("throws on HTTP errors with response body", async () => {
queueGuardedResponse(new Response("bad request body", { status: 400 }));
+6 -2
View File
@@ -1,5 +1,5 @@
// Inworld plugin module implements tts behavior.
import { MAX_AUDIO_BYTES } from "openclaw/plugin-sdk/media-runtime";
import { canonicalizeBase64, MAX_AUDIO_BYTES } from "openclaw/plugin-sdk/media-runtime";
import { readResponseWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
import type { SpeechVoiceOption } from "openclaw/plugin-sdk/speech-core";
import { fetchWithSsrFGuard, type SsrFPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
@@ -186,7 +186,11 @@ export async function inworldTTS(params: {
}
if (parsed.result?.audioContent) {
const chunk = Buffer.from(parsed.result.audioContent, "base64");
const canonicalAudio = canonicalizeBase64(parsed.result.audioContent);
if (!canonicalAudio) {
throw new Error("Inworld TTS returned malformed base64 audio data");
}
const chunk = Buffer.from(canonicalAudio, "base64");
const nextDecodedAudioBytes = decodedAudioBytes + chunk.length;
if (nextDecodedAudioBytes > MAX_AUDIO_BYTES) {
throw new Error(