Repository navigation
fix(sessions): list only the empty user's sessions in FirestoreSessionService - #7663
AkshayShah03 wants to merge 2 commits into
Conversation
…nService list_sessions checked `if user_id:`, so user_id="" fell through to the all-users collection_group query and returned every user's sessions. Check `is not None` instead, as the other session services do. Fixes google#7662
Somay-kousis
left a comment
There was a problem hiding this comment.
Ran this locally. The fix does what it says for the leak: user_id="" no longer takes the collection_group path that returns every user's sessions.
What I ran (PR head e44692c, merge base d324744)
- New test
test_list_sessions_with_empty_user_id_lists_only_that_user: passes on head. With onlyfirestore_session_service.pyreverted to the merge base it fails withExpected 'collection_group' to not have been called. Called 1 times. tests/unittests/integrations/firestore: 53 passed on head.- Grepped the file for other truthiness checks on
user_id: none left after this change.
Findings
-
Worth considering (suspicion, not verified against a real database): with a real client,
user_id=""now builds a query on an empty path segment.src/google/adk/integrations/firestore/firestore_session_service.py:371calls_get_sessions_ref(app_name, ""), and google-cloud-firestore 2.34.1 acceptsdocument("")locally. The query parent it would send isprojects/p/databases/(default)/documents/adk-session/app/users/(trailing slash, empty document id). I expect the Firestore backend to reject that with INVALID_ARGUMENT rather than return[], so callers would get an exception where the other session services return an empty list. I had no emulator, so I could not confirm the server response.create_session(user_id="")builds the same path, so no session for""can exist in Firestore anyway. If the server does reject it, returning an emptyListSessionsResponseearly whenuser_id == ""would match the other services and avoid the round trip. Either way this is still better than the current leak. -
Nit: the second change (line 395, user-state lookup) is not covered by the test. I put line 395 back to
if user_id:and the whole firestore suite still passes (53 passed). As far as I can tell the result is the same in that case, because theelsebranch would fetch user""throughget_allinstead, so this line is a consistency change rather than a behaviour fix. Fine to keep, just noting the test only pins line 371.
Not checked
- Behaviour against a real Firestore instance or the emulator (see 1).
- Anything outside
list_sessions, and the broadertests/unittests/sessionssuite.
The Firestore backend rejects a document path with an empty segment (400 InvalidArgument, checked against the emulator), so list_sessions with user_id="" raised instead of returning an empty list, and create_session cannot store a session for that user either.
|
Thanks for running it and for the careful review @Somay-kousis. On (1), you were right. I checked against the Firestore emulator (cloud-firestore-emulator v1.19.8):
af160d6 now returns an empty On (2): with the early return, the empty-string case no longer reaches the user-state lookup, so that line is now only the |
Link to Issue or Description of Change
1. Link to an existing issue (if applicable):
SqliteSessionService)Problem:
FirestoreSessionService.list_sessionschecksif user_id:, souser_id=""falls through to thecollection_groupquery thatuser_id=Noneuses, and returns every user's sessions in the app. The other session services (InMemory, Sqlite, Database, Redis, VertexAI) treat""as a user id.Solution:
ListSessionsResponseforuser_id == ""without querying. The Firestore backend rejects a document path with an empty segment (400 InvalidArgument, checked against the emulator), so querying that user's collection would raise, andcreate_session(user_id="")can't store a session for that user either. An empty list matches the other session services.user_id is not Noneinstead of truthiness in the rest oflist_sessions, as the other services do.Testing Plan
Unit Tests:
Added
test_list_sessions_with_empty_user_id_returns_no_sessionstotests/unittests/integrations/firestore/test_firestore_session_service.py. It fails onmain(collection_groupis called) and passes with this change.The one failure,
integrations/vmaas/test_agent_engine_environment.py::test_reading_directory_raises, also fails onmainwithout this change.pyinkandisortreport no changes.Manual End-to-End (E2E) Tests:
Ran the snippet from #7662 (mocked Firestore client with two other users' sessions):
main:[('alice', 's-alice'), ('bob', 's-bob')] collection_group used: True[] collection_group used: FalseAlso ran against the Firestore emulator (cloud-firestore-emulator v1.19.8), with sessions for
aliceandbob:main:list_sessions(user_id="")returns the sessions of both userslist_sessions(user_id="")returns[];Noneand"alice"are unchangedcreate_session(user_id="")fails on both with400 Document name ".../users//sessions/..." lacks a resource id, so no session for""can existChecklist