From b7626f05fb92b24ab923ad81a037071ebd5623d1 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Tue, 16 Jun 2026 22:56:24 +0200 Subject: [PATCH] Authorize KB write access before auto-linking an uploaded file (CWE-862/863) (#26001) process_uploaded_file auto-links an uploaded file to the knowledge base named in client-supplied metadata.knowledge_id, but it called Knowledges.add_file_to_knowledge_by_id directly with no authorization, while the dedicated POST /knowledge/{id}/file/add endpoint gates the same operation on owner / admin / write grant. A read-only collaborator (or any verified user who knows the KB id) could therefore attach arbitrary files to a knowledge base they cannot write: the KnowledgeFile membership row was committed, and the later vector-index write check failed closed but left the row in place. Gate the auto-link on the same owner/admin/write check before inserting the membership row; otherwise skip the link and log. The file still uploads as the user's own file, it just is not linked to a KB they cannot write. Co-authored-by: jagstack <52110932+jagstack@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 (1M context) --- backend/open_webui/routers/files.py | 44 +++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/backend/open_webui/routers/files.py b/backend/open_webui/routers/files.py index dbf1ccb885..f5f8df66dd 100644 --- a/backend/open_webui/routers/files.py +++ b/backend/open_webui/routers/files.py @@ -178,19 +178,39 @@ async def process_uploaded_file( knowledge_id = file_metadata.get('knowledge_id') if knowledge_id: try: - await Knowledges.add_file_to_knowledge_by_id( - knowledge_id=knowledge_id, - file_id=file_item.id, - user_id=user.id, - directory_id=file_metadata.get('directory_id'), + # Gate like POST /knowledge/{id}/file/add: a client-supplied + # metadata.knowledge_id must not let a non-writer attach files (CWE-862/863). + knowledge = await Knowledges.get_knowledge_by_id(id=knowledge_id, db=db_session) + can_write = bool(knowledge) and ( + knowledge.user_id == user.id + or user.role == 'admin' + or await AccessGrants.has_access( + user_id=user.id, + resource_type='knowledge', + resource_id=knowledge.id, + permission='write', + db=db_session, + ) ) - await process_file( - request, - ProcessFileForm(file_id=file_item.id, collection_name=knowledge_id), - user=user, - db=db_session, - ) - log.info(f'Linked file {file_item.id} to knowledge {knowledge_id}') + if not can_write: + log.warning( + f'Refusing to auto-link file {file_item.id} to knowledge ' + f'{knowledge_id}: user {user.id} lacks write access' + ) + else: + await Knowledges.add_file_to_knowledge_by_id( + knowledge_id=knowledge_id, + file_id=file_item.id, + user_id=user.id, + directory_id=file_metadata.get('directory_id'), + ) + await process_file( + request, + ProcessFileForm(file_id=file_item.id, collection_name=knowledge_id), + user=user, + db=db_session, + ) + log.info(f'Linked file {file_item.id} to knowledge {knowledge_id}') except Exception as e: log.warning(f'Failed to link file {file_item.id} to knowledge {knowledge_id}: {e}')