Skip to content

bug(cli): sandbox upload aborts on EPERM when uploading directories containing OS-protected paths #2920

Description

@MarsKubeX

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> and sandbox 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

  1. On macOS (without Full Disk Access for the terminal/app):
    openshell sandbox create --name test-sandbox
  2. openshell sandbox upload test-sandbox ~ /sandbox/home
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    state:triage-neededOpened without agent diagnostics and needs triage

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions