{"record":{"id":"799bc7dfca56387b","repo":"sveltejs/kit","slug":"cannot-redirect-to-json-stringify-location-wit","errorCode":null,"errorMessage":"Cannot redirect to ${JSON.stringify(location)} with `{ external: true }`. The `javascript:` and `data:` protocols must be explicitly listed in the `external` allowlist (prod: 'Cannot redirect to external URL unless explicitly allowed')","messagePattern":"Cannot redirect to (.+?) with `(.+?)`\\. The `javascript:` and `data:` protocols must be explicitly listed in the `external` allowlist \\(prod: 'Cannot redirect to external URL unless explicitly allowed'\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/kit/src/exports/url.js","lineNumber":58,"sourceCode":" * @param {{ external?: boolean | string[] }} [options]\n */\nexport function validate_redirect_location(location, options) {\n\tif (!is_external_location(location)) return;\n\n\tconst external = options?.external;\n\n\tif (!external) {\n\t\tthrow new Error(\n\t\t\tDEV\n\t\t\t\t? `Cannot redirect to external URL ${JSON.stringify(location)}. ` +\n\t\t\t\t\t\t'To redirect to an external URL, pass `{ external: true }` or an allowlist of permitted origins as the third argument to `redirect`'\n\t\t\t\t: 'Cannot redirect to external URL unless explicitly allowed'\n\t\t);\n\t}\n\n\tif (external === true) {\n\t\tif (is_javascript_location(location)) {\n\t\t\tthrow new Error(\n\t\t\t\tDEV\n\t\t\t\t\t? `Cannot redirect to ${JSON.stringify(location)} with \\`{ external: true }\\`. ` +\n\t\t\t\t\t\t\t'The `javascript:` and `data:` protocols must be explicitly listed in the `external` allowlist'\n\t\t\t\t\t: 'Cannot redirect to external URL unless explicitly allowed'\n\t\t\t);\n\t\t}\n\n\t\treturn;\n\t}\n\n\tif (Array.isArray(external)) {\n\t\tif (!external.some((allowed) => matches_external_allowlist_entry(location, allowed))) {\n\t\t\tthrow new Error(\n\t\t\t\tDEV\n\t\t\t\t\t? `Cannot redirect to ${JSON.stringify(location)}: URL origin is not included in the \\`external\\` allowlist`\n\t\t\t\t\t: 'Cannot redirect to external URL unless explicitly allowed'\n\t\t\t);\n\t\t}","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/sveltejs/kit/blob/03f1687fe612ce3d2d9131139b5b188d9cf90c64/packages/kit/src/exports/url.js#L40-L76","documentation":"Even with `{ external: true }`, SvelteKit blocks `javascript:` and `data:` URLs because redirecting to them is a code-injection/XSS vector. Such URLs can only be redirected to if they are explicitly listed in an `external` allowlist array, signaling deliberate intent.","triggerScenarios":"Calling `redirect(302, 'javascript:alert(1)', { external: true })` or `redirect(302, 'data:text/html,...', { external: true })` — `true` is not enough; only `external: ['javascript:...', 'data:...']` permits these schemes.","commonSituations":"Passing user-supplied URLs straight through with `external: true` in a test harness or admin tool; accidentally forwarding a `data:` URL captured from a form or query parameter.","solutions":["Remove any `javascript:`/`data:` redirect targets — use regular `https://` or relative URLs.","If genuinely required (rare), enumerate them in an allowlist: `redirect(302, loc, { external: ['javascript:myscheme'] })` (pattern: explicit allowed origins/schemes array).","Sanitize input: reject or strip locations whose scheme is not `http:`/`https:` or a relative path.","Treat any user path that produces these URLs as an attack attempt and fall back to a safe default redirect."],"exampleFix":"// before\nredirect(302, target, { external: true }); // target may be 'data:...'\n// after\nif (/^data:|^javascript:/i.test(target)) redirect(302, '/');\nelse redirect(302, target, { external: true });","handlingStrategy":"validation","validationCode":"function isSafeRedirectTarget(loc) {\n  if (/^(javascript|data):/i.test(loc)) return false;\n  try { const u = new URL(loc, 'http://internal'); return !/^javascript:|^data:/i.test(u.protocol); }\n  catch { return false; }\n}\nif (!isSafeRedirectTarget(target)) redirect(302, '/');","typeGuard":"const isWebUrl = (s) => {\n  try { const u = new URL(s, 'http://internal'); return ['http:', 'https:'].includes(u.protocol); }\n  catch { return false; }\n};","tryCatchPattern":"try {\n  redirect(302, target, { external: true });\n} catch (e) {\n  if (String(e.message).includes('javascript:') || String(e.message).includes('data:')) {\n    redirect(302, '/');\n  } else throw e;\n}","preventionTips":["Allowlist schemes: only http/https (or relative) targets.","Reject any location starting with javascript: or data: outright.","Log and drop suspicious redirect targets from user input.","Pass an explicit origins array rather than `external: true` when possible."],"tags":["redirect","xss","security","validation","sveltekit"],"backgroundTag":"open-redirect-blocked","analyzedSha":"03f1687fe612ce3d2d9131139b5b188d9cf90c64","analyzedAt":"2026-09-02T02:01:50.504Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}