unauthenticated cross-user file/document disclosure (/get_file_base64, /get_doc)
是否已有关于该错误的issue或讨论? | Is there an existing issue / discussion for this?
- 我已经搜索过已有的issues和讨论 | I have searched the existing issues / discussions
该问题是否在FAQ中有解答? | Is there an existing answer for this in FAQ?
- 我已经搜索过FAQ | I have searched FAQ
当前行为 | Current Behavior
reported via email on 9 June 2026 - no response:
I found a security issue in QAnything (confirmed on current main, commit 65de1042) and reproduced it against a running stack (MySQL + Milvus + Elasticsearch).
Summary
Two unauthenticated POST endpoints return full content by server-assigned ID with no ownership check:
- /api/local_doc_qa/get_file_base64 returns the base64 of any uploaded file given file_id.
- /api/local_doc_qa/get_doc returns any parsed document chunk given doc_id.
Neither requires authentication (routes have no auth middleware; handlers carry only @get_time_async), and the backing SQL has no user_id predicate (SELECT file_location FROM File WHERE file_id=%s; SELECT json_data FROM Documents WHERE doc_id=%s). The wider API treats user_id as a self-asserted string (list_files takes a caller-supplied user_id, user_info defaults to "1234"), so it is not a real boundary. The unauthenticated get_user_id (kb_id -> user_id) and list_files endpoints supply the IDs needed.
Where
qanything_kernel/qanything_server/handler.py:1452 (get_file_base64), :1192 (get_doc) qanything_kernel/connector/database/mysql/mysql_client.py:880 (get_file_location), :620 (get_document_by_doc_id) qanything_kernel/qanything_server/sanic_api.py (routes registered, no auth)
Proof of concept (no Authorization header, non-owner)
POST /api/local_doc_qa/get_file_base64 {"file_id":"Fabc...cde"} -> file_base64 decodes to the victim's file content. POST /api/local_doc_qa/get_doc {"doc_id":"Fabc...cde_1"} -> the victim's chunk text (incl. an embedded secret token).
Impact
Unauthenticated, cross-tenant disclosure of uploaded files and extracted text (the core asset of a private knowledge-base product), with companion unauth endpoints providing the IDs.
Suggested fix
Require real authentication (verified session/token, not a self-asserted user_id); in get_file_base64/get_doc resolve the owner of the requested id and enforce it matches the caller (add the user_id predicate to the SQL); apply the same to get_user_id/list_files and the other read endpoints.
期望行为 | Expected Behavior
No response
运行环境 | Environment
QAnything日志 | QAnything logs
No response
复现方法 | Steps To Reproduce
No response
备注 | Anything else?
No response
Source: netease-youdao/QAnything