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) <noreply@anthropic.com>
This commit is contained in:
authored and GitHub committed 2026-06-16 22:56:24 +02:00
1 parent 1fc0e3ade7
commit b7626f05fb
1 file changed
+32 -12
+32 -12
View File
@@ -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}')