URLs contain more structure than they appear to
A destination includes a scheme, host, optional port, path, query, and fragment. Treating it as an arbitrary string makes validation inconsistent and can introduce unsafe or surprising behavior.
Parse the complete value once with a tested URL parser, then apply rules to the structured result.
Fragments do not belong in the server request
A browser keeps the fragment after the hash sign and does not send it to the destination server. A redirect service can preserve it for client navigation, but a platform may intentionally remove fragments when its contract treats them as local UI state.
Whichever policy is chosen should be visible and tested. Silent encoding of the hash into a path changes the destination and is a common normalization bug.
Private destinations need special care
Loopback, private, link-local, and internal hosts can become dangerous when a platform also fetches previews or performs health checks. Rejecting them before storage simplifies the security boundary.
Hostname resolution needs additional checks in an isolated fetcher because a public-looking hostname can later resolve to a private address. String validation alone is not a complete SSRF defense.