v0.50.258 — login stability for VPN / Tailscale users
Small focused login-stability batch. Three independent fixes from #1419 plus an Opus pre-release advisor follow-up that fixed a real multi-param query truncation bug in the redirect URL encoding before tag.
Fixed
- Login stability: 30-day session TTL, redirect-back, connectivity probe (#1419) — three independent fixes for users on flaky networks. (1)
SESSION_TTLextended from 24 hours to 30 days inapi/auth.pyso users no longer get kicked out daily. (2) When a session expires and the user is redirected to/login, the server now passes?next=<original-path>so_safeNextPath()instatic/login.jsredirects them back after a successful login instead of dumping them on the login screen. (3) Login page now probes/healthon load (a public endpoint) and distinguishes "session expired / wrong password" from "can't reach server" — when the server is unreachable, shows a clear "Cannot reach server — check your VPN / Tailscale connection." message, disables the form, retries every 3 seconds, and auto-reloads the page once the server becomes reachable again. (#1419, @bsgdigital)
Pre-release hardening (Opus advisor)
- Login redirect URL encoding fix — multi-param queries no longer truncated — the original PR #1419 implementation built the outer
?next=parameter viaquote(path, safe='/:@!$&\'()*+,;=')which kept?and&literal. Two real problems: (a) paths with multi-param queries (e.g./api/sessions?limit=50&offset=0) round-tripped as/api/sessions?limit=50because the inner&terminated the outernextvalue andoffset=0leaked out as a top-level outer query parameter the login page ignored; (b) attacker-controlled paths with embedded&next=https://evil.cominjected a second top-levelnextparameter (browsers'URLSearchParams.get()returns first-match (benign), Python'sparse_qsreturns last-match (the evil URL) — parser-divergence footgun even though_safeNextPath()rejects the actual exploit). Fix encodes the entirepath?queryblob withsafe='/'so?,&,=all percent-encode. The outernextthen holds exactly one path-with-query string the browser auto-decodes once. CRLF injection through the redirect URL also confirmed blocked (\rand\npercent-encoded byquote()). 6 regression tests pin the round-trip behavior across simple paths, single-query paths, multi-param queries, and attacker-injection neutralization.
Tests
3610 passed, 2 skipped, 3 xpassed, 0 failed. Browser tests + Phase 2 API sanity all green. Independent end-to-end review by @nesquena traced the encoding fix across a 12-scenario behavioral harness (including CRLF injection, protocol-relative paths, control-char paths) and verified the _safeNextPath() 4-layer open-redirect guard chain holds.
Contributors
@bsgdigital · @nesquena (review)
Held for next release
- #1418 (DeepSeek 1M variants) — deferred until hermes-agent #18534 lands the regex widening that accepts the
[1m]model ID suffix. Without it, dropdown selections silently route throughdeepseek-chat.
Full Changelog: v0.50.257...v0.50.258