NVIDIA / NVIDIA/NemoClaw

[Ubuntu 24.04][Sandbox] a refused sandbox download still creates its host destination, unlike the other refusal paths

Open
#11,365 2 comments 0 reactions 0 assignees View on GitHub
area: sandbox area: security platform: ubuntu
Dominant language
TypeScript
Stars
22.5k
Forks
3.1k
Avg merge
1d 43m
Merged PRs (30d)
718

Description

## Description

A sandbox download that is correctly refused still creates its host destination. The refusal itself works: a directory artifact containing a symbolic link is rejected, the symlink is not materialised, and the command exits non-zero. What remains is an empty destination directory on the host that the operator never asked for and that the other refusal paths do not leave behind.

This is the unfinished half of #10636, whose own expected result reads *"It exits nonzero, explains that a symlink is not supported, and does not publish the host destination."* On v0.0.120 the first two clauses hold and the third does not. That issue is closed as completed, so this is filed separately to give the remaining defect an open target rather than to reopen a fix that did land.

A caller that checks for the destination's existence rather than the exit code concludes the download succeeded.

- **Platform scope:** Reproduced on Ubuntu 24.04 x86_64; other platforms not tested for this path.
- **Regression:** No — this is residue from a partially complete fix, not a behaviour that used to work.
- **OpenShell issue:** Yes — the failing surface is the sandbox download command NemoClaw uses for manual state transfer.

## Environment

```text
Device: Ubuntu 24.04 x86_64 workstation
OS: Ubuntu 24.04.4 LTS
Architecture: x86_64
Node.js: v22.23.1
Docker: Docker version 29.5.2
OpenShell CLI: openshell 0.0.106
NemoClaw: nemoclaw v0.0.120
OpenClaw: 2026.7.1
```

## Steps to Reproduce

1. Onboard a sandbox on an isolated gateway port and wait for Ready.
2. Build three sources inside the sandbox so every rejection path can be compared in one run: a directory containing a symbolic link, a FIFO special file, and a plain regular file.
3. Download the directory that contains the symlink to a fresh host destination. Record the exit code and whether the destination exists afterwards.
4. Download the FIFO to a second fresh destination. Record the same two facts.
5. Download a path that does not exist, to a third fresh destination. Record the same two facts.
6. Download the regular file to a fourth destination, as a success control. Record the same two facts.

Capture exit codes directly, not through a pipeline: a pipe reports the exit code of the last command in the pipeline rather than of the download.

## Expected Result

Every refused download leaves no host destination, matching the behaviour of the FIFO and missing-source paths and matching the expected result recorded in #10636. Only the success control creates its destination.

## Actual Result

The refused symlink-directory download creates its destination; the other two refusals do not.

```text
source exit host destination
directory containing a symlink 1 created, an empty directory
FIFO special file 1 not created
path that does not exist 1 not created
regular file (success control) 0 created, correct content
```

The refusal itself is correct and the symlink is not materialised:

```text
Downloading sandbox:{path}/testdir-with-symlink/ into /tmp/nemoclaw-download-XXXX/artifact
Download complete
Refusing to publish symbolic link from staged artifact
'/tmp/nemoclaw-download-XXXX/artifact/member-link'.
```

Note also that `Download complete` is printed before the refusal, so the first line of output reads as success.

## Related

#10636 covered the security half of this behaviour — a directory artifact containing a symlink was published to the host. That half no longer reproduces on v0.0.120: the symlink is refused. This report covers only the destination that is still created on refusal, which is the remaining clause of that issue's expected result.

## Logs

```text
Four-arm run on one host, exit codes captured without a pipeline:

symlink-dir RC=1 destination exists=YES
control fifo RC=1 destination exists=NO
control missing RC=1 destination exists=NO
control regular RC=0 destination exists=YES

Leftover destination after the refused download:

{host dir}/dir-result:
total 8
drwxrwxr-x 2 user user 4096 .
drwxrwxr-x 3 user user 4096 ..
```

Contributor guide

Open the contributing guide

Research direction

Start at the sandbox download command and trace the symlink-directory refusal path, comparing it with the FIFO and missing-source refusal paths described in the report. Reproduce the four-arm comparison on Ubuntu 24.04, capturing exit codes directly. Done means the symlink case exits nonzero, does not publish the artifact, leaves no host destination, and no longer reports completion before refusal.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
cli, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.