Please describe your issue in English
Note: Small LLMs cannot perform well at prompt following, and are prone to hallucinations. Please make sure your LLM is cutting-edge, preferably a reasoning model, e.g. OpenAI o-series, DeepSeek R1, Claude 3.7 Sonnet etc.
Describe the bug
CollectionRouter.invoke() accepts arbitrary keyword arguments but does not use caller authorization context when selecting vector database collections. Routing is based only on the query and the globally listed collection names/descriptions. Downstream RAG flows then search the selected collections directly.
If DeepSearcher is deployed as a shared service where different users, tenants, roles, or permission scopes are allowed to access different collections, two callers with different authorization scopes can be routed to the same restricted collection. This can expose retrieval results from collections the caller should not be allowed to search.
Relevant code:
deepsearcher/agent/collection_router.py: invoke(query, dim, **kwargs) ignores **kwargs.
deepsearcher/agent/collection_router.py: collection selection is based on vector_db.list_collections(dim=dim) and LLM-selected collection names.
deepsearcher/agent/naive_rag.py: retrieve() calls the collection router with only query and dim, then calls vector_db.search_data() for each selected collection.
deepsearcher/agent/deep_search.py and deepsearcher/agent/chain_of_rag.py follow the same routing/search pattern.
To Reproduce
Steps to reproduce the behavior:
- Configure a vector database with at least two collections, for example:
board_docs: restricted board materials.
public_docs: public announcements.
- Use a collection router with an LLM response that selects
board_docs for a query such as quarterly revenue.
- Call
CollectionRouter.invoke() twice with the same query but different caller contexts, for example:
- Caller A:
tenant_id=tenant_a, permissions=executive-read, authorized_collection_set=["board_docs", "public_docs"].
- Caller B:
tenant_id=tenant_b, permissions=public-read, authorized_collection_set=["public_docs"].
- Observe that both callers can receive
board_docs in the selected collection list because the router does not evaluate the caller context.
- In a RAG flow such as
NaiveRAG.retrieve(), observe that the selected collection is searched directly.
Minimal behavioral expectation:
selected_victim, _ = router.invoke(
"quarterly revenue",
dim=embedding.dimension,
tenant_id="tenant_a",
permissions="executive-read",
authorized_collection_set=["board_docs", "public_docs"],
)
selected_attacker, _ = router.invoke(
"quarterly revenue",
dim=embedding.dimension,
tenant_id="tenant_b",
permissions="public-read",
authorized_collection_set=["public_docs"],
)
assert "board_docs" in selected_victim
assert "board_docs" not in selected_attacker
Actual behavior: selected_attacker can include board_docs because authorization-related fields are ignored.
Expected behavior
Collection routing should not select collections outside the caller's authorized collection set. If an application supplies authorization context through **kwargs or another request context, that context should be enforced before retrieval. At minimum, selected collections should be intersected with the caller's authorized collection set before search_data() is called.
If DeepSearcher intentionally does not implement authorization, the documentation should state that collection-level access control must be enforced by the embedding application or vector database layer before exposing RAG endpoints to multiple users.
Screenshots
Not applicable.
Environment (please complete the following information):
- OS: Linux
- pip dependencies: project installed from the current repository checkout
- Version: current
master checkout of zilliztech/deep-searcher
Additional context
This is most relevant for deployments that expose DeepSearcher as a multi-user or multi-tenant service. The repository does not appear to define first-class tenant_id, user_id, permissions, or authorized_collection_set models, so the issue is conditional on the deployment using collections as an access-control boundary.
Security impact: unauthorized users may retrieve or summarize content from collections they should not be allowed to search if the application relies on DeepSearcher routing to constrain accessible collections.
Please describe your issue in English
Note: Small LLMs cannot perform well at prompt following, and are prone to hallucinations. Please make sure your LLM is cutting-edge, preferably a reasoning model, e.g. OpenAI o-series, DeepSeek R1, Claude 3.7 Sonnet etc.
Describe the bug
CollectionRouter.invoke()accepts arbitrary keyword arguments but does not use caller authorization context when selecting vector database collections. Routing is based only on the query and the globally listed collection names/descriptions. Downstream RAG flows then search the selected collections directly.If DeepSearcher is deployed as a shared service where different users, tenants, roles, or permission scopes are allowed to access different collections, two callers with different authorization scopes can be routed to the same restricted collection. This can expose retrieval results from collections the caller should not be allowed to search.
Relevant code:
deepsearcher/agent/collection_router.py:invoke(query, dim, **kwargs)ignores**kwargs.deepsearcher/agent/collection_router.py: collection selection is based onvector_db.list_collections(dim=dim)and LLM-selected collection names.deepsearcher/agent/naive_rag.py:retrieve()calls the collection router with onlyqueryanddim, then callsvector_db.search_data()for each selected collection.deepsearcher/agent/deep_search.pyanddeepsearcher/agent/chain_of_rag.pyfollow the same routing/search pattern.To Reproduce
Steps to reproduce the behavior:
board_docs: restricted board materials.public_docs: public announcements.board_docsfor a query such asquarterly revenue.CollectionRouter.invoke()twice with the same query but different caller contexts, for example:tenant_id=tenant_a,permissions=executive-read,authorized_collection_set=["board_docs", "public_docs"].tenant_id=tenant_b,permissions=public-read,authorized_collection_set=["public_docs"].board_docsin the selected collection list because the router does not evaluate the caller context.NaiveRAG.retrieve(), observe that the selected collection is searched directly.Minimal behavioral expectation:
Actual behavior:
selected_attackercan includeboard_docsbecause authorization-related fields are ignored.Expected behavior
Collection routing should not select collections outside the caller's authorized collection set. If an application supplies authorization context through
**kwargsor another request context, that context should be enforced before retrieval. At minimum, selected collections should be intersected with the caller's authorized collection set beforesearch_data()is called.If DeepSearcher intentionally does not implement authorization, the documentation should state that collection-level access control must be enforced by the embedding application or vector database layer before exposing RAG endpoints to multiple users.
Screenshots
Not applicable.
Environment (please complete the following information):
mastercheckout ofzilliztech/deep-searcherAdditional context
This is most relevant for deployments that expose DeepSearcher as a multi-user or multi-tenant service. The repository does not appear to define first-class
tenant_id,user_id,permissions, orauthorized_collection_setmodels, so the issue is conditional on the deployment using collections as an access-control boundary.Security impact: unauthorized users may retrieve or summarize content from collections they should not be allowed to search if the application relies on DeepSearcher routing to constrain accessible collections.