From 934802e1868f7dbd57d148cd9bc003498490e464 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Tue, 11 Aug 2026 07:36:27 +0200 Subject: [PATCH] fix: enforce features.memories permission on the legacy memory context path (#27668) Revoking a user's `features.memories` permission removed their access to the memories API and to the native function-calling memory tools, but their stored memories were still injected into the system context on the legacy function-calling path. The branch in `process_chat_payload` only checked the client-supplied `features['memory']` flag plus the global `memories.system_context.enable` switch, with no user-permission check. `add_memory_context` did not compensate: it only checks `model_allows_memory`, which is a model capability rather than a permission, and the one call inside it that does check the permission (`query_memory`) has its 403 swallowed by a `try/except`, so `Memories.get_memories_by_user_id` and the neighbourhood scan still fed the system prompt. Gate the branch with the same permission check the native path already performs in `get_builtin_tools`, matching the neighbouring `web_search` and `image_generation` branches. Only the caller's own memories were injected into the caller's own context, so there was no cross-user exposure. The practical effect was that the permission toggle did not do what its name implies: an admin who revoked it still got memory content injected for that user. --- backend/open_webui/utils/middleware.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 1c6f1fc510..5a10db3386 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -2538,7 +2538,13 @@ async def process_chat_payload(request, form_data, user, metadata, model): ) if 'memory' in features and features['memory'] and await Config.get('memories.system_context.enable'): - form_data = await add_memory_context(request, form_data, user, model) + # features is client-supplied; re-check the permission the native FC path enforces. + if getattr(user, 'role', None) == 'admin' or await has_permission( + getattr(user, 'id', ''), + 'features.memories', + await Config.get('user.permissions'), + ): + form_data = await add_memory_context(request, form_data, user, model) if 'web_search' in features and features['web_search']: # features is client-supplied; re-check the permission the native FC path enforces.