Skip to content

fix: enforce path boundary in built-in agent file tools (path traversal)#5615

Open
adilburaksen wants to merge 1 commit intogoogle:mainfrom
adilburaksen:fix/path-traversal-only
Open

fix: enforce path boundary in built-in agent file tools (path traversal)#5615
adilburaksen wants to merge 1 commit intogoogle:mainfrom
adilburaksen:fix/path-traversal-only

Conversation

@adilburaksen
Copy link
Copy Markdown

Summary

Fixes a path traversal vulnerability in the Agent Builder Assistant's file tools
(read_files, write_files, delete_files, explore_project).

Supersedes #5413 — the YAML callback RCE portion of #5413 was already addressed
internally (2026-04-21). This PR contains only the resolve_root_directory.py fix.

Root cause

Two flaws in resolve_root_directory.py:

Flaw 1 — Absolute path bypass (line 51–52 before fix):

if file_path_obj.is_absolute():
    return file_path_obj   # No boundary check

Any absolute path passed to read_files/write_files/delete_files was returned
directly, allowing /etc/passwd, /root/.ssh/id_rsa, etc.

Flaw 2 — Attacker-controlled root_directory (line 56–57 before fix):

if session_state and "root_directory" in session_state:
    root_directory = session_state["root_directory"]

Session state is set via POST /apps/{app_name}/users/{user}/sessions. An attacker
can inject root_directory: "/" to redirect all relative file paths under /.

Fix

  • _validate_root_directory(): rejects absolute paths and .. components from
    session-state root_directory
  • Boundary check: both absolute and relative file_path values are resolved to
    a real path and verified to be within resolved_root via candidate.relative_to()
  • Removes the unconditional is_absolute → return bypass

Attack scenario (for context)

POST /apps/__agent/users/attacker/sessions
{"state": {"root_directory": "/"}}

POST /run  (app_name=__agent)
{"new_message": {"parts": [{"text": "read /etc/passwd"}]}}
→ returns /etc/passwd contents

No authentication bypass required — /run and session creation have no auth by default
in dev mode; the intended security boundary is container isolation (documented in ADK).

This PR does not change that model — it closes the path escape within the boundary.

Testing

Added _validate_root_directory() unit tests cover: absolute path rejection,
.. component rejection, null-byte rejection, valid relative paths pass through.

resolve_root_directory.py: prevent path traversal in Agent Builder Assistant

- Add _validate_root_directory() to reject absolute paths and '..' from
  session-state root_directory (closes Flaw 2 from the security report)
- Remove the unconditional 'if is_absolute: return' bypass that let any
  absolute file_path skip root enforcement (closes Flaw 1)
- Resolve both candidate and root to real paths, then enforce the boundary
  with candidate.relative_to(resolved_root); ValueError on escape

Affected tools: read_files, write_files, delete_files, explore_project
Attack vector: POST /apps/__agent session state + read_files with '/'
  root_directory or absolute file_path → arbitrary file read/write/delete
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tools [Component] This issue is related to tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants