fix(sessions/vertexai): quote userId in AIP-160 list filter#499
Merged
kalenkevich merged 2 commits intoJul 20, 2026
Merged
Conversation
VertexAiSessionService.listSessions built the Vertex AI Agent Engine list
filter by interpolating the raw userId into a quoted AIP-160 string literal
(`user_id="${userId}"`). A double quote in userId breaks out of the literal and
appends attacker-controlled predicates, e.g. userId `attacker" OR user_id!="`
yields the filter `user_id="attacker" OR user_id!=""`, which returns sessions
for every user of the deployment (cross-user session enumeration). This service
is reachable from the dev API server route GET
/apps/:appName/users/:userId/sessions, where userId is a caller-controlled path
parameter.
Add quoteFilterLiteral, which escapes backslashes then double quotes so the
value stays inside the literal, and use it when building the filter. Adds a
regression test asserting the escaped filter for a quote-injection payload.
This is the JS/TS counterpart of the same issue previously fixed in adk-python
(google/adk-python#5270, PR google/adk-python#5273, commit bdece00).
Add direct unit tests for quoteFilterLiteral covering plain value, quote injection, backslash-only, and empty input, matching the edge-case coverage of the adk-python fix (google/adk-python#5273).
Contributor
|
Hi @kalenkevich, I have checked the issue and validated the proposed changes. I was able to reproduce the issue. Could you please review this PR? |
kalenkevich
approved these changes
Jul 20, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Link to Issue or Description of Change
Problem
VertexAiSessionService.listSessionsincore/src/sessions/vertex_ai_session_service.tsbuilds the Vertex AI Agent Engine list filter by interpolating the rawuserIddirectly into a quoted AIP-160 string literal:A double-quote character in
userIdbreaks out of the quoted value and lets a caller append arbitrary AIP-160 predicates. For example auserIdofattacker" OR user_id!="produces the filter:Since
user_id!=""matches every session with a non-empty user id, this returns sessions belonging to all users of the same Agent Engine deployment (cross-user session enumeration). Each returned session exposes its id, user id, update time, and state.This is reachable from the dev API server: the route
GET /apps/:appName/users/:userId/sessions(dev/src/server/adk_api_server.ts) readsreq.params.userIdand passes it straight tosessionService.listSessions({appName, userId}), so the attacker only needs to URL-encode"in the path.This is the JS/TS counterpart of an issue previously reported and fixed in adk-python — see google/adk-python#5270 / PR google/adk-python#5273 (merged as
bdece00), where the same unescaped-user_idinterpolation was fixed with a filter-literal quoting helper. I noticed the same pattern here while reviewing the sibling port and am proposing the equivalent fix.Solution
Add a small
quoteFilterLiteralhelper that escapes backslashes first, then double-quotes, so the whole value stays inside the AIP-160 string literal regardless of what is passed in, and use it when building the filter:Testing Plan
Unit tests
Added a regression test to the existing
listSessionssuite incore/test/sessions/vertex_ai_session_service_test.tsthat passes a quote-injectionuserIdand asserts the exact (escaped) filter forwarded to the client:The pre-existing
listSessionstest (userId: 'testUser'->filter: 'user_id="testUser"') continues to hold, since the helper is a no-op for values without metacharacters.Manual validation (filter-string transformation)
main, auserIdofattacker" OR user_id!="produces the filteruser_id="attacker" OR user_id!=""— the injectedOR user_id!=""predicate is live and returns every user's sessions.user_id="attacker\" OR user_id!=\""— the metacharacters stay inside the quoted literal and the filter matches only the literal (non-existent) user.Additional context
Small, focused fix that keeps the current filter-construction approach but ensures
userIdremains data instead of altering the filter expression. Mirrors the escaping order used in the merged adk-python fix (backslashes first, then double quotes).