Any client-controlled URL (including OpenAI image_url) must be treated as SSRF-/DoS-/parsing-risk input and validated at every transition before connecting.

Apply this standard:

Example pattern (server-side fetch):

async function safeFetchImageBytes(inputUrl: string) {
  // 1) Parse + enforce strict outbound policy
  let current = inputUrl;
  for (let hop = 0; hop <= 3; hop++) {
    const parsed = parseAndValidatePublicUrl(current); // strict scheme/host policy

    // 2) DNS rebinding defense (reject if any IP answer is private)
    // validateResolvedIps(parsed.hostname)

    // 3) Manual redirect handling
    const res = await fetch(parsed.toString(), { method: 'GET', redirect: 'manual' });
    if (res.status >= 300 && res.status < 400 && res.headers.get('location')) {
      current = new URL(res.headers.get('location')!, parsed).toString();
      continue; // re-validate next hop
    }

    // 4) Verify content-type and read with a size cap
    const ct = (res.headers.get('content-type') || '').toLowerCase();
    if (!ct.startsWith('image/')) throw new Error('Image content-type required');
    const data = await readCapped(res, 1 * 1024 * 1024);
    return data;
  }
  throw new Error('Too many redirects');
}