Skip to content

Collection routing ignores caller authorization context #267

Description

@3em0

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:

  1. Configure a vector database with at least two collections, for example:
    • board_docs: restricted board materials.
    • public_docs: public announcements.
  2. Use a collection router with an LLM response that selects board_docs for a query such as quarterly revenue.
  3. 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"].
  4. Observe that both callers can receive board_docs in the selected collection list because the router does not evaluate the caller context.
  5. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions