diff --git a/backend/open_webui/models/messages.py b/backend/open_webui/models/messages.py index 304276b3d9..0b6c4e080b 100644 --- a/backend/open_webui/models/messages.py +++ b/backend/open_webui/models/messages.py @@ -328,7 +328,8 @@ class MessageTable: async with get_async_db_context(db) as db: message = await db.get(Message, parent_id) - if not message: + # Thread parent must belong to the requested channel; never disclose a foreign-channel message. + if not message or message.channel_id != channel_id: return [] result = await db.execute( diff --git a/backend/open_webui/routers/channels.py b/backend/open_webui/routers/channels.py index 7a509b6b09..f3f6fd2885 100644 --- a/backend/open_webui/routers/channels.py +++ b/backend/open_webui/routers/channels.py @@ -1129,6 +1129,13 @@ async def new_message_handler(request: Request, id: str, form_data: MessageForm, ): raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.DEFAULT()) + # Thread parent / reply target must belong to this channel (no cross-channel binding). + for ref_id in (form_data.parent_id, form_data.reply_to_id): + if ref_id: + ref = await Messages.get_message_by_id(ref_id, include_thread_replies=False, db=db) + if not ref or ref.channel_id != channel.id: + raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=ERROR_MESSAGES.DEFAULT()) + try: message = await Messages.insert_new_message(form_data, channel.id, user.id, db=db) if message: