# Open WebUI: LDAP and OAuth First-User Race Condition Allows Multiple Admin Accounts

LDAP/OAuth first-user admin assignment in Open WebUI used a TOCTOU check, letting concurrent first logins all become admins.

- Payout: Research
- Severity: high
- Program: Open WebUI
- Found by: sfwani
- Disclosed: 2026-05-14
- CVE: CVE-2026-45675
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-h3ww-q6xx-w7x3
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-h3ww-q6xx-w7x3
- Tags: area:web domain:web impact:ato impact:privesc kind:research platform:ghsa sev:high tech:oauth technique:incomplete-fix technique:race-window vuln:auth-bypass vuln:privilege-escalation vuln:race-condition

**Target:** LDAP and OAuth authentication handlers (auths.py, oauth.py)
**Root cause:** Role is determined by a has_users()/get_num_users()==0 check before the user insert, so concurrent first-login requests all observe an empty table and all get 'admin'. The signup_handler was patched to insert-then-check but LDAP/OAuth paths were not.
**Steps:**
1. Deploy Open WebUI with LDAP or OAuth enabled on a fresh instance with no users
2. Send multiple concurrent authentication requests from different users
3. All requests pass `Users.has_users(db=db)` / `get_num_users() == 0` simultaneously
4. Each inserts a user with `role='admin'` via `Auths.insert_new_auth`
**How found:** Noticed the signup_handler carried an explicit 'Insert with default role first to avoid TOCTOU race' fix, then checked whether the parallel LDAP and OAuth registration paths received the same fix — they had not.
**Exploitation:** An LDAP/OAuth user times their first login concurrently with the legitimate first admin; both requests see an empty user table and both are created with the admin role, giving the attacker full admin privileges.
**Escalation:** Admin role yields access to all user data, system configuration, API keys, and connected LLM backends.
**Insight:** When a TOCTOU fix lands in one registration path, grep every other path that assigns first-user/owner roles (SSO, LDAP, OAuth, invite) for the same pre-insert count check; incomplete fixes are the norm.

