T09 · Insecure Skill Coding Practices
Warning
- Location
- video-generation-provider.ts:127
- Finding
- Server-Side Request Forgery Through an Unvalidated Generated-Video URL<![CDATA[ ## Vulnerability Details **File Location**: `video-generation-provider.ts:127-141` and `video-generation-provider.ts:358-367` **Vulnerability Type**: Server-Side Request Forgery (SSRF) **Risk Level**: Medium ### Vulnerable Code ```ts async function downloadViduVideo(params: { url: string; timeoutMs?: number; fetchFn: typeof fetch; }): Promise<GeneratedVideoAsset> { const response = await fetchWithTimeout( params.url, { method: "GET" }, params.timeoutMs ?? DEFAULT_TIMEOUT_MS, params.fetchFn, ); await assertOkOrThrowHttpError(response, "Vidu generated video download failed"); const mimeType = normalizeOptionalString(response.headers.get("content-type")) ?? "video/mp4"; const arrayBuffer = await response.arrayBuffer(); return { buffer: Buffer.from(arrayBuffer), mimeType, fileName: `video-1.${mimeType.includes("webm") ? "webm" : "mp4"}`, }; } ``` The remotely supplied URL reaches this function here: ```ts const videoUrl = normalizeOptionalString(completed.creations?.[0]?.url); if (!videoUrl) { throw new Error("Vidu video generation completed without a video URL"); } const video = await downloadViduVideo({ url: videoUrl, timeoutMs: req.timeoutMs, fetchFn, }); ``` ### Technical Analysis The generated-video URL comes from `completed.creations[0].url`, which is controlled by the remote API response. The plugin passes this URL directly to `fetchWithTimeout` without validating its protocol, hostname, resolved IP address, port, or redirect chain. Creation requests use `resolveProviderHttpRequestConfig` and explicitly set `allowPrivateNetwork: false`. The generated-video download does not apply the same dispatcher policy or private-network restriction. Consequently, the protection covering the initial Vidu API request is not visibly applied to this secondary request. If the API response can be manipulated—for example, through compromise of the provider, a malicious configured endpoint, or another u ...[truncated 1870 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Apply the same SSRF-resistant HTTP policy used for provider requests to generated-asset downloads, including private-network blocking and the SDK dispatcher policy. 2. Require the URL to use HTTPS and reject embedded credentials, unsupported ports, malformed hostnames, and non-HTTP schemes. 3. Allowlist documented Vidu asset-delivery domains where operationally possible. Do not rely solely on hostname suffix matching. 4. Resolve the destination and reject loopback, private, link-local, multicast, carrier-grade NAT, documentation, and other reserved address ranges for both IPv4 and IPv6. 5. Repeat destination validation after every redirect and limit the number of redirects. This prevents a public URL from redirecting to an internal address. 6. Protect against DNS rebinding by ensuring that the validated address is the address used by the network connection. 7. Enforce a strict maximum response size before and during download. Abort streaming once that limit is exceeded rather than buffering an unlimited response. 8. Validate the returned media type and, where practical, inspect the file signature before accepting the response as a video. 9. Avoid returning the remote source URL in metadata unless downstream consumers require it; otherwise, it may expose signed URLs or asset identifiers. 10. Add tests covering loopback, RFC 1918, IPv6 local addresses, cloud metadata endpoints, redirects to private destinations, DNS rebinding scenarios, and oversized responses. ]]>
