fix(connectors): scope index endpoint authorization to the connector's own search space

The POST /search-source-connectors/{connector_id}/index endpoint loaded
the connector by id and then called check_permission() against the
client-supplied search_space_id query parameter (the caller's own space)
rather than the connector's own search_space_id, and never verified that
the two matched.

A user could therefore index another user's connector by passing their
own search_space_id: the indexer ran with the victim connector's stored
credentials and wrote the fetched content into the attacker's search
space. The read/update/delete handlers already authorize against
connector.search_space_id; this brings the index handler in line.

Reject a connector that does not belong to the requested search space
(404, to avoid disclosing connectors in other spaces) and authorize the
permission check against connector.search_space_id.
This commit is contained in:
Dmitry Maranik 2026-06-16 15:58:30 -07:00
parent 5d99489f4b
commit e1ea82d7cf

View file

@ -745,11 +745,23 @@ async def index_connector_content(
if not connector:
raise HTTPException(status_code=404, detail="Connector not found")
# Check if user has permission to update connectors (indexing is an update operation)
# Ensure the connector actually belongs to the requested search space.
# Without this, the permission check below would authorize against the
# caller-supplied search_space_id (their own space) while the connector
# lives in another user's space, allowing cross-tenant indexing of a
# foreign connector (and use of its stored credentials). Returning 404
# (rather than 403) on a mismatch also avoids disclosing the existence of
# connectors in other search spaces.
if connector.search_space_id != search_space_id:
raise HTTPException(status_code=404, detail="Connector not found")
# Check if user has permission to update connectors (indexing is an update
# operation). Authorize against the connector's OWN search space — matching
# the read/update/delete handlers — not the client-supplied query param.
await check_permission(
session,
user,
search_space_id,
connector.search_space_id,
Permission.CONNECTORS_UPDATE.value,
"You don't have permission to index content in this search space",
)