Back to Feed
article 3m read

A login gate that admits anyone who writes their own cookie went live

The new front end kept its session as plain JSON in a cookie and the gate only checked the expiry, so the one way past it was a hand-written cookie; the waitlist route trusted its request body the same way.

Article DepthPractice

Flow

My plan for the login cookie and the waitlist

  1. 1Fake-cookie test

    Write a cookie by hand and expect the dashboard to bounce it.

  2. 2Signed ID

    The cookie holds an account ID and end time, signed with a server key.

  3. 3Load from the database

    Pages with private data read roles and locks fresh.

  4. 4Named fields

    The waitlist saves only listed fields and writes its own time last.

  5. 5Missing secrets

    No signing key or bot secret in production stops the app.

The sign-in form on my new site doesn't sign anyone in. It sends you to the dashboard, and the gate in front of the dashboard sends you right back. Sign-up does the same.

I pushed the whole app at once, and going by its comments, an agent wrote most of it. The fake form is fine for now. The part under it is not, because it looks done. Nothing in the app ever hands out a login cookie, so the only way past the gate is to write the cookie yourself. And the gate lets you in.

The cookie is a note you can edit

The login cookie is plain text: who you are and when the login ends. The gate reads it and checks one thing, that the end time hasn't passed. A helper meant to tell pages who you are reads it the same way.

if (note && note.until > clock()) letThemIn(note.who);

No secret is involved, so anyone can write a note that passes. The cookie's safety flags keep it from leaking. They don't stop you from typing your own.

What a fake note could reach

The note has a role in it, and the top roles can act as other users. Today no page reads that role, and the dashboard is fake data. But the first page that does will trust whatever the visitor wrote. There's a real user database with roles and a lock flag, and none of it is wired to the cookie. A locked account stays logged in until the cookie runs out.

The waitlist trusts the form

The waitlist saves the email and a server time, then copies the whole request over it. The visitor's fields win, so they can set their own time and add anything. The bot check only runs if its secret is set. Leave it out, and everyone gets through.

A signed ID and real checks

None of this is fixed yet, and there are no tests. My plan has a few parts. The cookie holds just an account ID and an end time, signed with a server key and checked before it's read. Pages with private data load the account from the database, so roles and locks are current. The waitlist saves only named fields and writes its own time last. A missing key or bot secret stops the app in production.

The first test writes a fake cookie by hand and expects to be bounced from the dashboard. Until that test passes, the sign-in form can stay fake.

Keep reading

Pick up a connected idea or branch into a nearby one.

5 paths forward