mirror of
https://github.com/open-webui/open-webui.git
synced 2026-07-16 06:03:26 -05:00
[PR #24693] [MERGED] fix: enforce features.direct_tool_servers on chat-completion tool_servers #131452
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/24693
Author: @Classic298
Created: 5/13/2026
Status: ✅ Merged
Merged: 5/14/2026
Merged by: @tjbck
Base:
dev← Head:fix/direct-tool-servers-permission-on-chat-completions📝 Commits (2)
de788b5fix: enforce features.direct_tool_servers on chat-completion tool_servers11aed43chore: trim verbose comment on tool_servers permission check📊 Changes
1 file changed (+17 additions, -2 deletions)
View changed files
📝
backend/open_webui/main.py(+17 -2)📄 Description
The features.direct_tool_servers per-user permission was correctly enforced on the storage path (routers/users.py user/settings/update, which strips toolServers from saved settings when the caller lacks the permission), but the inference path (/api/chat/completions) popped tool_servers straight from the request body into metadata with no permission check. The middleware (utils/middleware.py:2799) then consumed direct_tool_servers to inject system_prompt into the message array and register external tool specs that get invoked during the completion. End result: any authenticated user could bypass the admin-set per-user feature toggle and use inline tool_servers in their chat-completion requests, even when admin had explicitly denied the permission.
Default for USER_PERMISSIONS_FEATURES_DIRECT_TOOL_SERVERS is False (config.py:2750), so under default config no regular user is supposed to be able to use direct tool servers — making this a real boundary bypass on out-of-the-box deployments rather than a corner case.
Mirror the storage-side behaviour at the inference entry point: pop tool_servers from the request body, then silently drop the value if the caller is non-admin and lacks features.direct_tool_servers. Admins always pass; users with the explicit grant always pass; everyone else gets None propagated into metadata, which the middleware already handles as the no-tool-servers case.
Contributor License Agreement
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.