Skip to content

fix(cli): cp-style sandbox download and workspace-boundary check#1318

Draft
laitingsheng wants to merge 1 commit into
NVIDIA:mainfrom
laitingsheng:fix/sandbox-download-traversal-and-file-shape
Draft

fix(cli): cp-style sandbox download and workspace-boundary check#1318
laitingsheng wants to merge 1 commit into
NVIDIA:mainfrom
laitingsheng:fix/sandbox-download-traversal-and-file-shape

Conversation

@laitingsheng
Copy link
Copy Markdown
Contributor

@laitingsheng laitingsheng commented May 12, 2026

Summary

openshell sandbox download produced a directory at the host destination instead of writing the source bytes as a regular file, and did not refuse sandbox-side paths that resolved outside /sandbox. This brings the download path to parity with the upload-side cp-style fix shipped in #694 (#667) and #952 (#885), and adds the explicit workspace-boundary check that the upload side never needed.

Related Issue

Fixes NVIDIA/NemoClaw#3345

Changes

  • sandbox_sync_down now validates the sandbox-side source path with a lexical workspace-boundary check before issuing any SSH command. Paths that resolve outside /sandbox (e.g. /etc/passwd, /sandbox/../etc/passwd, /sandboxed/secrets) are refused with a clear error.
  • Pre-probes whether the source is a file or directory over SSH, then branches.
  • Single-file downloads follow cp-style destination semantics:
    • Trailing slash on dest (or dest already exists as a directory) → file lands at <dest>/<source-basename>.
    • Otherwise dest is taken as the exact file path.
    • Extraction is staged in a sibling directory and the staged entry is atomically renamed into place.
    • Refuses to overwrite an existing directory with the downloaded file.
  • Directory downloads preserve prior flat-extract behaviour into dest (with an early refusal when dest exists as a non-directory).
  • The SSH tar stream is now factored through a shared stream_sandbox_tar helper, mirroring the upload-side ssh_tar_upload refactor from fix(cli): sandbox upload overwrites files instead of creating directories #694.
  • Caller signature: sandbox_sync_down takes dest: &str so trailing slashes survive (previously the value was converted to &Path at the dispatch site, which dropped them).

Testing

  • mise run pre-commit passes
  • Unit tests added/updated
  • E2E tests added/updated (if applicable)

Checklist

  • Follows Conventional Commits
  • Commits are signed off (DCO)
  • Architecture docs updated (if applicable)

`openshell sandbox download` produced a directory at the host destination
instead of writing the source bytes as a regular file, and did not refuse
sandbox-side paths that resolved outside `/sandbox` (only `creds.json` was
rejected, by filesystem policy rather than by an explicit check).

Mirrors the cp-style design from the upload-side fixes (NVIDIA#667 / NVIDIA#694 and
NVIDIA#885 / NVIDIA#952): destination resolution now respects trailing slashes and
existing-directory destinations, single-file sources land as regular files
via a staged extraction and atomic rename, and the function delegates the
SSH tar stream to a shared helper. Adds an explicit lexical
workspace-boundary check on the sandbox-side source — required on the
download side because filesystem policy alone is not a substitute for an
explicit check when crossing the trust boundary in the leak direction.

Signed-off-by: Tinson Lai <tinsonl@nvidia.com>
@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot Bot commented May 12, 2026

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Ubuntu 24.04][Sandbox] openshell sandbox download produces a directory instead of file content + does not reject path-traversal targets

1 participant