security: reject caller writes to reserved internal session state keys#1242
Open
XananasX7 wants to merge 1 commit into
Open
security: reject caller writes to reserved internal session state keys#1242XananasX7 wants to merge 1 commit into
XananasX7 wants to merge 1 commit into
Conversation
The dev web API accepted arbitrary session state from callers through both initial session creation and per-run stateDelta. Internal framework keys such as _code_execution_context are stored in the same mutable session-state namespace that callers can write to. The code execution path in CodeExecution.getOrSetExecutionId() reads _code_execution_context.execution_session_id from session state and prefers any pre-existing value over deriving a new one from the ADK session id. This means a caller who seeds that key via createSession state or stateDelta can steer which backing interpreter session is used by VertexAiCodeExecutor, potentially accessing another session's files, variables, or prior execution context. Fix: - Add RESERVED_STATE_KEYS constant enumerating all internal executor control keys (_code_execution_context, _code_executor_input_files, _code_executor_error_counts, _code_execution_results). - Add sanitizeCallerState() helper that strips reserved keys from any caller-supplied state map and logs a warning for each dropped key. - Apply sanitizeCallerState() in createSession() so reserved keys in initial session state are never persisted. - In appendEvent(), skip writes for reserved keys in stateDelta with a warning log, so per-run stateDelta cannot overwrite them either. Signed-off-by: El Mehdi Abenhazou <mehdiananas007@gmail.com>
Author
|
Hi — this fixes a caller-controlled session state injection reported to Google OSS VRP. The dev web API accepts arbitrary state through both session creation and per-run The fix adds a |
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.
Summary
The dev web API accepts arbitrary session state from callers through both initial session creation (
POST /apps/{app}/users/{user}/sessions) and per-runstateDelta(POST /run/POST /run_sse). Internal framework keys such as_code_execution_contextare stored in the same mutable session-state namespace, with no restriction on caller writes.Root cause
InMemorySessionService.createSession()accepts a caller-suppliedMap<String, Object> stateand stores it verbatim.appendEvent()iteratesstateDeltaand writes every non-prefixed key directly tosession.state().CodeExecution.getOrSetExecutionId()reads_code_execution_context.execution_session_idfrom session state, and returns the existing value if one is already present without any validation.VertexAiCodeExecutorthen forwards that value assession_idto the Vertex code interpreter extension.Combined, a caller can:
{ "state": { "_code_execution_context": { "execution_session_id": "attacker-chosen-session" } } }…and force subsequent code execution to bind to an arbitrary interpreter session identifier instead of the one derived from the ADK session.
Fix
Added a
RESERVED_STATE_KEYSconstant enumerating all internal executor-control keys:Added
sanitizeCallerState()which strips any reserved key from a caller-supplied state map (logging a warning for each):createSession()so reserved keys in initial session state are never persisted.appendEvent()so per-runstateDeltacannot overwrite reserved keys either.Internal framework code that legitimately writes these keys does so through
CodeExecutorContext.getStateDelta()→appendEvent()— but those writes go through theEventActions.stateDelta()path which is generated server-side, not from untrusted caller input.