From 993e74912199c66c522f08ec81abe31d76985e39 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Wed, 17 Jun 2026 00:05:45 +0200 Subject: [PATCH] refac --- backend/open_webui/models/auths.py | 3 +++ backend/open_webui/utils/auth.py | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/backend/open_webui/models/auths.py b/backend/open_webui/models/auths.py index 5e363352bd..96f6c39703 100644 --- a/backend/open_webui/models/auths.py +++ b/backend/open_webui/models/auths.py @@ -8,6 +8,7 @@ from typing import Optional from open_webui.internal.db import Base, JSONField, get_async_db_context from open_webui.models.users import User, UserModel, UserProfileImageResponse, Users +from open_webui.utils.auth import PLACEHOLDER_HASH from open_webui.utils.validate import validate_profile_image_url from pydantic import BaseModel, field_validator from sqlalchemy import Boolean, Column, String, Text, delete, select, update @@ -142,11 +143,13 @@ class AuthsTable: log.info('authenticate_user: %s', email) resolved = await Users.get_user_by_email(email, db=db) if not resolved: + verify_password(PLACEHOLDER_HASH) return # load the credential row and verify the password hash async with get_async_db_context(db) as session: credential = await session.get(Auth, resolved.id) if not credential or not credential.active: + verify_password(PLACEHOLDER_HASH) return if not verify_password(credential.password): return diff --git a/backend/open_webui/utils/auth.py b/backend/open_webui/utils/auth.py index 26cea6b45f..85e6706d95 100644 --- a/backend/open_webui/utils/auth.py +++ b/backend/open_webui/utils/auth.py @@ -162,6 +162,12 @@ def get_password_hash(password: str) -> str: return bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8') +# Pre-computed hash verified on signin paths that lack a real credential +# (unknown user, inactive account) so response timing cannot reveal +# whether an account exists (CWE-208). +PLACEHOLDER_HASH = get_password_hash('placeholder') + + def validate_password(password: str) -> bool: # The password passed to bcrypt must be 72 bytes or fewer. If it is longer, it will be truncated before hashing. if len(password.encode('utf-8')) > 72: