fix(openrouter): bound video response reads

Route OpenRouter video submit and poll success JSON through the shared bounded provider JSON reader, preserving malformed-response mapping and SSRF request policy coverage.

(cherry picked from commit 48f34b1d4d)
This commit is contained in:
Alix-007
2026-06-29 02:19:47 +08:00
committed by Dallin Romney
parent da7a0da19a
commit 9e337073c9
2 changed files with 28 additions and 8 deletions
@@ -546,6 +546,7 @@ describe("openrouter video generation provider", () => {
provider: "openrouter",
capability: "video",
baseUrl: "https://custom.openrouter.test/api/v1",
allowPrivateNetwork: false,
request: requestOverrides,
},
);
@@ -672,11 +673,10 @@ describe("openrouter video generation provider", () => {
it("wraps non-JSON successful OpenRouter submit responses", async () => {
postJsonRequestMock.mockResolvedValue({
response: {
json: async () => {
throw new SyntaxError("Unexpected token < in JSON");
},
},
response: new Response("<html></html>", {
status: 200,
headers: { "content-type": "text/html" },
}),
release: vi.fn(async () => {}),
});
@@ -691,6 +691,22 @@ describe("openrouter video generation provider", () => {
).rejects.toThrow("OpenRouter video generation response malformed");
});
it("bounds oversized successful OpenRouter submit responses", async () => {
const oversized = releasedOversizedJsonStream();
postJsonRequestMock.mockResolvedValue(oversized);
const provider = buildOpenRouterVideoGenerationProvider();
await expect(
provider.generateVideo({
provider: "openrouter",
model: "google/veo-3.1",
prompt: "oversized body",
cfg: {} as never,
}),
).rejects.toThrow("OpenRouter video generation: JSON response exceeds 16777216 bytes");
expect(oversized.wasCanceled()).toBe(true);
});
it("rejects unknown OpenRouter poll statuses without waiting for timeout", async () => {
postJsonRequestMock.mockResolvedValue(
releasedJson({
@@ -6,6 +6,7 @@ import {
assertOkOrThrowHttpError,
createProviderOperationDeadline,
postJsonRequest,
readProviderJsonResponse,
resolveProviderHttpRequestConfig,
resolveProviderOperationTimeoutMs,
sanitizeConfiguredModelProviderRequest,
@@ -68,9 +69,12 @@ type OpenRouterFrameImagePart = OpenRouterImagePart & {
async function readOpenRouterVideoJson(response: Response): Promise<Record<string, unknown>> {
let payload: unknown;
try {
payload = await response.json();
} catch {
throw new Error(OPENROUTER_VIDEO_MALFORMED_RESPONSE);
payload = await readProviderJsonResponse<unknown>(response, "OpenRouter video generation");
} catch (error) {
if (error instanceof Error && error.message.endsWith(": malformed JSON response")) {
throw new Error(OPENROUTER_VIDEO_MALFORMED_RESPONSE, { cause: error });
}
throw error;
}
if (!isRecord(payload)) {
throw new Error(OPENROUTER_VIDEO_MALFORMED_RESPONSE);