You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Quote user_id literals in VertexAiSessionService list filters #5270
VertexAiSessionService.list_sessions() builds an AIP-160 filter by interpolating raw user_id into a quoted literal. Embedded quotes can break out of that literal and append extra filter syntax.
So a value such as attacker" OR user_id!="" produces: user_id="attacker" OR user_id!=""
That changes the filter expression instead of keeping the whole value inside the string literal.
Expected behavior
user_id should be quoted as a filter literal before interpolation so embedded quotes and backslashes stay inside the value.
Proposed fix
Quote the filter literal before constructing the AIP-160 filter string and add a regression test that captures the exact filter passed to the Vertex client.
Validation
I have a PR prepared that:
quotes user_id before building the filter
adds a regression test for a quote-containing payload
reproduces the unsafe filter string on current origin/main
passes pytest tests/unittests/sessions in clean Linux Docker
@petrmarinec Thanks for the clear write-up — reproduced the injection on our end against the config['filter'] line in list_sessions()!
A workaround worth verifying: escape backslashes first, then double-quotes in user_id before interpolation (value.replace("\", "\\").replace('"', '\"')).
That keeps the whole value inside the AIP-160 string literal regardless of what's passed in.
Since you already have PR #5273 in flight, could you confirm that approach handles edge cases like backslash-only input and empty strings on your side before pushing it to review?
@petrmarinec That's exactly the coverage we needed — quote injection, backslash-only, and empty string nail the full edge-case surface for AIP-160 literal escaping, and 31/31 passing looks solid!
@petrmarinec The fix from PR #5273 has been merged — _quote_filter_literal() is now live in vertex_ai_session_service.py and the config['filter'] line uses it correctly.
The injection is no longer possible in v1.30.0 and later.
Thanks again for the thorough write-up, the edge-case test coverage, and the clean PR.
Activity
surajksharma07 commentedon Apr 11, 2026
@petrmarinec Thanks for the clear write-up — reproduced the injection on our end against the config['filter'] line in list_sessions()!
A workaround worth verifying: escape backslashes first, then double-quotes in user_id before interpolation (value.replace("\", "\\").replace('"', '\"')).
That keeps the whole value inside the AIP-160 string literal regardless of what's passed in.
Since you already have PR #5273 in flight, could you confirm that approach handles edge cases like backslash-only input and empty strings on your side before pushing it to review?
petrmarinec commentedon Apr 11, 2026
Thanks, confirmed and pushed an update to #5273.
I changed the helper to use the escaping order you suggested: escape backslashes first, then double-quotes before wrapping the value in quotes.
Added regression coverage for these cases:
attacker" OR user_id!=""->user_id="attacker\" OR user_id!=\"\""\->user_id="\\"user_id=""Verified locally:
PYTHONPATH=src python -m pytest tests/unittests/sessions/test_vertex_ai_session_service.py31 passedsurajksharma07 commentedon Apr 11, 2026
@petrmarinec That's exactly the coverage we needed — quote injection, backslash-only, and empty string nail the full edge-case surface for AIP-160 literal escaping, and 31/31 passing looks solid!
Team is looking more into it.
surajksharma07 commentedon Apr 19, 2026
@DeanChensj Please have a look into it once.
DeanChensj commentedon Apr 21, 2026
Thanks for the PR!
fix: Quote user_id literals in VertexAiSessionService list filters
surajksharma07 commentedon Apr 24, 2026
@petrmarinec The fix from PR #5273 has been merged — _quote_filter_literal() is now live in vertex_ai_session_service.py and the config['filter'] line uses it correctly.
The injection is no longer possible in v1.30.0 and later.
Thanks again for the thorough write-up, the edge-case test coverage, and the clean PR.
fix(sessions/vertexai): quote userId in AIP-160 list filter (#499)
fix: Quote user_id literals in VertexAiSessionService list filters
fix(session/vertexai): quote userId in AIP-160 list filter (#1171)
fix: backport session service fixes (#1322, #1204, #1237, #1171) (#1502)
fix(session/vertexai): quote userId in AIP-160 list filter (google#1171)
fix(session/vertexai): quote userId in AIP-160 list filter (google#1171)