Many apps fetch a URL on the user's behalf: link previews, image imports, webhooks, PDF generators, AI features that browse a page. If the address comes from the user and your server fetches it without checks, the user can point it at places only your server can reach, such as localhost, private network addresses, or the cloud metadata service that hands out temporary credentials.
AI-generated code frequently includes a helper that does fetch(userUrl) with no validation, because that is the simplest thing that works. The response can then leak internal data or cloud credentials, and redirects can bounce a request from an allowed address to a blocked one.
The strongest fix is an allowlist: only fetch from domains you have chosen, and build the request yourself from validated parts. If users must supply arbitrary URLs, resolve the address, refuse private and loopback ranges, do not follow redirects blindly, and limit response size and time. On AWS, require the newer metadata version and block outbound access your app does not need.
const allowed = new Set(["images.example.com"]);
const url = new URL(input);
if (url.protocol !== "https:" || !allowed.has(url.hostname)) {
throw new Error("URL not allowed");
}