bug(cli): `sandbox upload` aborts on EPERM when uploading directories containing OS-protected paths
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 8.7k
- Forks
- 1.3k
- Avg merge
- 2d 11h
- Merged PRs (30d)
- 253
Description
User Story
As an integrator building a desktop application on OpenShell,
I want sandbox upload (and sandbox create --upload) to skip inaccessible paths with a warning instead of aborting,
so that uploading broad directory trees (e.g. $HOME) works without requiring elevated OS permissions.
Problem Statement
When sandbox upload or sandbox create --upload is given a broad host directory (e.g. $HOME or /),
the tar-packing phase walks the local directory tree recursively. If any path returns EPERM
(or PermissionDenied) — for example, macOS TCC-protected directories like ~/.Trash,
~/Library/Mail, ~/Library/Safari, or ~/Library/Containers — the entire upload aborts
immediately.
There is no flag or mechanism to continue past inaccessible paths. The upload is all-or-nothing.
Impact / Why This Matters
When this happens, any integration that uploads $HOME (or another broad tree) to a sandbox
fails on macOS unless the calling application has Full Disk Access — a manual system-level permission
that users must grant through System Settings > Privacy & Security. On Linux, similar failures occur
with root-owned dotfiles or restricted directories under /.
This results in:
- Integrators cannot offer a "Home Directory" upload mode out of the box — the most common desktop
use case for broad file access silently fails. - The only workaround today is asking every user to grant Full Disk Access to the application, which
is a significant trust and UX barrier. - The sandbox itself is created successfully; only the upload step fails. This means the sandbox
exists but is missing its intended content, leading to confusing downstream failures.
Acceptance Criteria
-
sandbox upload <dir> <dest>andsandbox create --upload <dir>:<dest>complete
successfully when the source tree contains inaccessible paths, skipping those paths
and uploading everything else. - Each skipped path emits a visible warning to stderr (e.g.
⚠ skipping (permission denied): /Users/x/.Trash). - A summary line reports how many paths were skipped (e.g.
⚠ 3 paths skipped due to permission errors). - A mechanism exists (new default behavior or opt-in flag) to let uploads
continue past permission-denied paths instead of aborting. - Uploads that do not encounter permission errors are unaffected — no change in behavior
or output when all paths are accessible. - Unit tests cover the skip path for both
read_dir(directory listing denied) and
symlink_metadata(stat denied) failure modes.
Reproduction Steps
- On macOS (without Full Disk Access for the terminal/app):
openshell sandbox create --name test-sandbox openshell sandbox upload test-sandbox ~ /sandbox/home- Observe the upload aborts with an error like:
Error: failed to read directory /Users/<username>/.Trash Caused by: Operation not permitted (os error 1)
Alternatively, create with inline upload:
openshell sandbox create --upload : -- true
(same EPERM abort)
Environment
- Openshell v0.0.92
- OS: macOS 15.x (Apple Silicon) — TCC-protected paths under $HOME
- Runtime: Podman
Logs
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the sandbox upload and sandbox create --upload entry points and trace the tar-packing directory walk. Add unit coverage for denied read_dir and symlink_metadata operations, then verify inaccessible paths are skipped with stderr warnings and a summary while accessible uploads retain their current behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100