fix: gate chat-file links by caller access + repair insert_chat_files db arg (#25054)

insert_chat_files() stored any caller-supplied file_id with no ownership
check, so a user could attach another user's file to their own chat and
then read it through the shared-chat access path in has_access_to_file().
Filter file_ids to those the caller owns, is admin for, or can read.

Also repairs an UnboundLocalError introduced in 260ead64d: the existing
duplicate-check referenced `session` before it was assigned (db=session),
so the function threw on every call and no chat_file rows were persisted.
This commit is contained in:
Classic298
2026-05-28 17:42:17 -05:00
committed by GitHub
parent f5f4b58958
commit 3f1c52e018
+22 -1
View File
@@ -1624,13 +1624,34 @@ class ChatTable:
return None
chat_message_file_ids = {
item.id for item in await self.get_chat_files_by_chat_id_and_message_id(chat_id, message_id, db=session)
item.id for item in await self.get_chat_files_by_chat_id_and_message_id(chat_id, message_id, db=db)
}
# Remove duplicates and existing file_ids
file_ids = list({file_id for file_id in file_ids if file_id and file_id not in chat_message_file_ids})
if not file_ids:
return None
# Only link files the caller can read; blocks forging a chat_file row to another user's file.
from open_webui.models.files import Files
from open_webui.models.users import Users
from open_webui.utils.access_control.files import has_access_to_file
user = await Users.get_user_by_id(user_id, db=db)
accessible_file_ids = []
for file_id in file_ids:
file = await Files.get_file_by_id(file_id, db=db)
if not file:
continue
if (
file.user_id == user_id
or (user and user.role == 'admin')
or (user and await has_access_to_file(file_id, 'read', user, db=db))
):
accessible_file_ids.append(file_id)
file_ids = accessible_file_ids
if not file_ids:
return None
try:
async with get_async_db_context(db) as session:
now = int(time.time())