Skip to content

DELETE /documents has no ownership check and deletes before validating (cross-tenant data destruction) #303

Description

@nangelovv

Summary

DELETE /documents has two related problems:

  1. No ownership check. It deletes whatever file_ids are supplied, with no user_id verification, so any authenticated caller can delete another tenant's document chunks — irreversible cross-tenant data destruction.
  2. Deletes before validating. It calls delete() first and checks existence afterwards, so a request mixing valid and unknown ids destroys the valid rows and then returns 404 ("not found"), implying nothing happened.

Current code

async def delete_documents(request: Request, document_ids: List[str] = Body(...)):
    try:
        if isinstance(vector_store, AsyncPgVector):
            existing_ids = await vector_store.get_filtered_ids(document_ids, ...)
            await vector_store.delete(ids=document_ids, ...)   # (2) deletes first
        ...
        if not all(id in existing_ids for id in document_ids):  # (2) validates after
            raise HTTPException(status_code=404, detail="One or more IDs not found")
        # (1) user_id is never consulted

Impact

  • A caller who knows/guesses another user's file_id can delete that user's documents.
  • A partially-wrong batch (["valid_id", "ghost_id"]) destroys valid_id and returns 404, masking the data loss.

Fix

Resolve the requester identity, fetch the target documents, and verify existence (404) and ownership (403) before the destructive delete; delete nothing when either check fails. Unowned chunks (user_id is None) stay deletable. This is an intentional contract change (DELETE gains authorization). Related prior art: #262. PR to follow.

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