max / makenotwork
| 1 | -- Per-app opt-in for the RFC 8252 loopback redirect wildcard. |
| 2 | -- |
| 3 | -- Background: OAuth `redirect_uri` validation accepts ANY http://127.0.0.1:PORT/, |
| 4 | -- [::1]:PORT/, or localhost:PORT/ regardless of an app's registered |
| 5 | -- redirect_uris list. That's correct for native (desktop/mobile) apps that |
| 6 | -- can't reserve known ports, but it widens the attack surface for any |
| 7 | -- web-only app — a phishing URL pointing /oauth/authorize at the attacker's |
| 8 | -- loopback can hijack the auth flow even with PKCE in play (attacker |
| 9 | -- initiates and supplies their own code_verifier). |
| 10 | -- |
| 11 | -- This column gates the wildcard per app: |
| 12 | -- - existing rows default `true` to preserve SyncKit (today's only OAuth |
| 13 | -- consumer, all native). |
| 14 | -- - new rows registered via the developer UI default `false`; the app |
| 15 | -- creator must explicitly opt in by checking "This is a desktop or |
| 16 | -- mobile app." |
| 17 | -- |
| 18 | -- See `routes/oauth.rs::is_localhost_redirect` and the Run #2 audit entry. |
| 19 | |
| 20 | sync_apps ADD COLUMN allow_loopback BOOLEAN NOT NULL DEFAULT true; |
| 21 | |
| 22 | -- Future-proof: change the column-level default to `false` so newly |
| 23 | -- INSERTed rows that don't explicitly set it land safe. |
| 24 | sync_apps ALTER COLUMN allow_loopback SET DEFAULT false; |
| 25 |