Repository navigation
[Desktop] App stops opening after ~70 launches: every launch adds a persistent auth cookie, and the Cookie header exceeds Node's 16KB limit #10598
Replies: 2 comments
|
补充一个同日、同版本环境的复现( 现象 本地时间 11:26–11:54 之间连续 10 次启动失败,10 份 crash 记录内容完全一致: 窗口一次都没出现;重启不自愈;日志里没有任何指向 cookie / 登录态的提示。 处置 把 补充一点 这里的"每次启动都算一次"很容易被低估:那 10 次失败本身就是重启造成的(插件更新/崩溃重试/连点图标都会重启)。用户完全不知道自己正在消耗这个额度,而且失败时看到的是"应用打不开",不是"登录态异常"。 因此除了你提的三条修复,建议再加一条可观测性:auth 失败时在窗口或日志里明确写出"登录态异常(cookie 过多/无效),需要重置会话数据",并给出可执行的一步操作。否则用户只能靠搜索才能找到"删 cookies"这个解法。 |
|
The reproduction looks conclusive. There is one HTTP-cookie detail that makes the current design especially problematic: cookie scope does not include the TCP port. In other words, these: are different origins for some browser security rules, but cookies are matched primarily by host/domain + path (+ Secure/SameSite rules), not by port. So encoding the port into the cookie name: does not make the browser send that cookie only to that port. Instead, after N launches you effectively get: which explains why the failure grows monotonically until Node rejects the request before application authentication is reached. Because of that, I would treat increasing maxHeaderSize only as a defensive guard, not a fix. I also would not make “prune all dsh-auth-* cookies on startup” the primary fix unless DSH guarantees a single active desktop host. If two desktop instances/profiles can coexist, instance A deleting every DSH auth cookie can invalidate instance B. The cleanest fix depends on the intended concurrency model. If desktop is single-instance, use one stable host-scoped cookie name: Each successful launch then replaces the previous value instead of creating another header entry: Header cardinality remains O(1), not O(number of launches). In that model I would also explicitly expire legacy cookies during migration: otherwise users who already accumulated 60–70 entries can remain unable to reach the request handler that sets the new cookie. That migration cleanup probably needs to happen from Electron's cookie/session API before the first host request, because the reported failure occurs at Node's HTTP parser/header-size boundary. Server-side cleanup is too late if Node rejects the request before routing. If multiple desktop hosts must run concurrently, a different cookie name per port still does not provide isolation, because port is not part of cookie matching. In that case I would reconsider using persistent host-wide cookies as the per-instance credential at all, or introduce an instance-isolation mechanism that the browser actually uses for cookie scoping. I would add a regression test for the lifecycle, not just one request: expected: and a migration test: If concurrent instances are supported, add: One additional security/property test is worthwhile: and verify exactly which DSH cookies the browser is willing to attach there. The current design should not assume that hashing a port into the cookie name gives port-level confidentiality. So I agree with the reported root cause, but I would define the invariant more strongly: rather than merely raising the header limit or periodically deleting cookies. |
Uh oh!
There was an error while loading. Please reload this page.
Summary
On the desktop build, every launch adds one persistent cookie:
dsh-auth-<sha256("127.0.0.1:<port>")>Max-Age: 60 daysAfter enough launches the
Cookierequest header grows past Node's defaulthttp.maxHeaderSize(16,384 bytes), the host rejects the request, and the desktop app can no longer open — including a manual double-click.Symptom
The main process starts, the host prints
dsh web: http://127.0.0.1:<port>/?token=..., then:desktop welcome: Web authentication failed(thrown byconnectDesktopWelcome()in the Electron main process, afternet.fetchreturns non-2xx)A manual double-click reproduces it. A launch with a fresh
--user-data-dirworks, so the app / runtime / plugins are intact — the broken state is persisted user data.Evidence (measured, 2026-10-22, Windows 10 22H2, Electron 44.7.0 / Node 24.21.0)
dsh-auth-*cookies inNetwork/Cookiesname=valuelengthCookieheaderhttp.maxHeaderSizeTimeline that pins the threshold:
Deleting the 71
dsh-auth-*rows restores the app immediately.Reproduction
Option A: start the desktop app ~70 times.
Option B: seed the cookie DB directly (app fully closed):
Then launch →
desktop welcome: Web authentication failed, no window.Suggested fixes
host_key='127.0.0.1' AND name LIKE 'dsh-auth-%'when the host starts. These cookies are per-launch by design, so removing old ones is safe.dsh-auth) so each launch overwrites the previous cookie.A defensive increase of
maxHeaderSizeonly delays the problem and is not recommended.Impact
This "works for ~70 restarts, then breaks permanently" pattern is easy to miss in normal use but hits long-term users hard — every app restart counts, including the ones triggered by plugin updates.
I can attach the (redacted) cookie DB backup or a small reproduction script if useful.
中文摘要:桌面版每次启动随机端口,认证 cookie 名带端口哈希、有效期 60 天、旧的不清理。攒到 71 条时 Cookie 请求头 16,110 字节,超过 Node 默认 16KB 上限,host 直接拒收 →
desktop welcome: Web authentication failed→ 窗口不出现(手动双击也一样)。删掉这 71 条 cookie 即恢复。建议启动时清理旧的dsh-auth-*,或让 cookie 名不带端口。All reactions