Read the session from the tab, not the shared cookie jar

Fixkamo-internal
Shipped
August 24, 2026 at 11:05 PM UTC
Author
kamo
Commit
1b1c236

46 client modules read the *** id out of document.cookie and sent it as X-***-Token. sessionStorage is per-TAB; a cookie is per-ORIGIN. While every organization had a hostname of its own those were the same boundary, so it did not matter. Serving organizations without a domain from one shared host ends that: the cookie becomes a single slot any tab can overwrite, so a tab can send a different organization's session than the one it is displaying. Mostly this was already masked. installSessionLayer() patches window.fetch to set X-***-Token from sessionStorage on same-origin /api/* calls, and headers.set() overwrites, so an explicit cookie-sourced header is normally replaced -- every one of these call sites is same-origin /api/*, and none touches a WebSocket or another origin. Normally is not always: the patch only fires when sessionStorage HAS a token, so a freshly-opened tab with an empty store sends whatever the cookie holds. That is the case this closes. app/logout/page.tsx keeps its cookie writes -- clearing them is how a session is torn down -- and useSmsWebSocket.ts was already migrated; its document.cookie is in a comment explaining why it must not be used. check-session-token-source.mjs holds the line, with those two allowlisted and their reasons recorded. It strips comments before matching, so an explanation of why the cookie is avoided does not read as a use of it. Two files were CRLF and a naive rewrite reflowed them entirely; they were redone byte-wise, so the diff is the substitution and nothing else. 2882 tests and all 8 guards pass. The production build could not be run locally -- other sessions hold the Next build lock continuously -- but tsc is clean and an earlier full build of this same code succeeded; only line endings changed after it.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing