Session Binding Finally Has a Real Answer: How DBSC Uses Your TPM to Kill Cookie Theft
Source: lobsters
MFA adoption killed a lot of credential-stuffing attacks. Attackers adapted. Instead of stealing passwords, they started stealing the session cookies that get issued after a successful login, bypassing MFA entirely because the cookie represents an already-authenticated session. That shift created the infostealer economy: a mature, industrialized market for tools like Redline, Raccoon, Vidar, and Lumma that specialize in extracting browser cookie stores and selling them on log markets within hours of infection.
The 2023 CircleCI breach traced back to session cookie theft from a developer’s laptop. Repeated YouTube creator account takeovers in 2022 and 2023 came from malicious email attachments that dropped infostealers. The 2024 wave of Snowflake customer breaches shared the same root cause. The common thread is that a cookie is a bearer token: possession equals authentication, no questions asked, regardless of where or on what device it gets used.
Google’s April 2026 announcement about Device Bound Session Credentials represents the most technically coherent answer to this problem that the web platform has produced. Understanding why requires looking at what failed before it.
Token Binding and Why It Didn’t Survive
The web security community tried to solve session binding before. RFC 8471, Token Binding over HTTP, was the most serious attempt. The idea was to cryptographically bind tokens to the TLS connection using a private key held by the browser. A stolen cookie would be useless because it would be tied to the TLS session that issued it, not to any future connection from a different machine.
Token Binding had Microsoft’s full support and partial Chrome support. It died anyway. Chrome removed it in Chrome 70. The post-mortems pointed to several causes: incompatibility with TLS 1.3 middleboxes, the complexity of binding at the TLS layer, the near-zero server adoption outside Microsoft’s services, and a fundamental architectural mismatch between TLS connection ephemerality and the session lifetimes web apps actually use. The IETF working group closed. The lesson was that binding to the transport layer is the wrong abstraction.
Device Bound Session Credentials (DBSC) learns from that failure in a specific way: it binds to the device, not the connection. The private key lives in the platform’s hardware secure enclave, operations happen at the application layer via HTTP headers, and the binding survives TLS connection changes, network switches, and middleboxes. These are not incidental design choices; they are the direct corrections to the reasons Token Binding failed.
The Threat Model, Precisely
Before getting into the protocol, it’s worth being precise about what DBSC is and is not protecting against.
The primary threat is cookie exfiltration followed by replay from a different device. An infostealer running with user-level privileges extracts the browser’s cookie store (encrypted with DPAPI or macOS Keychain keys that the malware can decrypt while running in the user’s session), uploads the cookies to a command-and-control server, and a human operator or automated tool uses them to log into the victim’s accounts from infrastructure in another country. This is the scenario DBSC directly defeats.
What DBSC does not defeat: an attacker who maintains persistent access to the compromised machine and acts as a real-time transparent proxy, relaying challenge-response operations through the victim’s TPM. This is a significantly higher bar for the attacker, requiring sustained presence rather than a one-time exfiltration, but it is not impossible. DBSC also does not protect against browser extension compromise (extensions with cookie access could intercept cookies before short-lived rotation), server-side session database breaches, or social engineering where the user performs the actions themselves.
That honest framing matters because DBSC is sometimes described as ending session hijacking. It ends a large and economically dominant subset of session hijacking. Sophisticated, persistent, targeted attacks remain possible.
How the Protocol Works
DBSC operates at the HTTP header layer. The WICG specification defines a handshake between the server and browser that happens transparently, without JavaScript involvement in the common case.
Session Registration
After a user authenticates, the server signals DBSC support in the response headers:
Sec-Session-Registration: path="/auth/dbsc/register"; challenge="<base64-nonce>"
The browser sees this header and generates a new asymmetric key pair for the session. The private key is stored in the platform’s secure key store: TPM 2.0 via Windows CNG on Windows, the Secure Enclave via macOS Keychain on macOS, Android Keystore backed by StrongBox on Android. The private key never leaves the hardware; all signing operations execute inside the secure element.
The browser then sends a registration request to the specified path. The body is a signed JWT:
{
"iss": "https://origin.example",
"sub": "<session-id>",
"jti": "<challenge-nonce>",
"iat": 1744300000,
"key": {
"kty": "EC",
"crv": "P-256",
"x": "...",
"y": "..."
}
}
The JWT is signed with ES256 (ECDSA with SHA-256 over P-256), the curve most widely supported by TPM implementations. The server validates the signature, stores the public key associated with the session, and returns a configuration response specifying the refresh endpoint, session lifetime, and which cookies are covered by the binding.
The Proof-of-Possession Loop
This is where the actual protection lives. The server issues session cookies as it normally would, but those cookies have short lifetimes (hours rather than weeks). When a protected cookie is about to expire or when the server requests proof, the browser contacts the refresh endpoint with a signed challenge:
- The refresh endpoint issues a fresh nonce in the
Sec-Session-Challengeheader. - The browser signs the nonce with the TPM-bound private key.
- The signed proof goes back to the refresh endpoint in the
Sec-Session-Responseheader. - The server validates the signature against the stored public key.
- On success, the server issues a new short-lived session cookie.
- The original request proceeds.
From the user’s perspective, nothing happens. The browser handles the refresh loop entirely in the background.
The key insight is what this does to stolen cookies. An attacker who exfiltrates a session cookie gets a credential that will fail to refresh. The server requires a valid signed proof for each refresh cycle. The attacker’s machine cannot produce that proof because the private key is locked inside the victim’s TPM hardware. The cookie expires and the stolen session becomes useless, typically within the hour.
The Challenge Header
Servers can also inject a challenge into any response, not just the dedicated refresh endpoint:
Sec-Session-Challenge: "<nonce>"; id="session-id"
This triggers an out-of-band proof-of-possession without blocking the current request. It gives servers a way to demand device verification on sensitive operations (account settings changes, high-value transactions) without redesigning their session infrastructure.
Server-Side Implementation
Adopting DBSC is more involved than deploying a security header like HSTS. The server needs to maintain a mapping of session IDs to public keys, implement a stateful challenge-response protocol at the refresh endpoint, and switch to short-lived session cookies for the credentials being protected.
A minimal refresh endpoint implementation in pseudocode:
@app.post("/auth/dbsc/refresh")
def dbsc_refresh(request):
session_id = request.headers.get("Sec-Session-Id")
signed_response = request.headers.get("Sec-Session-Response")
# Load the stored public key for this session
public_key = session_store.get_public_key(session_id)
if not public_key:
return 401, "Unknown session"
# Verify the signed challenge
stored_nonce = nonce_store.pop(session_id) # single-use
if not verify_jwt(signed_response, public_key, nonce=stored_nonce):
session_store.invalidate(session_id)
return 401, "Invalid proof"
# Issue a new short-lived session cookie
new_cookie = generate_session_cookie(max_age=3600)
response = Response()
response.set_cookie("session", new_cookie, max_age=3600, secure=True)
return response
The stateful nonce management is important for replay prevention. Stored nonces need to be single-use and have their own expiration window to prevent accumulation attacks.
Public key storage scales like session storage: one row per active session, roughly 100–200 bytes for a P-256 JWK. At Google’s scale that’s substantial; for most applications it’s negligible.
Where It Sits Relative to Passkeys
Passkeys get discussed in the same security conversations, but they solve a different layer of the problem. Passkeys replace passwords at the authentication step, binding the login credential to a device using the same TPM/Secure Enclave infrastructure. They are excellent at preventing phishing-based credential theft.
But passkeys don’t protect what happens after login. Once a server issues a session cookie in exchange for a successful passkey assertion, that cookie is a bearer token again. DBSC extends the hardware-binding guarantee from the authentication step into the session lifetime. The two are complementary: use passkeys to bind the login, use DBSC to bind the session that follows.
Google’s services are in a position to demonstrate this stack end-to-end. A Google Account login with a passkey followed by a DBSC-protected session would require hardware presence at every step, from initial authentication through every sensitive request.
The Ecosystem Problem
The protocol is well-designed. The adoption challenge is significant.
Safari has not committed to DBSC. Apple’s approach to session security runs through their own ecosystem infrastructure, and their track record on features with strong hardware dependencies is to move at their own pace. Without Safari, a large fraction of web traffic, particularly on mobile, remains unprotected by DBSC regardless of server adoption. Attackers will route around it.
Firefox has participated in WICG discussions but has not committed to an implementation timeline. The open question there is partly technical (Firefox’s platform key store integration varies significantly across operating systems) and partly strategic.
TPM availability is another constraint. Windows 11 mandates TPM 2.0, covering most recent hardware, but older Windows 10 machines and most Linux desktops lack the hardware requirement. The DBSC specification allows for a software-only fallback, but that fallback is meaningfully weaker: OS-level encryption rather than hardware-backed key storage, closer in strength to Chrome’s App-Bound Encryption from 2024 than to true device binding.
The privacy angle deserves mention. DBSC keys are per-session, not per-device, which limits cross-site tracking implications. However, within a single origin, the public key creates a persistent device fingerprint that survives cookie clearing. A user who clears their cookies to reset their session will still have their device recognized if the server retains the key association. The WICG discussions included substantial debate about this, and the per-session key design was the resolution, but servers that store keys beyond session lifetime would undermine the privacy property.
A Practical Rollout
For teams thinking about implementation, the path of least disruption is to introduce DBSC alongside existing session infrastructure rather than replacing it. Issue DBSC-protected short-lived cookies in addition to existing longer-lived cookies during a transition, validate that the refresh loop works across your deployment (particularly if you use CDN edge nodes for session termination), and then progressively reduce the lifetime of the primary session cookie.
Key loss scenarios need UX handling. If a user’s TPM is reset, their machine is reimaged, or they switch to a new device, the browser cannot produce a valid proof. The server should detect repeated proof failures and redirect to re-authentication with a clear message, not return opaque 401 errors. The security behavior (logout the unrecognized session) is correct; the user experience needs to make the cause legible.
Enterprise environments with HTTPS inspection proxies need to verify that the refresh endpoint traffic reaches the origin server. Token Binding failed partly because of middlebox incompatibility; DBSC’s header-based design avoids TLS-layer issues, but application-layer proxying that rewrites headers could still interfere with the Sec-Session-* header family.
The Larger Picture
The web security community has been trying to solve device-bound session credentials for over a decade. Token Binding showed that binding to the TLS layer was the wrong approach. Hardware-backed passkeys demonstrated that TPM-level key management at web scale is achievable. DBSC combines those lessons into a design that is transparent to users, backward-compatible with existing session infrastructure, and focused on the attack vector that has been most economically damaging: stolen cookies replayed across devices.
The rollout will be uneven. Safari’s absence will limit the protection for a large portion of users. Server adoption requires active investment, not just a header flag. The software fallback on hardware-less devices provides weaker guarantees. These are real constraints.
None of them change the underlying correctness of the approach. For the specific attack that has drained accounts, broken into companies, and funded the infostealer economy at scale, DBSC is a technically sound answer. Getting it deployed broadly is the remaining work.