mirror of
https://github.com/open-webui/open-webui.git
synced 2026-09-06 08:18:53 +00:00
fix: fold admin bypass into runtime base-model checks in openai/ollama
Address review feedback: the runtime check_base_model_access calls in routers/openai.py and routers/ollama.py only considered request.state.bypass_filter and BYPASS_MODEL_ACCESS_CONTROL, omitting the admin + BYPASS_ADMIN_ACCESS_CONTROL term that main.py, functions.py, and routers/models.py already threaded in. Because check_base_model_access enforces grants for every role when bypass_filter is False, admins in BYPASS_ADMIN_ACCESS_CONTROL deployments could be blocked from chained bases they did not own or hold a grant on — a regression relative to their behavior on non-chained models. Fold the admin bypass term into the effective filter at every runtime call site: the native ollama and openai chat completion paths, plus the four secondary ollama paths (openai completion, openai chat completion, anthropic messages, responses).
This commit is contained in:
parent
7a0fd37a66
commit
402881b621
2 changed files with 36 additions and 6 deletions
|
|
@ -63,6 +63,7 @@ from open_webui.utils.payload import (
|
|||
)
|
||||
from open_webui.utils.auth import get_admin_user, get_verified_user
|
||||
from open_webui.config import (
|
||||
BYPASS_ADMIN_ACCESS_CONTROL,
|
||||
UPLOAD_DIR,
|
||||
)
|
||||
from open_webui.env import (
|
||||
|
|
@ -1106,7 +1107,13 @@ async def generate_chat_completion(
|
|||
# Re-run the access check against the resolved base model. The check
|
||||
# on the user-facing wrapper does not authorize the chain target:
|
||||
# grants or ownership on the wrapper must not leak into the base.
|
||||
await check_base_model_access(user, base_model_id, bypass_filter)
|
||||
# Fold admin bypass in so admins behave consistently with the other
|
||||
# new call sites (main.py, functions.py, models.py).
|
||||
await check_base_model_access(
|
||||
user,
|
||||
base_model_id,
|
||||
bypass_filter or (user.role == 'admin' and BYPASS_ADMIN_ACCESS_CONTROL),
|
||||
)
|
||||
|
||||
params = model_info.params.model_dump()
|
||||
|
||||
|
|
@ -1198,7 +1205,11 @@ async def generate_openai_completion(
|
|||
|
||||
model_id = form_data.model
|
||||
model_info = await Models.get_model_by_id(model_id)
|
||||
base_bypass_filter = getattr(request.state, 'bypass_filter', False) or BYPASS_MODEL_ACCESS_CONTROL
|
||||
base_bypass_filter = (
|
||||
getattr(request.state, 'bypass_filter', False)
|
||||
or BYPASS_MODEL_ACCESS_CONTROL
|
||||
or (user.role == 'admin' and BYPASS_ADMIN_ACCESS_CONTROL)
|
||||
)
|
||||
if model_info:
|
||||
if model_info.base_model_id:
|
||||
payload['model'] = model_info.base_model_id
|
||||
|
|
@ -1262,7 +1273,11 @@ async def generate_openai_chat_completion(
|
|||
|
||||
model_id = completion_form.model
|
||||
model_info = await Models.get_model_by_id(model_id)
|
||||
base_bypass_filter = getattr(request.state, 'bypass_filter', False) or BYPASS_MODEL_ACCESS_CONTROL
|
||||
base_bypass_filter = (
|
||||
getattr(request.state, 'bypass_filter', False)
|
||||
or BYPASS_MODEL_ACCESS_CONTROL
|
||||
or (user.role == 'admin' and BYPASS_ADMIN_ACCESS_CONTROL)
|
||||
)
|
||||
if model_info:
|
||||
if model_info.base_model_id:
|
||||
payload['model'] = model_info.base_model_id
|
||||
|
|
@ -1324,7 +1339,11 @@ async def generate_anthropic_messages(
|
|||
model_id = payload.get('model', '')
|
||||
|
||||
model_info = await Models.get_model_by_id(model_id)
|
||||
base_bypass_filter = getattr(request.state, 'bypass_filter', False) or BYPASS_MODEL_ACCESS_CONTROL
|
||||
base_bypass_filter = (
|
||||
getattr(request.state, 'bypass_filter', False)
|
||||
or BYPASS_MODEL_ACCESS_CONTROL
|
||||
or (user.role == 'admin' and BYPASS_ADMIN_ACCESS_CONTROL)
|
||||
)
|
||||
if model_info:
|
||||
if model_info.base_model_id:
|
||||
payload['model'] = model_info.base_model_id
|
||||
|
|
@ -1384,7 +1403,11 @@ async def generate_responses(
|
|||
model_id = form_data.model
|
||||
|
||||
model_info = await Models.get_model_by_id(model_id)
|
||||
base_bypass_filter = getattr(request.state, 'bypass_filter', False) or BYPASS_MODEL_ACCESS_CONTROL
|
||||
base_bypass_filter = (
|
||||
getattr(request.state, 'bypass_filter', False)
|
||||
or BYPASS_MODEL_ACCESS_CONTROL
|
||||
or (user.role == 'admin' and BYPASS_ADMIN_ACCESS_CONTROL)
|
||||
)
|
||||
if model_info:
|
||||
if model_info.base_model_id:
|
||||
payload['model'] = model_info.base_model_id
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ from open_webui.utils.access_control import (
|
|||
check_base_model_access,
|
||||
)
|
||||
from open_webui.config import (
|
||||
BYPASS_ADMIN_ACCESS_CONTROL,
|
||||
CACHE_DIR,
|
||||
)
|
||||
from open_webui.env import (
|
||||
|
|
@ -1065,7 +1066,13 @@ async def generate_chat_completion(
|
|||
# Re-run the access check against the resolved base model. The check
|
||||
# on the user-facing wrapper does not authorize the chain target:
|
||||
# grants or ownership on the wrapper must not leak into the base.
|
||||
await check_base_model_access(user, base_model_id, bypass_filter)
|
||||
# Fold admin bypass into the filter so admins mirror the behaviour
|
||||
# of the other new call sites (main.py, functions.py, models.py).
|
||||
await check_base_model_access(
|
||||
user,
|
||||
base_model_id,
|
||||
bypass_filter or (user.role == 'admin' and BYPASS_ADMIN_ACCESS_CONTROL),
|
||||
)
|
||||
|
||||
params = model_info.params.model_dump()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue