This is not an unsafe-admin-action report: the same intended model access restriction is enforced on the direct model path and on the normal-chat selected-model control, then bypassed only through the task endpoint call order.
PoV
The attached local PoV does not start a server and does not contact any model provider. It imports the current Open WebUI task endpoint and replaces provider dispatch plus model-access checks with local stubs so the call graph can be observed safely.
Observed result:
Case
Expected
Actual
Direct task request with model=restricted-model
Denied before provider dispatch
Denied; no provider call recorded
Normal-chat post-preprocessor control with model=restricted-model and metadata.selected_model_id=restricted-model
Denied before provider dispatch
Denied; no provider call recorded
Task request with model=public-arena that selects restricted-model
Denied when selected model is restricted
Local provider stub reached with model=restricted-model and bypass_filter=true
In the arena task case, the restricted model is absent from the access-check log.
Impact
A regular user can use a readable arena wrapper as an oracle for a restricted model via task-generation endpoints. For /api/v1/tasks/moa/completions, the caller controls the task prompt and receives the generated response.
The crossed security boundary is model read authorization: a non-admin user who is denied direct access to a model can still cause Open WebUI to dispatch a request to that model with the operator-configured backend credentials.
This can allow:
use of paid or internal models with the admin-configured provider key;
bypass of model access grants shown in the model selector;
cost and usage impact on pay-per-token providers;
exposure of model behavior or internal deployment capabilities that admins intended to restrict.
Authentication is required, so PR:L is used. User interaction is not required. The confidentiality impact is High because the attacker can query a model the administrator intended to restrict. Integrity and availability are Low because the request can consume provider quota and produce model output under an authorization decision the system would otherwise deny.
This should not be Critical: exploitation requires an authenticated user and a readable arena wrapper, does not cross into another security authority, and does not provide arbitrary code execution or full instance compromise.
Suggested Fix
Do not use bypass_filter=True for arena fallback dispatch unless the selected underlying model has already been authorized for the caller.
Recommended changes:
after selecting selected_model_id, load the selected model and call check_model_access(user, selected_model) before recursive dispatch;
for filter_mode=exclude or empty model_ids, build the candidate pool from models the current user can read, not every non-arena model in request.app.state.MODELS;
add regression tests for /api/v1/tasks/moa/completions, /api/v1/tasks/title/completions, /api/v1/tasks/tags/completions, and normal /api/chat/completions arena behavior.
Appendix: Affected Components
backend/open_webui/routers/tasks.py
/api/v1/tasks/moa/completions builds a payload from caller-controlled model, prompt, and responses, then calls generate_chat_completion(request, form_data=payload, user=user).
backend/open_webui/utils/chat.py
checks access for the user-supplied arena wrapper model.
fallback arena resolution selects an underlying model when the caller did not pass through process_chat_payload().
recursive dispatch uses bypass_filter=True.
backend/open_webui/utils/models.py
arena wrapper access checks only wrapper access_grants.
Current-head references:
backend/open_webui/routers/tasks.py:662-707
backend/open_webui/utils/chat.py:190-204
backend/open_webui/utils/chat.py:215-240
backend/open_webui/utils/chat.py:248-269
backend/open_webui/utils/middleware.py:2323-2347
backend/open_webui/utils/models.py:378-407
Appendix: Duplicate Analysis
This is distinct from GHSA-9vvh-qmjx-p4q8 / CVE-2026-44555, which covers base_model_id chaining and user-created workspace models. Current head includes the base-model-chain access fix through has_base_model_access.
This report covers task endpoints that call generate_chat_completion() without the main chat preprocessor. The root cause is arena fallback plus recursive bypass_filter=True, not base_model_id.
Live duplicate sweep before submission also reviewed:
GHSA-v6qf-75pr-p96m: exposed HTTP query parameter ?bypass_filter=true. This report does not rely on caller-controlled query parameters; the task endpoint reaches the server-side recursive bypass_filter=True path after arena fallback resolution.
GHSA-hp5m-24vp-vq2q: /api/openai/responses passthrough missing model authorization. This report targets /api/v1/tasks/moa/completions and the arena resolver inside utils.chat.generate_chat_completion().
GHSA-gfm2-xm6c-37qc: chat ownership authorization in completions. This report does not require another user's chat ID.
If maintainers prefer to treat this as the same broad "wrapper checked, underlying model not checked" class, it should still be a distinct exploitation vector and affected component: task endpoints, not model creation/import or base_model_id dispatch.
Appendix: Preconditions
Authenticated non-admin user.
The user can read an arena wrapper model, for example a custom arena with a public read grant.
The arena model includes at least one restricted underlying model that the user cannot query directly.