We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.

This lesson's interactive features are locked, please to keep using them

Open Redirects

An open redirect sends a user to a destination supplied by the requester. Unlike SSRF, the server isn't fetching the destination itself. The app is lending its trusted domain to an attacker-controlled redirect.

Imagine a conference site that carries a returnTo value through login and redirects to it afterward:

const returnTo = String(req.body.returnTo ?? "/");
res.redirect(returnTo);

If an attacker puts an external URL in a legitimate conference login link, the victim sees the trusted domain, signs in, and is immediately sent to a phishing site.

To deal with this, I like to use a shared helper that returns the requested path when it's explicitly allow-listed and / otherwise:

const ALLOWED_RETURN_PATHS = new Set(["/", "/account", "/schedule"]);

export function safeReturnTo(value: unknown): string {
  return typeof value === "string" && ALLOWED_RETURN_PATHS.has(value)
    ? value
    : "/";
}

A check like value.startsWith("/") isn't enough. A scheme-relative URL like //evil.example starts with a slash but still sends the browser to another host. Exact matching also rejects crafted prefixes, encoded paths, and internal destinations the flow doesn't need.

Assignment

Bearly Secure already has a shared safeReturnTo helper, but isn't using it for all login flows. Ensure the shared redirect policy is applied to every login handler.

With Bearly Secure still running, run and submit the CLI tests from the project root.