Redirects
A redirect target that comes from a request (?next=... after sign-in) is the classic open redirect.
A redirect target that comes from a request (?next=... after sign-in) is the classic open redirect. Every redirect
that leaves a page's beforeLoad or loader, an API route or a server function (a JSON call and a form post alike)
passes checkRedirectTarget first, applied to the target as the code wrote it. Allowed: a path on this
site (/dashboard), a relative path, and an absolute http(s) URL whose origin is the request's own or is listed in
trustedOrigins. Refused: //host and /\host, backslashes and control characters, a scheme such as
javascript:, user info (https://app.example@evil.test) and any other origin. A refused target is a server error,
not a redirect: the handler reports RedirectBlockedError to onError, answers 500, and the target never reaches a
Location header.
import { redirect, type RequestEvent } from "@shadow-js/dusk/server";
/** Sends the browser to ?next=..., which is checked by the framework, not by this code. */
export const GET = (event: RequestEvent): never => {
throw redirect(event.url.searchParams.get("next") ?? "/", { status: 303 });
};
A page redirects the same way, from beforeLoad or a loader. The router would turn //evil.example into the local path
/evil.example and hide the attempt, so the page path checks the target as written, like the API route above.
import { redirect } from "@shadow-js/dusk";
/** Sends the visitor to ?next=...; the framework checks the target. */
export const beforeLoad = ({ location }: { location: { search: string } }): never => {
throw redirect(new URLSearchParams(location.search).get("next") ?? "/", { status: 303 });
};