media download redirect policy: validate every destination before following
·
An output URL can redirect to a storage or delivery host. A backend downloader should apply its destination policy at every hop rather than validating only the first URL and then following anything automatically. Keep the API client and media downloader separate: the Genace bearer key authenticates API requests and does not belong on arbitrary artifact requests.
Start from a validated job output
Read a succeeded job snapshot and select the expected media type. Save the job ID and output index before retrieval. Do not let the same downloader accept an unrelated caller-supplied URL through a less restricted route. A trusted source of the initial reference does not eliminate the need for transport and size controls.
The following Fetch helper illustrates manual redirects in a trusted server runtime. It first requires HTTPS without URL user information. The policy callback must then enforce your reviewed host and network rules, returning exactly true to allow a destination. It may be synchronous or asynchronous: the helper awaits the decision at every hop. Browser Fetch has different visibility constraints for manual redirects, so this is not a universal browser download snippet.
export async function mediaResponse(initialUrl, allowDestination) {
let url = new URL(initialUrl);
for (let hop = 0; hop <= 4; hop += 1) {
if (url.protocol !== 'https:' || url.username || url.password) {
throw new Error('Blocked media destination');
}
const allowed = await allowDestination(new URL(url));
if (allowed !== true) throw new Error('Blocked media destination');
const response = await fetch(url, {
redirect: 'manual',
signal: AbortSignal.timeout(30000),
});
if ([301, 302, 303, 307, 308].includes(response.status)) {
const location = response.headers.get('location');
await response.body?.cancel();
if (!location) throw new Error('Redirect has no location');
url = new URL(location, url);
continue;
}
if (!response.ok) {
await response.body?.cancel();
throw new Error(`Media HTTP ${response.status}`);
}
return response;
}
throw new Error('Too many redirects');
}
The hop count and timeout are example limits. Add a total deadline and streamed byte cap around body consumption. The helper intentionally sends no Authorization header and releases redirect response bodies before continuing.
An async function returns a Promise, which is truthy even when it eventually resolves to false. Testing the Promise itself with a plain boolean condition would allow a denied URL to reach fetch. Awaiting and requiring exactly true closes that mistake; a policy rejection or thrown exception prevents the next request. Returning a string such as allowed is not approval.
The callback receives a fresh URL object so changing its argument cannot rewrite the URL subsequently fetched. Treat the callback as a reviewed decision function, not as a URL-normalization hook. If the actual destination needs to change, represent that change through a redirect response and apply policy again before connecting.
Review network destinations, not just strings
A hostname allowlist is useful when your storage hosts are predictable, but server-side URL fetching also needs network-level controls. Consider resolved addresses, private ranges, loopback, link-local destinations, and DNS changes between validation and connection. A simple string prefix test is not an SSRF defense.
Awaiting a DNS lookup does not bind that checked address to fetch’s later connection. This helper is not a complete SSRF defense: use a transport or egress control that enforces the approved network destination at connection time, including after redirects. The HTTPS/user-information checks do not solve DNS rebinding, proxy routing, or network-layer authorization by themselves.
If a redirect crosses to a newly required CDN host, fail with a controlled policy error and review that host through configuration. Do not solve it by forwarding every request header or allowing every destination. Keep destination policy changes observable and versioned.
Recover delivery without changing render state
A blocked redirect or failed download is a local delivery issue. Preserve the succeeded remote state and source identity. Once the destination policy is corrected, retry retrieval of the existing output under the normal access window. Do not generate another video merely because the downloader rejected a hop.
Verification checklist
Use local mock servers to test a relative redirect, a loop, a missing Location header, and a cross-host hop. Assert every destination is checked and no API secret appears at either server. Test a redirect to a blocked private address through your network enforcement layer.
Finally, verify oversized and slow bodies are stopped after redirect resolution. Successful routing is only one stage of media validation; inspect the resulting bytes before publication.
Run offline cases where async policy resolves false for the initial URL and for a redirected host: assert zero requests to denied destinations. Also test sync denial, non-boolean policy results, a callback that mutates its URL argument, HTTP or credential-bearing URLs, missing Location, HTTP errors, and a redirect loop. These fixtures validate control flow and body cleanup, not DNS pinning, real egress rules, or full streamed-download limits.
See SSRF boundaries, authorization redirect handling, and download validation.
Continue with production operations
Where these facts come from
- Editorial keyword hypothesis; search volume not measured
- https://fetch.spec.whatwg.org/
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await
- codebase: src/ai/providers/types.ts
- codebase: src/ai/providers/seedance.ts