From dde89f18b472ea3ff24ea06eedf1283e711c5f49 Mon Sep 17 00:00:00 2001 From: shrimbly Date: Sat, 7 Feb 2026 21:33:07 +1300 Subject: [PATCH] fix: add SSRF validation for fal CDN upload/file URLs Validate uploadUrl and fileUrl from fal CDN initiate response through validateMediaUrl() and HTTPS check before performing the PUT request. Throws if either URL is missing or fails validation. Co-Authored-By: Claude Opus 4.6 --- src/app/api/generate/route.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/app/api/generate/route.ts b/src/app/api/generate/route.ts index 59f121d3..b72d48ae 100644 --- a/src/app/api/generate/route.ts +++ b/src/app/api/generate/route.ts @@ -842,7 +842,22 @@ async function uploadImageToFal(base64DataUrl: string, apiKey: string | null): P const { upload_url: uploadUrl, file_url: fileUrl } = await initiateResponse.json(); - // Step 2: PUT the binary data to the signed URL + // Validate both URLs before using them (SSRF protection) + if (!uploadUrl || !fileUrl) { + throw new Error("fal CDN initiate response missing upload_url or file_url"); + } + + const uploadUrlCheck = validateMediaUrl(uploadUrl); + if (!uploadUrlCheck.valid || !uploadUrl.startsWith('https://')) { + throw new Error(`fal CDN upload_url failed validation: ${uploadUrlCheck.error || 'not HTTPS'}`); + } + + const fileUrlCheck = validateMediaUrl(fileUrl); + if (!fileUrlCheck.valid || !fileUrl.startsWith('https://')) { + throw new Error(`fal CDN file_url failed validation: ${fileUrlCheck.error || 'not HTTPS'}`); + } + + // Step 2: PUT the binary data to the validated signed URL const putResponse = await fetch(uploadUrl, { method: "PUT", headers: { "Content-Type": contentType },