mirror of
https://github.com/open-webui/open-webui.git
synced 2026-05-07 11:28:35 -05:00
[PR #21630] [CLOSED] fix: race condition in signup allows multiple admin accounts #41800
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/open-webui/open-webui/pull/21630
Author: @theeggorchicken
Created: 2/20/2026
Status: ❌ Closed
Base:
main← Head:fix/signup-race-condition📝 Commits (1)
9f837b0fix: race condition in signup allows multiple admin accounts📊 Changes
1 file changed (+11 additions, -7 deletions)
View changed files
📝
backend/open_webui/routers/auths.py(+11 -7)📄 Description
Security Fix: TOCTOU Race in Signup Allows Multiple Admin Registrations
Vulnerable Lines
File:
backend/open_webui/routers/auths.py#L703-L709What could happen
On a fresh Open WebUI deployment with multiple uvicorn workers, an attacker can send concurrent signup requests during first-user registration. Each worker's
has_users()check returns False before any insert completes, so multiple accounts receive the admin role. I tested this with 4 workers and 30 concurrent requests — 4 accounts got admin. Each had full admin privileges: listing users, reading config, managing the instance.How to verify
UVICORN_WORKERS=4andENABLE_SIGNUP=true/api/v1/auths/signupwith different email addresses"role": "admin"— without this fix, multiple willFull HTTP traces and race condition results: evidence gist
What this PR does
Eliminates the TOCTOU (time-of-check-to-time-of-use) race window in
signup_handlerby reversing the order of operations:has_users()→ decide role → hash password (~100ms) → insert with pre-decided roleget_num_users()after insert → promote to admin only if user count is exactly 1The key insight is that
get_num_users()after the insert is a point-in-time read that includes the just-inserted row. If two concurrent requests both insert, both will see count >= 2, so neither gets promoted. Only the truly first user (count == 1) becomes admin.The fix also moves the
ENABLE_SIGNUP = Falseguard into the same conditional block, so signup is disabled atomically with the admin promotion.Evidence
https://gist.github.com/theeggorchicken/455f6c46ea73bd96396400a679c3c207
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.