← Back to PRs

#22910: fix(browser): resolve symlinks in upload path validation

by erdinccurebal open 2026-02-21 20:24 View on GitHub →
size: S
## Summary - On macOS, `/tmp` is a symlink to `/private/tmp` (and `/var` to `/private/var`). The upload path validation in `resolvePathWithinRoot` compared paths using `path.resolve` (which doesn't resolve symlinks), causing legitimate uploads to be rejected when the resolved real path differed from the provided path - The CLI's `normalizeUploadPaths` calls `resolveExistingPathsWithinRoot` which returns real (symlink-resolved) paths via `openFileWithinRoot`. These real paths were then sent to the server, which re-validated them against the unresolved root directory and rejected them - Fixed `resolvePathWithinRoot` to resolve both root and target paths to their real form using `fs.realpathSync` before comparison - Fixed `resolveExistingPathsWithinRoot` to use the real root path when computing relative paths for `openFileWithinRoot` - Symlink escapes (files that symlink outside the upload root) are still correctly rejected — now caught earlier at the path validation level Fixes #22848 ## Test plan - [x] All 6 tests in `src/browser/paths.test.ts` pass (including 2 new tests) - [x] New test: "accepts paths through parent directory symlinks" — verifies uploads work when root dir involves a symlink - [x] New test: "accepts real paths when root uses a symlinked directory" — verifies the CLI→server flow where real paths are sent - [x] `src/browser/server.agent-contract-form-layout-act-commands.test.ts` — 11 tests pass (no regression) - [x] `src/infra/tmp-openclaw-dir.test.ts` — 7 tests pass (no regression) <!-- greptile_comment --> <h3>Greptile Summary</h3> Resolves symlink handling in upload path validation to fix macOS `/tmp` → `/private/tmp` rejection issue. The fix uses `fs.realpathSync()` to resolve both root and target paths before comparison, ensuring legitimate uploads through symlinked directories work correctly while maintaining security by rejecting symlink escapes. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge - it fixes a legitimate path validation bug while maintaining security guarantees - The implementation correctly handles symlink resolution edge cases, includes comprehensive test coverage (2 new tests for symlink scenarios + existing tests still pass), and maintains security by rejecting symlink escapes. The fix is well-scoped to the specific issue without introducing unnecessary changes. - No files require special attention <sub>Last reviewed commit: ba7ada0</sub> <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs