fix(#5578): stop login next= param from nesting into itself and exploding the URL
An expired-auth 401 on the login page fed the login redirect its own address: each of the three redirect guards (_safeNextPath in login.js, _safe_login_redirect_path in routes.py, the api() 401 redirect in workspace.js, _safe_login_inner_next in auth.py) validated against open-redirect but none rejected a `next` pointing back at the login page, so every auth bounce wrapped + re-encoded the previous login URL one level deeper — growing the URL exponentially until the browser's length limit broke the tab. All guards now collapse/reject a `next` whose decoded leading PATH resolves to the login route (bounded percent-decoding up to 8 levels, fail-closed at the cap), while preserving the existing open-redirect protections AND legitimate non-login paths that merely carry their own `next=` query key. Length cap as belt-and-suspenders. Self-built (nesquena-hermes); nesquena independent review APPROVED. Gate (Codex) found + fixed an over-broad nested-next reject (regressed next-carrying paths) and a deep-encode decode off-by-one; both root-fixed, login guards verified clean.
This commit is contained in:
1 parent
1f68c8cfa5
commit
e09e819f08
7 files changed
+293
-3
No files matched your search
@@ -3071,6 +3071,10 @@ window._mirrorSpeechSettingsFromServer=_mirrorSpeechSettingsFromServer;
|
||||
return true;
|
||||
};
|
||||
const redirectToLogin=(nextUrl)=>{
|
||||
// #5578: never nest the login URL into its own next= — if already on a
|
||||
// login-shaped page, reload 'login' bare (the page keeps its inner next).
|
||||
const _p=(window.location.pathname||'').replace(/\/+$/,'');
|
||||
if(/(?:^|\/)login$/.test(_p)){window.location.href='login';return;}
|
||||
window.location.href='login?next='+encodeURIComponent(nextUrl);
|
||||
};
|
||||
return {
|
||||
|
||||
Reference in new issue
Block a user