CodePark/ questions / Server headers, redirects & logs
START PRACTICINGPRACTICE
Backend question · Auth & security › Server headers, redirects & logs

What's wrong with this logout route, and how should a server validate redirect targets?

app.get("/logout", (req, res) => {
  res.clearCookie("sid");
  res.redirect(req.query.next || "/");
});

It is an open redirect. A link like https://app.example/logout?next=https://evil.example/login starts with your trusted domain, so people and email filters trust it. The user ends up on the attacker's fake login page.

Open redirects cause more harm when combined with other bugs:

  • In OAuth, a redirect on an allowed callback path can forward codes or tokens to the attacker.
  • An SSRF allowlist that trusts your own domain can be bypassed, because the server follows the redirect to an internal address.

How to validate:

  • Best: don't accept URLs. Accept a key, like next=billing, and map it to a path on the server.
  • Or accept only same-origin paths. Parse with new URL(next, "https://app.example"), require that the origin is your own, and redirect to url.pathname + url.search.
  • For several domains, compare the host against an exact allowlist.
  • Don't use regexes or startsWith("/"). Values like //evil.example and /\evil.example pass them, but browsers treat them as other sites.
  • Check the type. req.query.next can be an array.
  • Redirecting to an unchecked next parameter is an open redirect.
  • Attackers use it for phishing links that start with your domain.
  • It can also help OAuth token theft and SSRF allowlist bypasses.
  • Map keys to paths, or parse the URL and require your own origin.
  • Prefix checks and regexes miss //evil.example.