- 3holes the review found; the worst, anonymous registration with attacker-chosen redirects
- 7acceptance probes, one or more for each fix
- 24 hfrom adding the registration lock to reverting it
A security review of my deliberately public OAuth endpoint found holes, the worst of them in client registration. I fixed all three, checked the fixes with explicit probes, and the next morning every AI assistant that used the endpoint could no longer authenticate. I re-ran the threat model. The registration lock had added friction without adding security, because the control that protects is the consent screen, where I log in and approve every grant. I reverted my own fix and wrote down why.
The challenge
The endpoint exists so that AI assistants, including commercial ones, can connect to my private tool estate. It has to be public, and the assistants self-register as OAuth clients, some of them caching their client identity indefinitely. I cannot hand a secret to every agent that might connect. The review was right that anonymous registration with free-form redirects is a textbook hole. The question was what closing it bought.
Constraints
Public by design. Self-registering clients that remember their identity, so a lock that invalidates registrations breaks every existing client at once. One operator who cannot be a per-agent secret-distribution service.
My approach
Severity-ordered triage, minimal fixes, explicit probes for each. Then, when the lock broke everything, the discipline to ask the question again from the top: what does an attacker gain from a hostile registration? Nothing, unless a human logs in and approves that client on the consent screen.
It holds a client identity and nothing else.
No approval, no access.
The consent screen is the control. Registration is bookkeeping.
What I built
Admin-gated registration with fail-closed behaviour, plus two smaller fixes for the other findings.
Acceptance probes that checked each fix did what it claimed.
A one-line, reversible bypass of the registration gate, with the rationale written beside it, and the pending-client lifetime raised so legitimate clients stop expiring between uses.
Difficult decisions
Reverting my own fix. It is uncomfortable to undo a security change the day after making it. It is worse to leave a system nobody can use while believing it is safer.
Choosing consent over registration as the control point. The lock looked like security. The consent step is security.
Not rushing a richer design. The right answer is more nuanced than either the lock or the bypass, and I did not force one in under pressure.
Results
Every client can authenticate again.
Technologies used
OAuth 2.0 · Dynamic client registration · PKCE · Python service · Redis · NGINX front with TLS and rate limits · Threat modelling
What this demonstrates
Security judgment under real use: knowing which control protects, and reversing on evidence rather than defending a change because it was mine.