NVIDIA / NVIDIA/NemoClaw

debug bundle is staged at a predictable path and published world-readable

Open
#10,195 1 comment 0 reactions 0 assignees View on GitHub
area: cli area: observability area: security
Dominant language
TypeScript
Stars
22.5k
Forks
3.1k
Avg merge
1d 1h
Merged PRs (30d)
715

Description

### What happens

`src/lib/diagnostics/tarball.ts:28` stages the debug bundle at a path other local users can
predict, and lets `tar` create it:

```
const partial = `${output}.partial.${process.pid}`;
```

Nothing creates that file first, so the `spawnSync("tar", ...)` at
`src/lib/diagnostics/tarball.ts:29` chooses its mode and the success path renames it to `output`
at `src/lib/diagnostics/tarball.ts:51`. Two things follow, both observed on `main` (`337c1eed5`)
with the default `umask 022`:

**The bundle is published group- and world-readable** — `bundle mode: 644`. That is the file the
command tells users to attach to a GitHub issue
(`src/lib/diagnostics/debug.ts:514-517`).

**`tar` follows a symlink planted at the staging path.** After planting one and letting `tar`
write, the symlink target began `037 213` — the gzip magic number, i.e. it was overwritten with
tarball content.

Both are reachable because the command's own example writes into a world-writable directory
(`src/commands/debug.ts:88`):

```
nemoclaw debug --output /tmp/nemoclaw-debug.tar.gz
```

There, any local user can read the bundle, or pre-plant a symlink at
`/tmp/nemoclaw-debug.tar.gz.partial.` — a small, enumerable space — to have a file of their
choosing overwritten with the tool's privileges.

### Why this looks like drift

The repository already stages temp files safely: `src/lib/shields/timer.ts:167` uses
`fs.openSync(tempPath, "wx", 0o600)`, `src/lib/share-command.ts:233` uses
`{ mode: 0o600, flag: "wx" }`, and `src/lib/shields/index.ts:393` uses `O_EXCL | O_NOFOLLOW`.

The staging path here arrived in #4506 (`f8c85f37e`), whose stated goal was to leave no partial
tarball and rename atomically. Permissions and predictability were not in that change's scope.

### Environment

macOS 26.5.1 (25F80), Node v26.7.0, `main` at `337c1eed5`.

Contributor guide

Open the contributing guide

Research direction

Start in src/lib/diagnostics/tarball.ts at the partial-path creation and tar invocation, then compare the safe temporary-file patterns in src/lib/shields/timer.ts, src/lib/share-command.ts, and src/lib/shields/index.ts. Check the debug output path in src/lib/diagnostics/debug.ts:514-517 and the example in src/commands/debug.ts:88; done means the bundle is not world-readable and a planted staging symlink cannot redirect tar output.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
70/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.