CVE-2021-43812 (TypeScript, published 2021-12-16T19:15Z)
Description: value: The Auth0 Next.js SDK is a library for implementing user authentication in Next.js applications. Versions before 1.6.2 do not filter out certain returnTo parameter values from the login url, which expose the application to an open redirect vulnerability. Users are advised to upgrade as soon as possible. There are no known workarounds for this issue.
Severity: MEDIUM (CVSS v3 base score: 6.1)
Weakness: CWE-601 \u2014 URL Redirection to Untrusted Site ('Open Redirect')
A web application accepts a user-controlled input that specifies a link to an external site, and uses that link in a Redirect. This simplifies phishing attacks.
Repository: https://github.com/auth0/nextjs-auth0
Files changed:
src/handlers/login.ts
src/index.ts
src/utils/url-helpers.ts
tests/fixtures/open-redirect-payloads.json
tests/handlers/login.test.ts
tests/utils/url-helpers.test.ts
Commit message: Enforce configured host on user supplied returnTo (#557)

* Enforce configured host on user supplied returnTo

* Test improvements per PR suggestions

Vulnerable code:
import isSafeRedirect from '../utils/url-helpers';
import { NextConfig } from '../config';
export default function handleLoginFactory(handler: BaseHandleLogin, nextConfig: NextConfig): HandleLogin {
        const returnTo = Array.isArray(req.query.returnTo) ? req.query.returnTo[0] : req.query.returnTo;
        if (!isSafeRedirect(returnTo)) {
          throw new Error('Invalid value provided for returnTo, must be a relative url');
        }
  const handleLogin = loginHandler(baseHandleLogin, nextConfig);
 * @param url
export default function isSafeRedirect(url: string): boolean {
  if (typeof url !== 'string') {
    throw new TypeError(`Invalid url: ${url}`);

  // Prevent open redirects using the //foo.com format (double forward slash).
  if (/\/\//.test(url)) {
    return false;

  return !/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(url);
      returnTo: '/foo'
      returnTo: '/foo'
    await expect(
      get(baseUrl, '/api/auth/login?returnTo=https://www.google.com', { fullResponse: true })
    ).rejects.toThrow('Invalid value provided for returnTo, must be a relative url');
import isSafeRedirect from '../../src/utils/url-helpers';
      expect(isSafeRedirect('file://foo')).toEqual(false);
      expect(isSafeRedirect('https://foo')).toEqual(false);
      expect(isSafeRedirect('http://foo')).toEqual(false);
      expect(isSafeRedirect('/foo')).toEqual(true);
      expect(isSafeRedirect('/foo?some=value')).toEqual(true);
      expect(isSafeRedirect('//google.com')).toEqual(false);
      expect(isSafeRedirect('///google.com')).toEqual(false);
    test('should throw when non string provided', () => {
      expect(isSafeRedirect.bind(null)).toThrow('Invalid url: undefined');

Fixed code:
import toSafeRedirect from '../utils/url-helpers';
import { BaseConfig, NextConfig } from '../config';
export default function handleLoginFactory(
  handler: BaseHandleLogin,
  nextConfig: NextConfig,
  baseConfig: BaseConfig
): HandleLogin {
        const dangerousReturnTo = Array.isArray(req.query.returnTo) ? req.query.returnTo[0] : req.query.returnTo;
        const safeBaseUrl = new URL(options.authorizationParams?.redirect_uri || baseConfig.baseURL);
        const returnTo = toSafeRedirect(dangerousReturnTo, safeBaseUrl);
  const handleLogin = loginHandler(baseHandleLogin, nextConfig, baseConfig);
 * @param dangerousRedirect
 * @param safeBaseUrl
export default function toSafeRedirect(dangerousRedirect: string, safeBaseUrl: URL): string | undefined {
  let url: URL;
  try {
    url = new URL(dangerousRedirect, safeBaseUrl);
  } catch (e) {
    return undefined;
  if (url.origin === safeBaseUrl.origin) {
    return url.toString();
  return undefined;
[
  "javascript:alert(1)",
  "java%0d%0ascript%0d%0a:alert(0)",
  "javascript://%250Aalert(1)",
  "javascript://%250Aalert(1)//?1",
  "javascript://%250A1?alert(1):0",
  "%09Jav%09ascript:alert(document.domain)",
  "javascript://%250Alert(document.location=document.cookie)",
  "/%09/javascript:alert(1);",
  "/%09/javascript:alert(1)",
  "//%5cjavascript:alert(1);",
  "//%5cjavascript:alert(1)",
  "/%5cjavascript:alert(1);",
  "/%5cjavascript:alert(1)",
  "javascript://%0aalert(1)",
  "<>javascript:alert(1);",
  "//javascript:alert(1);",
  "//javascript:alert(1)",
  "/javascript:alert(1);",
  "/javascript:alert(1)",
  "javascript:alert(1)",
  "javascript:alert(1);",
  "javascript:alert(1)",
  "javascripT://anything%0D%0A%0D%0Awindow.alert(document.cookie)",
  "javascript:confirm(1)",
  "javascript://https://whitelisted.com/?z=%0Aalert(1)",
  "javascript:prompt(1)",
  "jaVAscript://whitelisted.com//%0d%0aalert(1);//",
  "javascript://whitelisted.com?%a0alert%281%29",
  "/x:1/:///%01javascript:alert(document.cookie)/",
  "<>//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "//;@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "/////Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "/////Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "////Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ//",
  "////Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "///;@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "///Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ//",
  "///Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "///Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "///Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ//",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "/.Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "/〱Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  ".Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "〱Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ%00｡Ｐⓦ",
  "%01https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "%01https://google.com",
  "////%09/Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "///%09/Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "//%09/Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "/%09/Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "////%09/google.com",
  "///%09/google.com",
  "//%09/google.com",
  "/%09/google.com",
  "////%09/whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "///%09/whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "//%09/whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "/%09/whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "////%09/whitelisted.com@google.com",
  "///%09/whitelisted.com@google.com",
  "//%09/whitelisted.com@google.com",
  "/%09/whitelisted.com@google.com",
  "&%0d%0a1Location:https://google.com",
  "%19Jav%09asc%09ript:https%20://whitelisted.com/%250Aconfirm%25281%2529",
  "////216.58.214.206",
  "///216.58.214.206",
  "//216.58.214.206",
  "/\\216.58.214.206",
  "/216.58.214.206",
  "216.58.214.206",
  "////Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e",
  "///Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e",
  "////Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e%2f",
  "///Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e%2f",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e%2f",
  "////Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f..",
  "///Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f..",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f..",
  "%2f216.58.214.206//",
  "%2f216.58.214.206",
  "%2f216.58.214.206%2f%2f",
  "////Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "///Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "/Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "//%2f%2fⓁ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "/%2f%2fⓁ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "%2f$2f216.58.214.206",
  "$2f%2f216.58.214.206%2f%2f",
  "%2f$2f3627734734",
  "$2f%2f3627734734%2f%2f",
  "//%2f%2fgoogle.com",
  "/%2f%2fgoogle.com",
  "$2f%2fgoogle.com",
  "%2f$2fgoogle.com",
  "$2f%2fgoogle.com%2f%2f",
  "%2f3627734734//",
  "%2f3627734734",
  "%2f3627734734%2f%2f",
  "/%2f%5c%2f%67%6f%6f%67%6c%65%2e%63%6f%6d/",
  "/%2f%5c%2f%6c%6f%63%61%6c%64%6f%6d%61%69%6e%2e%70%77/",
  "%2fgoogle.com//",
  "%2fgoogle.com",
  "%2fgoogle.com%2f%2f",
  "////3627734734",
  "///3627734734",
  "//3627734734",
  "/3627734734",
  "3627734734",
  "//3H6k7lIAiqjfNeN@whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "//3H6k7lIAiqjfNeN@whitelisted.com+@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "//3H6k7lIAiqjfNeN@whitelisted.com@google.com/",
  "//3H6k7lIAiqjfNeN@whitelisted.com+@google.com/",
  "////%5cⓁ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "///%5cⓁ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "//%5cⓁ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "/%5cⓁ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "////%5cgoogle.com",
  "///%5cgoogle.com",
  "//%5cgoogle.com",
  "/%5cgoogle.com",
  "////%5cwhitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "///%5cwhitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "//%5cwhitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "/%5cwhitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "////%5cwhitelisted.com@google.com",
  "///%5cwhitelisted.com@google.com",
  "//%5cwhitelisted.com@google.com",
  "/%5cwhitelisted.com@google.com",
  "/%68%74%74%70%3a%2f%2f%67%6f%6f%67%6c%65%2e%63%6f%6d",
  "%68%74%74%70%3a%2f%2f%67%6f%6f%67%6c%65%2e%63%6f%6d",
  "%68%74%74%70%73%3a%2f%2f%6c%6f%63%61%6c%64%6f%6d%61%69%6e%2e%70%77",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ:80?@whitelisted.com/",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ:80#@whitelisted.com/",
  "\";alert(0);//",
  "data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=",
  "data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik7PC9zY3JpcHQ+Cg==",
  "data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik8L3NjcmlwdD4=",
  "data:whitelisted.com;text/html;charset=UTF-8,<html><script>document.write(document.domain);</script><iframe/src=xxxxx>aaaa</iframe></html>",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ%E3%80%82pw",
  "//google%00.com",
  "/google%252ecom",
  "google%252ecom",
  "<>//google.com",
  "/<>//google.com",
  "//;@google.com",
  "///;@google.com",
  "/////google.com/",
  "/////google.com",
  "////;@google.com",
  "////google.com//",
  "////google.com/",
  "////google.com",
  "///;@google.com",
  "///google.com//",
  "///google.com/",
  "///google.com",
  "///google.com/",
  "//google.com",
  "//google.com//",
  "//google.com/",
  "//google.com",
  "/.google.com",
  "///google.com/",
  "//google.com/",
  "//google.com",
  "/google.com",
  "/〱google.com",
  "/google.com",
  "../google.com",
  ".google.com",
  "@google.com",
  "//google.com/",
  "〱google.com",
  "google.com",
  "google.com%23@whitelisted.com",
  "////google.com/%2e%2e",
  "///google.com/%2e%2e",
  "//google.com/%2e%2e",
  "/google.com/%2e%2e",
  "//google.com/%2E%2E",
  "////google.com/%2e%2e%2f",
  "///google.com/%2e%2e%2f",
  "//google.com/%2e%2e%2f",
  "////google.com/%2f..",
  "///google.com/%2f..",
  "//google.com/%2f..",
  "//google.com/%2F..",
  "/google.com/%2F..",
  "////google.com/%2f%2e%2e",
  "///google.com/%2f%2e%2e",
  "//google.com/%2f%2e%2e",
  "/google.com/%2f%2e%2e",
  "//google.com//%2F%2E%2E",
  "//google.com:80?@whitelisted.com/",
  "//google.com:80#@whitelisted.com/",
  "google.com/.jpg",
  "//google.com\twhitelisted.com/",
  "//google.com/whitelisted.com",
  "//google.com@whitelisted.com",
  "google.com/whitelisted.com",
  "//google%E3%80%82com",
  "/http://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "/http:/Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "http://;@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "http://.Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "http:/Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "http:Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "http://00330.00072.0000326.00000316",
  "http:00330.00072.0000326.00000316",
  "http://00330.0x3a.54990",
  "http:00330.0x3a.54990",
  "http://00330.3856078",
  "http:00330.3856078",
  "http://0330.072.0326.0316",
  "http:0330.072.0326.0316",
  "http:%0a%0dⓁ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "http:%0a%0dgoogle.com",
  "http://0xd8.072.54990",
  "http:0xd8.072.54990",
  "http://0xd8.0x3a.0xd6.0xce",
  "http:0xd8.0x3a.0xd6.0xce",
  "http://0xd8.3856078",
  "http:0xd8.3856078",
  "http://0xd83ad6ce",
  "http:0xd83ad6ce",
  "http://[::216.58.214.206]",
  "http:[::216.58.214.206]",
  "http://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ%23.whitelisted.com/",
  "http://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ%2f%2f.whitelisted.com/",
  "http://3627734734",
  "http:3627734734",
  "http://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ%3F.whitelisted.com/",
  "http://3H6k7lIAiqjfNeN@00330.00072.0000326.00000316",
  "http:3H6k7lIAiqjfNeN@00330.00072.0000326.00000316",
  "http://3H6k7lIAiqjfNeN@00330.0x3a.54990",
  "http:3H6k7lIAiqjfNeN@00330.0x3a.54990",
  "http://3H6k7lIAiqjfNeN@00330.3856078",
  "http:3H6k7lIAiqjfNeN@00330.3856078",
  "http://3H6k7lIAiqjfNeN@0330.072.0326.0316",
  "http:3H6k7lIAiqjfNeN@0330.072.0326.0316",
  "http://3H6k7lIAiqjfNeN@0xd8.072.54990",
  "http:3H6k7lIAiqjfNeN@0xd8.072.54990",
  "http://3H6k7lIAiqjfNeN@0xd8.0x3a.0xd6.0xce",
  "http:3H6k7lIAiqjfNeN@0xd8.0x3a.0xd6.0xce",
  "http://3H6k7lIAiqjfNeN@0xd8.3856078",
  "http:3H6k7lIAiqjfNeN@0xd8.3856078",
  "http://3H6k7lIAiqjfNeN@0xd83ad6ce",
  "http:3H6k7lIAiqjfNeN@0xd83ad6ce",
  "http://3H6k7lIAiqjfNeN@[::216.58.214.206]",
  "http:3H6k7lIAiqjfNeN@[::216.58.214.206]",
  "http://3H6k7lIAiqjfNeN@3627734734",
  "http:3H6k7lIAiqjfNeN@3627734734",
  "http://3H6k7lIAiqjfNeN@472.314.470.462",
  "http:3H6k7lIAiqjfNeN@472.314.470.462",
  "http://3H6k7lIAiqjfNeN@[::ffff:216.58.214.206]",
  "http:3H6k7lIAiqjfNeN@[::ffff:216.58.214.206]",
  "http://3H6k7lIAiqjfNeN@whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "http://3H6k7lIAiqjfNeN@whitelisted.com+@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "http://3H6k7lIAiqjfNeN@whitelisted.com@google.com/",
  "http://3H6k7lIAiqjfNeN@whitelisted.com+@google.com/",
  "http://472.314.470.462",
  "http:472.314.470.462",
  "http://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ%5c%5c.whitelisted.com/",
  "/http://%67%6f%6f%67%6c%65%2e%63%6f%6d",
  "http://%67%6f%6f%67%6c%65%2e%63%6f%6d",
  "http://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ:80?@whitelisted.com/",
  "http://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ:80#@whitelisted.com/",
  "http://[::ffff:216.58.214.206]",
  "http:[::ffff:216.58.214.206]",
  "/http://google.com",
  "/http:/google.com",
  "http://;@google.com",
  "http://.google.com",
  "http://google.com",
  "http://google.com",
  "http:/google.com",
  "http:google.com",
  "http://google.com%23.whitelisted.com/",
  "http://google.com%2f%2f.whitelisted.com/",
  "http://google.com%3F.whitelisted.com/",
  "http://google.com%5c%5c.whitelisted.com/",
  "http://google.com:80?@whitelisted.com/",
  "http://google.com:80#@whitelisted.com/",
  "http://google.com\twhitelisted.com/",
  "//https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ//",
  "/https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ//",
  "https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "https:Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "https://%09/Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "/https://%09/google.com",
  "https://%09/google.com",
  "https://%09/whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "https://%09/whitelisted.com@google.com",
  "https://%0a%0dⓁ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "https://%0a%0dgoogle.com",
  "//https:///Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e",
  "/https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e",
  "https:///Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e",
  "//https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e%2f",
  "https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e%2f",
  "/https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f..",
  "https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f..",
  "/https:///Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "/https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "https:///Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "https%3a%2f%2fgoogle.com%2f",
  "/https://%5cⓁ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "/https:/%5cⓁ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "https://%5cⓁ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "https:/%5cⓁ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "/https://%5cgoogle.com",
  "/https:/%5cgoogle.com/",
  "https://%5cgoogle.com",
  "https:/%5cgoogle.com/",
  "/https://%5cwhitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "https://%5cwhitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "/https://%5cwhitelisted.com@google.com",
  "https://%5cwhitelisted.com@google.com",
  "https://%6c%6f%63%61%6c%64%6f%6d%61%69%6e%2e%70%77",
  "//https://google.com//",
  "/https://google.com//",
  "/https://google.com/",
  "/https://google.com",
  "/https:google.com",
  "https://////google.com",
  "https://google.com//",
  "https://google.com/",
  "https://google.com",
  "https:/google.com",
  "https:google.com",
  "//https:///google.com/%2e%2e",
  "/https://google.com/%2e%2e",
  "https:///google.com/%2e%2e",
  "//https://google.com/%2e%2e%2f",
  "https://google.com/%2e%2e%2f",
  "/https://google.com/%2f..",
  "https://google.com/%2f..",
  "/https:///google.com/%2f%2e%2e",
  "/https://google.com/%2f%2e%2e",
  "https:///google.com/%2f%2e%2e",
  "https://google.com/%2f%2e%2e",
  "https://:@google.com@whitelisted.com",
  "https://google.com?whitelisted.com",
  "https://google.com/whitelisted.com",
  "https://google.comwhitelisted.com",
  "https://google.com#whitelisted.com",
  "https://google%E3%80%82com",
  "//https://whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ//",
  "/https://whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "https://:@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ@whitelisted.com",
  "https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/whitelisted.com",
  "https://whitelisted.com;@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "https://whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ//",
  "https://whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "https://whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "/https://whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e",
  "https:///whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e",
  "//https://whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e%2f",
  "https://whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e%2f",
  "/https://whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f..",
  "https://whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f..",
  "/https:///whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "/https://whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "https:///whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "https://whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "//https://whitelisted.com@google.com//",
  "/https://whitelisted.com@google.com/",
  "https://whitelisted.com;@google.com",
  "https://whitelisted.com.google.com",
  "https://whitelisted.com@google.com//",
  "https://whitelisted.com@google.com/",
  "https://whitelisted.com@google.com",
  "/https://whitelisted.com@google.com/%2e%2e",
  "https:///whitelisted.com@google.com/%2e%2e",
  "//https://whitelisted.com@google.com/%2e%2e%2f",
  "https://whitelisted.com@google.com/%2e%2e%2f",
  "/https://whitelisted.com@google.com/%2f..",
  "https://whitelisted.com@google.com/%2f..",
  "/https:///whitelisted.com@google.com/%2f%2e%2e",
  "/https://whitelisted.com@google.com/%2f%2e%2e",
  "https:///whitelisted.com@google.com/%2f%2e%2e",
  "https://whitelisted.com@google.com/%2f%2e%2e",
  "/https://whitelisted.com@google.com/%2f.//whitelisted.com@google.com/%2f..",
  "https://whitelisted.com/https://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "https://whitelisted.com/https://google.com/",
  "@https://www.google.com",
  "http://Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ\twhitelisted.com/",
  "http://whitelisted.com@00330.00072.0000326.00000316",
  "http:whitelisted.com@00330.00072.0000326.00000316",
  "http://whitelisted.com@00330.0x3a.54990",
  "http:whitelisted.com@00330.0x3a.54990",
  "http://whitelisted.com@00330.3856078",
  "http:whitelisted.com@00330.3856078",
  "http://whitelisted.com@0330.072.0326.0316",
  "http:whitelisted.com@0330.072.0326.0316",
  "http://whitelisted.com@0xd8.072.54990",
  "http:whitelisted.com@0xd8.072.54990",
  "http://whitelisted.com@0xd8.0x3a.0xd6.0xce",
  "http:whitelisted.com@0xd8.0x3a.0xd6.0xce",
  "http://whitelisted.com@0xd8.3856078",
  "http:whitelisted.com@0xd8.3856078",
  "http://whitelisted.com@0xd83ad6ce",
  "http:whitelisted.com@0xd83ad6ce",
  "http://whitelisted.com@[::216.58.214.206]",
  "http:whitelisted.com@[::216.58.214.206]",
  "http://whitelisted.com%2eⓁ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "http://whitelisted.com%2egoogle.com/",
  "http://whitelisted.com@3627734734",
  "http:whitelisted.com@3627734734",
  "http://whitelisted.com@472.314.470.462",
  "http:whitelisted.com@472.314.470.462",
  "http://whitelisted.com:80%40Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "http://whitelisted.com:80%40google.com/",
  "http://whitelisted.com@[::ffff:216.58.214.206]",
  "http:whitelisted.com@[::ffff:216.58.214.206]",
  "http://whitelisted.com@google.com/",
  "http://whitelisted.com+&@google.com#+@whitelisted.com/",
  "http://whitelisted.com+&@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ#+@whitelisted.com/",
  "http://www.google.com.whitelisted.com",
  "http://www.Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ.whitelisted.com",
  "ja\nva\tscript\r:alert(1)",
  "java%09script:alert(1)",
  "java%0ascript:alert(1)",
  "java%0d%0ascript%0d%0a:alert(0)",
  "java%0dscript:alert(1)",
  "Javas%26%2399;ript:alert(1)",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ\twhitelisted.com/",
  "\u006A\u0061\u0076\u0061\u0073\u0063\u0072\u0069\u0070\u0074\u003aalert(1)",
  "////whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ//",
  "////whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "///whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ//",
  "///whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/whitelisted.com",
  "//Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ@whitelisted.com",
  "//whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ//",
  "//whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/",
  "Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/whitelisted.com",
  "whitelisted.com;@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ",
  "////whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e",
  "///whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e",
  "////whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e%2f",
  "///whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e%2f",
  "//whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e%2f",
  "////whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f..",
  "///whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f..",
  "//whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f..",
  "////whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "///whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "//whitelisted.com@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2f%2e%2e",
  "/whitelisted.com:80%40google.com",
  "whitelisted.com@%E2%80%AE@google.com",
  "////whitelisted.com@google.com//",
  "////whitelisted.com@google.com/",
  "///whitelisted.com@google.com//",
  "///whitelisted.com@google.com/",
  "//whitelisted.com@google.com//",
  "//whitelisted.com@google.com/",
  "whitelisted.com;@google.com",
  "whitelisted.com.google.com",
  "////whitelisted.com@google.com/%2e%2e",
  "///whitelisted.com@google.com/%2e%2e",
  "////whitelisted.com@google.com/%2e%2e%2f",
  "///whitelisted.com@google.com/%2e%2e%2f",
  "//whitelisted.com@google.com/%2e%2e%2f",
  "////whitelisted.com@google.com/%2f..",
  "///whitelisted.com@google.com/%2f..",
  "//whitelisted.com@google.com/%2f..",
  "////whitelisted.com@google.com/%2f%2e%2e",
  "///whitelisted.com@google.com/%2f%2e%2e",
  "//whitelisted.com@google.com/%2f%2e%2e",
  "//whitelisted.com+&@google.com#+@whitelisted.com/",
  "//whitelisted.com@https:///Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ/%2e%2e",
  "//whitelisted.com@https:///google.com/%2e%2e",
  "//whitelisted.com+&@Ⓛ𝐨𝗰�𝕝ⅆ𝓸ⓜₐℹⓃ｡Ｐⓦ#+@whitelisted.com/"
]
      returnTo: new URL('/foo', withoutApi.baseURL).toString()
      returnTo: new URL('/foo', withoutApi.baseURL).toString()
    const cookieJar = new CookieJar();
    await get(baseUrl, '/api/auth/login?returnTo=https://www.google.com', { cookieJar });
    const { value: state } = getCookie('state', cookieJar, baseUrl) as Cookie;

    const decodedState = decodeState(state.split('.')[0]);
    expect(decodedState).toEqual({});
  });

  test('should allow absolute urls in params of returnTo urls', async () => {
    const loginOptions = {
      returnTo: '/default-redirect'
    };
    const baseUrl = await setup(withoutApi, { loginOptions });

    const cookieJar = new CookieJar();
    await get(baseUrl, '/api/auth/login?returnTo=/foo?url=https://www.google.com', { cookieJar });
    const { value: state } = getCookie('state', cookieJar, baseUrl) as Cookie;

    const decodedState = decodeState(state.split('.')[0]);
    expect(decodedState).toEqual({
      returnTo: new URL('/foo?url=https://www.google.com', withoutApi.baseURL).toString()
    });
  });

  test('should redirect relative to the redirect_uri over the base url', async () => {
    const loginOptions = {
      returnTo: '/default-redirect',
      authorizationParams: {
        redirect_uri: 'https://other-org.acme.com/api/auth/callback'
      }
    };
    const baseUrl = await setup(withoutApi, { loginOptions });

    const cookieJar = new CookieJar();
    await get(baseUrl, '/api/auth/login?returnTo=/foo', { cookieJar });
    const { value: state } = getCookie('state', cookieJar, baseUrl) as Cookie;

    const decodedState = decodeState(state.split('.')[0]);
    expect(decodedState).toEqual({
      returnTo: 'https://other-org.acme.com/foo'
    });
import toSafeRedirect from '../../src/utils/url-helpers';
import payloads from '../fixtures/open-redirect-payloads.json';
  const safeBaseUrl = new URL('http://www.example.com');

      expect(toSafeRedirect('file://foo', safeBaseUrl)).toEqual(undefined);
      expect(toSafeRedirect('https://foo', safeBaseUrl)).toEqual(undefined);
      expect(toSafeRedirect('http://foo', safeBaseUrl)).toEqual(undefined);
      expect(toSafeRedirect('/foo', safeBaseUrl)).toEqual('http://www.example.com/foo');
      expect(toSafeRedirect('foo', safeBaseUrl)).toEqual('http://www.example.com/foo');
      expect(toSafeRedirect('/foo?some=value', safeBaseUrl)).toEqual('http://www.example.com/foo?some=value');
      expect(toSafeRedirect('/foo?someUrl=https://www.google.com', safeBaseUrl)).toEqual(
        'http://www.example.com/foo?someUrl=https://www.google.com'
      );
      expect(toSafeRedirect('/foo', new URL('http://www.example.com:8888'))).toEqual('http://www.example.com:8888/foo');
      for (const payload of payloads) {
        expect(toSafeRedirect(payload, safeBaseUrl) || safeBaseUrl.toString()).toMatch(/^http:\/\/www.example.com\//);
      }
    test('should not throw for empty redirect', () => {
      expect(toSafeRedirect.bind(null, '', safeBaseUrl)).not.toThrow();