fix(browser): floor browser-use CLI subprocess PATH with sane system dirs - #93116
justcarlosm wants to merge 1 commit into
Conversation
…dirs Profile-spawned workers (kanban bots, cron jobs) can inherit a PATH of only version-manager dirs — observed in the wild as one nvm node dir repeated 7x. The uv-installed browser-use binary is a POSIX sh trampoline that resolves dirname/realpath through PATH, so it died with 'realpath: not found … exec: /python: not found' (exit 127) before its own Python ever started. _base_subprocess_env now floors the child PATH via browser_tool's _merge_browser_path (the agent-browser backend already guards the same hazard), degrading to appending FHS bin dirs if that import is ever unavailable. Windows is a no-op (.cmd shims don't trampoline). Verified: unit tests + real uvx browser-use --version under a nvm-only-PATH worker env, rc 127 -> rc 0.
Good diagnosis and a sensible guard: flooring the subprocess PATH so coreutils (
Minor: the hardcoded FHS list duplicates browser_tool's; consider exporting one shared constant so they can't diverge. |
|
Merged via #93356 (rebase) — your commit is on main with authorship preserved. |
Fixes #93115
Summary
browser_execdies with exit 127 (realpath: not found … exec: /python: not found) whenever a Hermes process inherits a PATH of only version-manager dirs — observed in the wild from kanban/cron profile workers carrying one nvm dir repeated 7x. The uv-installedbrowser-useentry point is a POSIX sh trampoline that resolvesdirname/realpaththrough PATH at invocation time, so it fails before its own Python starts.The agent-browser backend already defends against exactly this hazard via
tools/browser_tool.py::_merge_browser_path(); this change gives the browser-use backend the same floor.What changed
tools/browser_use_cli.py_base_subprocess_env()now floors the child PATH through a new_floor_subprocess_path()helper.browser_tool._merge_browser_path()(same sane-dir list, never drops or reorders existing entries) and degrades to appending FHS bin dirs if that import is ever unavailable..cmdshims don't trampoline through PATH.tests/tools/test_browser_use_cli.pytest_subprocess_env_floors_version_manager_only_path— the observed-in-the-wild case (nvm-only ×7) must yield/usr/bin+/bin.test_floor_preserves_existing_entries_and_order— floor only adds; existing entries keep relative order.test_floor_survives_missing_sibling_helper— degraded fallback still guarantees/usr/bin.Test plan
pytest tests/tools/test_browser_use_cli.py -o 'addopts=' -q→ 95 passedtest_browser_use_session_expiry.py,test_browser_homebrew_paths.py→ 32 passedenv -i HOME=… PATH=<nvm-dir>→_find_cli()resolves the managed uvx path →_base_subprocess_env()child PATH contains/usr/bin→uvx browser-use --versionexits 0 printing0.1.9; control run without the floor reproduces exit 127 byte-for-byte with the field report.Notes for reviewers
_merge_browser_path()rather than duplicating its list — if the sane-dir set changes for agent-browser, browser-use follows. The try/except keeps this file independent of that module's internals in tests (existing pattern in this suite stubstools.browser_tool)._base_subprocess_env) — every browser-use CLI launch goes through it, including the uvx zero-install fallback resolved by_find_cli().