Open redirect protection
Think of it like…a receptionist who will only forward your call to extensions on an approved list. Hand them a number that isn't on the sheet and they hang up — they never dial a random outside line just because you asked nicely.
Open redirects (OWASP "Unvalidated Redirects and Forwards", Aikido Top 10 #10) happen when an app blindly trusts a ?next=… / ?returnTo=… query parameter and emits a Location header pointing wherever the attacker wants — turning your trusted domain into a phishing launch pad. safeRedirect() validates every candidate URL against an explicit allowlist of internal paths and external origins before building the redirect response.
Quick start
safeRedirect() returns a Web-standard Response with the validated Location header and a Cache-Control: no-store directive so a per-request redirect is never cached and reused.
Strict by default
The defaults are deliberately conservative:
- Same-origin paths must start with
/and must not start with//or/\(browsers treat those as protocol-relative URLs that escape your origin). - Backslashes, control characters, and CR/LF are rejected to stop response-splitting and homograph tricks.
- Absolute URLs are allowed only when their
originexactly matches an entry inallowedOrigins. javascript:,data:,vbscript:, andfile:schemes are always refused — even if you accidentally wrote one into the allowlist.- The default status is
303 See Other, the POST-redirect-GET-safe choice.
Allowing internal paths and external origins
Path matching is exact on pathname. Query strings and fragments on the candidate are preserved in the final Location but ignored when deciding whether the target is allowed.
Fallback vs. throwing
When a candidate is rejected, you choose the behavior. Provide a fallback path and the user is quietly redirected there. Omit it and safeRedirect() throws an OpenRedirectBlockedError carrying the reason and the offending target.
The reason is one of empty-target, invalid-control-characters, protocol-relative, backslash-path, path-not-allowed, origin-not-allowed, scheme-not-allowed, or parse-failed — useful for metrics on which attack shape you are seeing.
Choosing a status code
Override the default 303 only when you genuinely need a different redirect semantic. Accepted values are 301, 302, 303, 307, and 308. You can also merge extra response headers; the Location header is always overwritten with the validated target.