Skip to content

fix: keep local environment file access in workspace - #5870

Closed
he-yufeng wants to merge 1 commit into
google:mainfrom
he-yufeng:fix/local-environment-path-boundary
Closed

fix: keep local environment file access in workspace#5870
he-yufeng wants to merge 1 commit into
google:mainfrom
he-yufeng:fix/local-environment-path-boundary

Conversation

@he-yufeng

Copy link
Copy Markdown
Contributor

Fixes#5869

Summary

  • resolve LocalEnvironment read/write paths against the workspace root
  • reject relative traversal and absolute paths outside working_dir
  • keep absolute paths inside working_dir working
  • add regression coverage for relative and absolute escape attempts

Tests

  • python -m pytest tests\unittests\tools\test_local_environment.py -q -p no:cacheprovider --basetemp .tmp\pytest
  • python -m ruff check src\google\adk\environment\_local_environment.py tests\unittests\tools\test_local_environment.py
  • python -m pyink --check src\google\adk\environment\_local_environment.py tests\unittests\tools\test_local_environment.py
  • python -m py_compile src\google\adk\environment\_local_environment.py tests\unittests\tools\test_local_environment.py
  • git diff --check

@adk-botadk-bot added the tools [Component] This issue is related to tools label May 27, 2026
@he-yufeng
he-yufengforce-pushed the fix/local-environment-path-boundary branch from 04a49ff to 34870c2CompareMay 27, 2026 18:11
@rohityanrohityan self-assigned this May 27, 2026
@rohityanrohityan added the needs review [Status] The PR/issue is awaiting review from the maintainer label May 27, 2026
@rohityan
rohityan requested a review from wyf7107May 27, 2026 19:22
@rohityan

Copy link
Copy Markdown
Collaborator

Hi @he-yufeng , Thank you for your contribution! We appreciate you taking the time to submit this pull request. Your PR has been received by the team and is currently under review. We will provide feedback as soon as we have an update to share.

@rohityan

Copy link
Copy Markdown
Collaborator

Hi @wyf7107 , can you please review this.

@er3b07

er3b07 commented May 28, 2026

Copy link
Copy Markdown

Hi @he-yufeng and team, just verified that the fix corrects successfully the path traversal
#5869

@he-yufeng

Copy link
Copy Markdown
ContributorAuthor

Gentle ping on this path-boundary fix. The branch is green, and #5869 verified the path traversal behavior after the patch.

The change stays limited to keeping local environment file access inside the workspace root. Happy to make any naming or API-shape adjustment if maintainers prefer a different boundary helper.

@he-yufeng
he-yufengforce-pushed the fix/local-environment-path-boundary branch 2 times, most recently from 34870c2 to 3f2af35CompareJune 12, 2026 01:15
@he-yufeng

Copy link
Copy Markdown
ContributorAuthor

Rebased onto the current upstream/main and resolved the LocalEnvironment path-resolution conflict.

The conflict was caused by upstream changing the helper to return Path; the branch now keeps that return type while preserving the workspace-boundary check.

Validation:

  • python -m py_compile src/google/adk/environment/_local_environment.py tests/unittests/tools/test_local_environment.py
  • PYTHONPATH=src python -m pytest tests/unittests/tools/test_local_environment.py -q (10 passed)
  • git diff --check upstream/main..HEAD

Current head: 3f2af35e

@he-yufeng
he-yufengforce-pushed the fix/local-environment-path-boundary branch 2 times, most recently from 931452c to 29d160bCompareJune 12, 2026 13:28
@he-yufeng

Copy link
Copy Markdown
ContributorAuthor

Rebased this on current main and re-ran the focused local checks:

  • PYTHONPATH=src python -m pytest tests\unittests\tools\test_local_environment.py -q -p no:cacheprovider --basetemp .tmp\pytest-5870 -> 10 passed
  • python -m py_compile on the touched files
  • python -m ruff check on the touched files
  • python -m pyink --check on the touched files
  • git diff --check upstream/main..HEAD

All passed locally.

@he-yufeng
he-yufengforce-pushed the fix/local-environment-path-boundary branch 2 times, most recently from 1d61969 to 77f9a9bCompareJune 12, 2026 21:58
@GWealeGWeale assigned GWeale and unassigned rohityanJun 15, 2026
@he-yufeng
he-yufengforce-pushed the fix/local-environment-path-boundary branch 3 times, most recently from e5c32d2 to 3c3cdd3CompareJune 18, 2026 06:16
@he-yufeng
he-yufengforce-pushed the fix/local-environment-path-boundary branch from 3c3cdd3 to f08eadcCompareJune 18, 2026 10:14
@er3b07

Copy link
Copy Markdown

Hi @GWeale@wyf7107 — gentle ping on #5870 (Fixes #5869).

I re-tested today against google-adk 2.3.0 on PyPI and current main: the path traversal behavior described in #5869 is still reproducible. I also confirmed the fix on this branch blocks the PoC as expected.

Whenever there is an update on review timing, I am happy to help re-test or provide any additional details.

Thank you for your time.

@wuliang229wuliang229 self-assigned this Jul 9, 2026
@wuliang229

Copy link
Copy Markdown
Collaborator

Merged in commit f41bc79

sasha-gitg added a commit to sasha-gitg/adk-python-public that referenced this pull request Aug 5, 2026
Backport of the `_local_environment.py` / `test_local_environment.py`
portion of the following commit from `main`, released in v2.5.0:
f41bc79
(squashed copybara commit; upstream PR google#5870, fixesgoogle#5869)
Only the two files above are taken from that commit -- the rest of it is
unrelated (a2a sample, PR-triage agent, transfer_to_agent_tool).
Adapted rather than cherry-picked directly: on `main` `_resolve_path`
returns a `Path`, while on v1 it returns `str` and `_sync_read` /
`_sync_write` take `str`. The containment check is the same; the v1
return type is preserved to keep the change minimal.
`_resolve_path` returned absolute paths verbatim:
if os.path.isabs(path):
return path
so `working_dir` was advisory only, and `read_file` / `write_file` --
and therefore the ReadFile, WriteFile and EditFile tools -- could reach
any path the process could access.
Paths are now resolved against `working_dir` and rejected with a
`ValueError` if they escape it. Absolute paths that stay inside
`working_dir` keep working.
sasha-gitg added a commit to sasha-gitg/adk-python-public that referenced this pull request Aug 5, 2026
Backport of the `_local_environment.py` / `test_local_environment.py`
portion of the following commit from `main`, released in v2.5.0:
f41bc79
(squashed copybara commit; upstream PR google#5870, fixesgoogle#5869)
Only the two files above are taken from that commit -- the rest of it is
unrelated (a2a sample, PR-triage agent, transfer_to_agent_tool).
Adapted rather than cherry-picked directly: on `main` `_resolve_path`
returns a `Path`, while on v1 it returns `str` and `_sync_read` /
`_sync_write` take `str`. The containment check is the same; the v1
return type is preserved to keep the change minimal.
`_resolve_path` returned absolute paths verbatim:
if os.path.isabs(path):
return path
so `working_dir` was advisory only, and `read_file` / `write_file` --
and therefore the ReadFile, WriteFile and EditFile tools -- could reach
any path the process could access.
Paths are now resolved against `working_dir` and rejected with a
`ValueError` if they escape it. Absolute paths that stay inside
`working_dir` keep working.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs review[Status] The PR/issue is awaiting review from the maintainertools[Component] This issue is related to tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

6 participants

@he-yufeng@rohityan@er3b07@wuliang229@GWeale@adk-bot