# Authlib RFC 7592 examples omit registration-access-token client binding

Authlib's RFC 7592 docstring examples never bind registration_access_token to the target client, letting any self-registered client read, modify, or delete other clients' registrations.

- Payout: Research
- Severity: high
- Program: Authlib
- Found by: alham-rizvi
- Disclosed: 2026-10-30
- CVE: CVE-2026-116672
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-c73q-w75p-j82v
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-c73q-w75p-j82v
- Tags: area:web domain:api domain:web impact:dos impact:integrity kind:research platform:ghsa sev:high tech:oauth technique:source-review vuln:access-control vuln:auth-bypass vuln:idor

**Target:** OAuth 2.0 dynamic client registration management endpoint (/register/{client_id})
**Root cause:** Documented example implementations of authenticate_client and check_permission look up the target client by payload client_id and check only client.editable, never comparing request.credential.client_id to the target client, so any valid registration_access_token authorizes access to any client.
**Steps:**
1. Deploy an AS using ClientConfigurationEndpoint with authenticate_client and check_permission implemented exactly as in the docstrings.
2. Register a throwaway client via the (commonly open) RFC 7591 endpoint, obtaining `client_id_A` and `registration_access_token_A`.
3. Identify or guess `client_id_B` of an unrelated client.
4. Send `GET /register/client_id_B` (or PUT/DELETE) with `Authorization: Bearer registration_access_token_A`; for PUT set `client_id` to `client_id_B` in the body.
5. authenticate_token passes (token valid), authenticate_client passes (looks up client_id_B from payload), check_permission passes (only checks client_B.editable) — client B's registration is returned, modified, or deleted.
**How found:** Code-reading of the RFC 7592 endpoint: noticed request.credential is set after authenticate_token specifically for downstream binding checks, but neither documented example reads it; contrasted with the RFC 7662 introspection example where checking a property of `client` is meaningful because it is the authenticated caller, whereas here `client` is the target.
**Exploitation:** Attacker self-registers a client on an open dynamic registration deployment to obtain a valid registration_access_token, then replays it against /register/{victim_client_id} for arbitrary targets. Read leaks client metadata; PUT can rewrite redirect_uris to an attacker endpoint enabling authorization code/token interception; DELETE removes arbitrary client registrations.
**Escalation:** Redirect URI hijack of victim client enables authorization code or token interception against that client's users; mass deletion of registrations yields DoS.
**Insight:** When a framework sets an authenticated credential on the request for later steps, grep every documented example for reads of that attribute — if the sample implementations never consume it, the samples teach an IDOR. Also compare sibling endpoint examples: a pattern that is correct where `client` means caller becomes a bypass where `client` means target.

