A key the browser can't hand over
Click Start session above. A supporting browser silently generates an ECDSA keypair, keeps the private half somewhere it can't export it from, and hands this server the public half. From then on, the browser has to re-sign a fresh server-issued challenge every few minutes to keep its session cookie alive — the card above is live, and the history log fills in as it happens.
Stolen cookies are how most accounts actually get taken over
Phishing kits and infostealer malware (Lumma, RedLine and the like are built almost entirely around this) don't bother stealing passwords anymore — they exfiltrate the browser's cookie jar. On a normal site that's enough: a session cookie is a bearer token, good for as long as it's valid, and that's typically hours to weeks. Steal one and you own the session, in full, until it happens to expire on its own.
DBSC doesn't stop the cookie from being stolen. It stops the theft from lasting: the cookie can only be renewed by signing a challenge with a private key a secure enclave or TPM never exposes, so a copied cookie has a shelf life instead of a free run. This demo sets that shelf life to 180 seconds so you can watch it run out instead of taking it on faith — a real deployment would use something much longer, minutes to hours, not a demo-friendly few minutes.
Proof of possession, not proof of every request
DBSC proves key possession at refresh time, not on every request in between. A cookie copied mid-lifetime is still valid until it expires — the private key was never needed to use it, only to renew it. That's why this demo also records the TLS fingerprint (JA4) of the connection that registered each session and compares it against every refresh. A mismatch doesn't prove theft on its own — plenty of devices share a JA4 — but it's a cheap, edge-computed signal worth feeding into bot or session-risk scoring rather than trusting the cookie alone.
Steal your own cookie
Start a session above, then do exactly what an infostealer does: open devtools → Application → Cookies → this site, and copy the value of dbsc_session. Nothing on this page hands it to you — it's HttpOnly, same as it would be on a real login — you have to go get it the way malware would.
Paste it into this, right now, alongside the dbsc_sid value the JSON returned when you started the session, and it works — it's still the current cookie:
curl -s https://dbsc.alpagot.net/protected --cookie "dbsc_sid=<from Start session>; dbsc_session=<paste from devtools>"
One practical gotcha: Chrome revalidates on its own schedule, and in practice that's noticeably faster than the 180s figure below — often under a minute, running quietly in the background whether or not the tab is doing anything. If you take even a short pause between copying the cookie from devtools and running the command, don't be surprised if it's already stale: you're not testing "before rotation" any more, you're testing "after" without meaning to. Copy and run it in the same breath, right after a fresh registered or refreshed line appears in the log above, to reliably catch it while it's still valid.
Now wait — up to 180 seconds, until the history log above shows another refreshed entry — and run the exact same command again, unchanged. It fails: the browser already rotated to a new cookie value behind the scenes, and the copy you're holding doesn't get to renew itself. That's the entire benefit, in one loop.
Run it from a terminal rather than a second browser tab and you get a tell for free: curl's TLS stack has a different JA4 than your browser's, so even the successful call before rotation comes back flagged as a JA4 mismatch — see the gap it doesn't close, above.
Compute, but not for the reason you'd guess
Unlike its VCL siblings, this one needed real compute — but not because VCL can't verify a signature. digest.ecdsa_verify() has a jwt digest format built for exactly this, and a P-256 key's fixed ASN.1 prefix makes turning a JWK's raw x/y into the PEM it wants a mechanical BLOB operation, not a JSON parser. The real blocker is state: registration and every refresh need to write — a newly bound key, a just-issued challenge — and have the very next request read that write back within seconds, quite possibly from a different POP. Edge dictionaries and config stores are populated through the control-plane API, not from inside vcl_recv, and even routed around that, updates take on the order of tens of seconds to reach every POP — too slow for a challenge POP A issued to verify on POP B moments later. A KV Store's real-time, globally-consistent read-after-write is the part with no VCL equivalent, and it's Compute-only.
Three honest caveats. Browser support is still rolling out — Chrome on Windows shipped it, macOS is expected later, Firefox's position is undecided — so if the card above never goes green, that's very possibly your browser, not this server. This is a demo for one tab, not a production identity system: no cross-device transfer, no enterprise policy, session termination is the bare minimum (Clear-Site-Data on logout). And this was built in September 2026 against the current draft — header names, the credential-attribute rules, and the refresh cadence are all things the spec could still change before it ships as a Recommendation.
Richard Alpagot
Senior Cloud Engineer at Fastly.
- websitewww.alpagot.net
- blogblog.alpagot.net
- linkedin/in/alpagot