From b5a1b7d44d8e9d60e9162d3b63d86ea35fd4a27a Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sat, 25 Apr 2026 11:12:40 +0100 Subject: [PATCH] fix(google): guard veo video downloads --- .../google/video-generation-provider.test.ts | 4 ++- .../google/video-generation-provider.ts | 35 +++++++++++-------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/extensions/google/video-generation-provider.test.ts b/extensions/google/video-generation-provider.test.ts index f7c6aa8a009..538e2398cb9 100644 --- a/extensions/google/video-generation-provider.test.ts +++ b/extensions/google/video-generation-provider.test.ts @@ -180,7 +180,9 @@ describe("google video generation provider", () => { durationSeconds: 3, }); - expect(fetchMock).toHaveBeenCalledWith( + expect(fetchMock).toHaveBeenCalledTimes(1); + const [[downloadUrl]] = fetchMock.mock.calls as unknown as [[string, RequestInit?]]; + expect(downloadUrl).toBe( "https://generativelanguage.googleapis.com/v1beta/files/generated-video:download?alt=media&key=google-key", ); expect(downloadMock).not.toHaveBeenCalled(); diff --git a/extensions/google/video-generation-provider.ts b/extensions/google/video-generation-provider.ts index 0e07031ecc2..20450170777 100644 --- a/extensions/google/video-generation-provider.ts +++ b/extensions/google/video-generation-provider.ts @@ -6,6 +6,7 @@ import { resolveProviderOperationTimeoutMs, waitProviderOperationPollInterval, } from "openclaw/plugin-sdk/provider-http"; +import { fetchWithSsrFGuard } from "openclaw/plugin-sdk/ssrf-runtime"; import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/temp-path"; import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime"; import type { @@ -223,21 +224,27 @@ async function downloadGeneratedVideoFromUri(params: { if (!downloadUrl) { return undefined; } - const response = await fetch(downloadUrl); - if (!response.ok) { - throw new Error( - `Failed to download Google generated video: ${response.status} ${response.statusText}`, - ); + const { response, release } = await fetchWithSsrFGuard({ + url: downloadUrl, + }); + try { + if (!response.ok) { + throw new Error( + `Failed to download Google generated video: ${response.status} ${response.statusText}`, + ); + } + const buffer = Buffer.from(await response.arrayBuffer()); + return { + buffer, + mimeType: + normalizeOptionalString(response.headers.get("content-type")) || + normalizeOptionalString(params.mimeType) || + "video/mp4", + fileName: `video-${params.index + 1}.mp4`, + }; + } finally { + await release(); } - const buffer = Buffer.from(await response.arrayBuffer()); - return { - buffer, - mimeType: - normalizeOptionalString(response.headers.get("content-type")) || - normalizeOptionalString(params.mimeType) || - "video/mp4", - fileName: `video-${params.index + 1}.mp4`, - }; } function extractGoogleApiErrorCode(error: unknown): number | undefined {