From f89b501985f6f34a6abcf3cb6a4adde0806dd61f Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Fri, 24 Jul 2026 08:18:43 +0200 Subject: [PATCH] fix: access-check note entries in get_accessible_folder_files (#26739) get_accessible_folder_files is the server-side filter that reduces a folder's attached-knowledge list (and, once #26723 lands, a direct model's) to the entries the caller may read, before that list is handed to the builtin knowledge tools as `__model_knowledge__`. It validated `file` and `collection` entries but passed `note` entries through unchecked (they fell into the `else` keep-as-is branch), even though notes are a first-class attached-knowledge type that flows through this list. No current caller is exploitable, because every note consumer (`query_knowledge_files`, `view_note`, and the legacy retrieval path) independently re-checks note access before returning content. But relying on each consumer to remember that check is exactly the fragility this helper exists to remove, and the same `_has_read_access_to_file` membership short-circuit that makes an unvalidated `file` entry dangerous would turn any future note path that trusts list membership into an IDOR. Validate notes here so the filter enforces its own contract instead of leaning on downstream re-checks. A note entry is now kept only when the caller owns it or holds a read grant. Notes are private by default and carry no self-grant, so ownership is checked explicitly alongside the grant lookup. Admins still bypass all checks and genuinely unknown types are still kept as-is. Related: #26723 --- .../open_webui/utils/access_control/files.py | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/backend/open_webui/utils/access_control/files.py b/backend/open_webui/utils/access_control/files.py index 4d6880cdfa..f015e71c70 100644 --- a/backend/open_webui/utils/access_control/files.py +++ b/backend/open_webui/utils/access_control/files.py @@ -122,8 +122,9 @@ async def get_accessible_folder_files( ) -> list[dict]: """Filter folder.data['files'] entries to those the caller can read. - Each entry is expected to have 'type' ('file' or 'collection') and 'id'. - Admins bypass all checks. Unknown types are kept as-is. + Entries carry a 'type' ('file', 'collection' or 'note') and 'id'. File, collection and + note ids are each access-checked against the caller; admins bypass all checks and + genuinely unknown types are kept as-is. """ if not entries: return [] @@ -148,6 +149,22 @@ async def get_accessible_folder_files( elif entry_type == 'collection': if await Knowledges.check_access_by_user_id(entry_id, user.id, 'read', db=db): accessible.append(entry) + elif entry_type == 'note': + # Owner has no self-grant (notes are private by default), so check ownership too. + from open_webui.models.notes import Notes + + note = await Notes.get_note_by_id(entry_id, db=db) + if note and ( + note.user_id == user.id + or await AccessGrants.has_access( + user_id=user.id, + resource_type='note', + resource_id=entry_id, + permission='read', + db=db, + ) + ): + accessible.append(entry) else: accessible.append(entry) return accessible