Play · Field Note
Google device-bound my cookies and killed my SMS bridge
Chrome’s Device Bound Session Credentials went GA in 2026 and quietly broke every tool that authenticates by copying your Google cookies. Not by blocking them; by putting them on a clock. This is the story of diagnosing an expiry you cannot see, and why “it worked for two hours” was the whole clue.
July 27, 2026
Part of my personal operating system is an SMS bridge: a small daemon on the Mac that pairs with Google Messages on my phone, so my assistant can read and triage texts from the terminal. It authenticates the way a whole family of local-first tools does: you sign in to Google in a browser, copy the session cookies, and hand them to the daemon.
One week in July, that stopped working. And it stopped working in the most confusing way possible: the pairing itself succeeded every time. The daemon connected, backfilled every conversation, and ran clean; then, roughly two hours later, every request came back 401 SESSION_COOKIE_INVALID and the relay was dead. A failure at minute zero says you did something wrong. A failure at hour two, after thousands of successful requests, says something is happening to you.
Three wrong theories
The first capture came from my regular Chrome profile, and the session died in eleven minutes. The theory wrote itself: the browser and the daemon were sharing one session, Google rotates these cookies continuously, and whoever rotates first wins; Chrome won. The fix would be capturing from a private window and closing it without signing out, so the daemon owns the session alone. That capture died at one hour and fifty-five minutes.
Theory two blamed contention on the phone side; Google Messages allows a small set of paired computers, and one of mine still held a live web session. So for the third attempt I removed every paired device and closed every Messages tab before capturing. That bought four minutes: one hour and fifty-nine.
Two deaths four minutes apart is not a race. It is a clock.
| Captured from | Session lifetime |
|---|---|
| Chrome, regular profile | 11 minutes |
| Chrome, incognito | 1h 55m |
| Chrome, incognito, every paired device removed first | 1h 59m |
| Safari, private window | alive at 43 hours |
Reading the answer out of Chrome's own state
The answer was sitting on my own disk, in a SQLite database Chrome keeps under a name that gives the whole thing away: Device Bound Sessions. Inside it, one registered session for google.com holding a record named sidts_session, which rotates the __Secure-1PSIDTS cookie through an endpoint called RotateBoundCookies. That rotation is not a refresh; it is a challenge, signed by a private key that lives in this Mac’s Secure Enclave and cannot leave it.
This is Device Bound Session Credentials. Under DBSC, the cookie I copied was cryptographically married to the Chrome instance that minted it. The copy stays valid exactly as long as Google tolerates a session that never answers a rotation challenge, which turns out to be about two hours; then it hard-fails. The invalidation was never a race and never contention. It was a timer that started the moment I copied the cookie.
The upstream maintainers of the bridge library had already written it down, in documentation I had read past three times: a private window is required, and you cannot capture from a browser with DBSC enabled. Firefox has not implemented it; Safari has not either. I had satisfied the first half of that sentence on three consecutive attempts and never the second half.
This is not a villain story
It would be easy to write this up as Google breaking the little guy’s tools, and it would be wrong. DBSC exists because stolen-cookie account takeover is real and rampant; malware that exfiltrates a session cookie gets the account without ever seeing the password or the second factor. DBSC’s answer is precise: make a copied cookie useless by binding the session to hardware it cannot follow.
The honest difficulty is that a local-first tool copying its own user’s cookie, with that user’s full consent, is indistinguishable from the attack the mechanism was built to stop. There is no header for “I meant to do this.” Good security and good tinkering are going to keep colliding exactly here, and the tinkerer’s move is not outrage; it is reading the spec and routing around it honestly.
The part most writeups skip: not being sure
At this point I had a beautiful theory and no proof. Three explanations survived the investigation. DBSC binding, which switching to a non-DBSC browser would fix. The possibility that incognito windows never enroll in DBSC at all, in which case my captures were never bound and the theory explained nothing. And the possibility that Google had simply shortened its tolerance for any session that never rotates, in which case no browser choice would help. Only one of the three was fixable by opening Safari.
Testing the normal way costs a full pairing ceremony each round: capture, hand-off, a confirmation tap on the phone. I had spent three of those on wrong theories already. So the experiment became its own small tool: a probe that tests the cookies alone. Sign in once in a Safari private window, capture, and let a script ask Google every ten minutes whether the session is still alive. No daemon, no pairing, no phone; just the one variable that mattered, isolated.
The verdict
The Safari-captured session was alive at every check for six straight hours, when the probe hit its cap and stopped. Three times the Chrome ceiling, and the probe was the cheapest experiment of the whole saga.
Then the better evidence arrived by accident. Nobody opened Safari again for two days, so that session sat on disk, completely static, rotated by no one. When I came back to it, forty-three hours old, it still answered alive. That number does double duty: it confirms the DBSC theory, and it kills the last rival, because a session that survives forty-three hours without a single rotation is proof that Google is not culling non-rotating sessions on a short fuse. The Chrome captures were the entire problem.
I re-paired the bridge with those two-day-old cookies. It is live again as I write this. And the failure mode that made every death so expensive is fixed separately: the daemon used to destroy its phone pairing whenever the cookies expired, turning a thirty-second credential refresh into a full ceremony. Now the pairing survives a cookie death, and recovery is pasting fresh cookies. The clock may find some new way to run out; the cost of it running out has collapsed.
The endpoint trap
One lesson from this week generalizes beyond Google, beyond cookies, beyond bridges, and it is the one I would keep if I could keep only one. The obvious health check was a lie. The endpoint the pairing flow itself uses returns 200 to completely unauthenticated requests; I verified it with a jar of fake cookies. Any monitor built on it would have reported a dead session as healthy forever.
The probe works because it polls two endpoints that can actually say no: Gmail’s atom feed answers 401 without a live session, and the account page answers with a redirect. It declares death only when both agree.
# every 10 minutes, ask two endpoints that can actually say no
atom=$(curl -s -o /dev/null -w '%{http_code}' -H "Cookie: $COOKIES" \
'https://mail.google.com/mail/u/0/feed/atom') # 401 when dead
acct=$(curl -s -o /dev/null -w '%{http_code}' -H "Cookie: $COOKIES" \
'https://myaccount.google.com') # 302 when dead
# declare death only when both agree; log the hour, never the cookieBefore you trust any liveness check, feed it garbage and watch it fail. A liveness probe that cannot fail is not a liveness probe.
What remains honest to say: the re-paired bridge is hours old as this publishes, and the daemon now owns a session it is expected to rotate itself. If it dies again, the diagnosis starts from a better place than last time, with a probe that costs nothing and endpoints that tell the truth. That is usually what a week like this buys. Not certainty; better instruments.